gpt4 book ai didi

java - Java 11 上 ShellFolder.getShellFolder() 的替换或使用方式

转载 作者:行者123 更新时间:2023-12-01 17:30:03 27 4
gpt4 key购买 nike

我目前正在使用 ShellFolder.getShellFolder() 来确定特定路径是位于本地驱动器(直接连接到 Windows 计算机)还是远程驱动器。

package com.jthink.songkong.analyse.analyser;

import com.jthink.songkong.analyse.filename.WindowsFileSystem;
import com.jthink.songkong.ui.MainWindow;
import sun.awt.shell.ShellFolder;
import sun.awt.shell.ShellFolderColumnInfo;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;

/**
* Only Windows can load these methods because of reliance on sun classes
*
*/
public class WindowsFilesystemType
{

public static final String WINDOWS_SHELL_ATTRIBUTES = "Attributes";
public static final String WINDOWS_SHELL_ITEM_TYPE = "Item type";
public static final String WINDOWS_SHELL_SIZE = "Size";
/**
* Is Windows NTFS or FAT32
*
* @param newPath
* @return
*/
public static boolean isNTFSOrFAT32(String newPath)
{
Path root = Paths.get(newPath).getRoot();
if (root == null)
{
return false;
}
try
{
FileStore fs = Files.getFileStore(root);
if (fs.type().equals(WindowsFileSystem.NTFS)
|| fs.type().equals(WindowsFileSystem.FAT)
|| fs.type().equals(WindowsFileSystem.FAT32)
|| fs.type().equals(WindowsFileSystem.EX_FAT))
{
return true;
}
return false;
}
catch (IOException ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
return false;
}
}

/**
* Is this a remote drive, only works for Windows because relies on underlying Windows code
*
* @param newPath
*
* @return true if this a remote (Network) drive
*/
public static boolean isRemote(String newPath)
{
try
{
Path root = Paths.get(newPath).getRoot();
ShellFolder shellFolder = ShellFolder.getShellFolder(root.toFile());
ShellFolderColumnInfo[] cols = shellFolder.getFolderColumns();
for (int i = 0; i < cols.length; i++)
{
if (cols[i].getTitle().equals(WINDOWS_SHELL_SIZE)
&& ((String) shellFolder.getFolderColumnValue(i)).startsWith(WindowsShellFileSystemType.NETWORK_DRIVE))
{
return true;
}
else if (cols[i].getTitle().equals(WINDOWS_SHELL_ATTRIBUTES)
&& ((String) shellFolder.getFolderColumnValue(i)).startsWith("\\"))
{
return true;
}
}
}
catch (Exception ex)
{
return false;
}
return false;
}

/**
* Is this a local drive, only works for Windows because relies on underlying Windows code
*
* @param newPath
*
* @return true if this a local drive
*/
public static boolean isLocal(String newPath)
{
try
{
Path root = Paths.get(newPath).getRoot();
ShellFolder shellFolder = ShellFolder.getShellFolder(root.toFile());
ShellFolderColumnInfo[] cols = shellFolder.getFolderColumns();
for (int i = 0; i < cols.length; i++)
{
if (cols[i].getTitle().equals(WINDOWS_SHELL_SIZE)
&& ((String) shellFolder.getFolderColumnValue(i)).startsWith(WindowsShellFileSystemType.LOCAL_DISK))
{
return true;
}
else if (cols[i].getTitle().equals(WINDOWS_SHELL_ATTRIBUTES)
&& ((String) shellFolder.getFolderColumnValue(i)).startsWith("\\"))
{
return false;
}
}
}
catch (Exception ex)
{
return true;
}
return true;
}

}

这在 Java 8 上运行良好

我现在正在转向 Java 11,我正在使用 maven 来编译项目,如果我将编译器的 source 参数从 8 增加到 9(或以上)

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<encoding>UTF-8</encoding>
<compilerVersion>11</compilerVersion>
<source>8</source>
<target>11</target>
<verbose>true</verbose>
<fork>true</fork>
</configuration>
</plugin>

