我当前正在使用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
所以,我正在寻找一种替代方法,或者:
目前看来,我在标准Java API中所需的功能似乎还无法替代(在Windows上标识路径是远程还是本地,这是确定的。
因此,选择是继续使用将来可能不存在的非公共类,还是编写hacky代码与将来可能会更改的操作系统命令(net
)进行交互。
因此,务实的解决方案是让我继续使用非公共类,并希望将某些内容添加到公共api,如果没有,并且非公共类被删除,那么我将不得不编写代码来进行讨论净赚钱。
为了允许使用Maven在编译时访问此非公共类,我在编译器插件中添加了以下内容:>
<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>