由于模块系统的引入,我编译失败(保持在8并将目标设置为11即可)

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] c:\Code\jthink\SongKong\src\main\java\com\jthink\songkong\analyse\analyser\WindowsFilesystemType.java:[5,14] error: package sun.awt.shell is not visible
(package sun.awt.shell is declared in module java.desktop, which does not export it)
[ERROR] c:\Code\jthink\SongKong\src\main\java\com\jthink\songkong\analyse\analyser\WindowsFilesystemType.java:[6,14] error: package sun.awt.shell is not visible
(package sun.awt.shell is declared in module java.desktop, which does not export it)
[INFO] 2 errors

所以我正在寻找一种替代方法:

  1. 有没有办法将 src 设置为 11 并允许使用某些模块选项进行编译
  2. 我最好能够使用标准 java 库可靠地检测本地驱动器还是远程驱动器

我需要 isLocal() 的原因是我的程序重命名文件,并且用户可以选择将路径长度限制为 259 个字符,因为较长的长度会导致 Windows 资源管理器出现问题,但如果他们正在修改远程驱动器,则不会通常为了执行此要求,我将向问题添加更多详细信息。

例如,如果音乐文件位于 Windows 使用的本地驱动器上,应用程序会重命名它们,那么他们可能希望强制执行该限制。但如果它是网络驱动器,他们可能不会,因为文件通常存储在 Nas 上,并且他们只能通过 Windows 访问文件,因为我的应用程序可以在 Windows 上运行,但不能在 Nas 上运行。

最佳答案

目前标准 Java API 中我需要的功能似乎没有替代品(在 Windows 上识别路径是远程还是本地)。

因此,选择是继续使用将来可能不存在的非公共(public)类,还是编写黑客代码来与将来可能会更改的操作系统命令( net )进行交互。

所以实用的解决方案是我继续使用非公共(public)类,并希望在公共(public)API中添加一些东西,如果不是并且非公共(public)类被删除,那么我将不得不编写代码此时与网络交谈。

为了允许在编译时使用 Maven 访问这个非公共(public)类,我在编译器插件中添加了以下内容

 <compilerArgs>
<arg>--add-exports=java.desktop/sun.awt.shell=ALL-UNNAMED</arg>
</compilerArgs>

例如

   <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<encoding>UTF-8</encoding>
<compilerVersion>11</compilerVersion>
<source>11</source>
<target>11</target>
<verbose>true</verbose>
<fork>true</fork>
<compilerArgs>
<arg>--add-exports=java.desktop/sun.awt.shell=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>

不幸的是,这个解决方案在 java 17 以后失败了,我查看了 sun shell 类,看看是否可以复制它们,sun.awt.shell 没问题,但 Windows 实现依赖于非 java 库

static {
// Load library here
sun.awt.windows.WToolkit.loadLibraries();
}

所以这是一个问题。

创建了以下内容,但仅仅依靠猜测是不可靠的

public class WindowsFilesystemType
{

public static final String WINDOWS_SHELL_ATTRIBUTES = "Attributes";
public static final String WINDOWS_SHELL_SIZE = "Size";

/**
* Is Windows NTFS or FAT32
*
* @param newPath
* @return
*/
public static boolean isNTFSOrFAT32(String newPath)
{
Path root = Paths.get(newPath).getRoot();
if (root == null)
{
return false;
}
try
{
FileStore fs = Files.getFileStore(root);
if (fs.type().equals(WindowsFileSystem.NTFS)
|| fs.type().equals(WindowsFileSystem.FAT)
|| fs.type().equals(WindowsFileSystem.FAT32)
|| fs.type().equals(WindowsFileSystem.EX_FAT))
{
return true;
}
return false;
}
catch (IOException ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
return false;
}
}



/**
* Is this a local drive, only works for Windows machine
*
* TODO unreliable since moved to Java 17
*
* @param newPath
*
* @return true if this a local drive
*/
public static boolean isLocal(String newPath)
{
//If not a windows fs unlikely to be local drive
if(!isNTFSOrFAT32(newPath))
{
return false;
}

//Mapped \\ must be network drive ?
Path root = Paths.get(newPath).getRoot();
if (root.toString().startsWith("\\"))
{
return false;
}

//Low drive letter assume local
root = Paths.get(newPath).getRoot();
if (
(root.toString().equals("C:\\"))||
(root.toString().equals("D:\\"))||
(root.toString().equals("E:\\"))||
(root.toString().equals("F:\\"))
)
{
return true;
}

//Assume network then if higher drive letter
return false;
}
}

关于java - Java 11 上 ShellFolder.getShellFolder() 的替换或使用方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61139440/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com