我正试图找到一种方法来检测闪存驱动器何时插入我的计算机。到目前为止,我找到的解决方案是进行民意调查 FileSystem#getFileStores
为了改变。这确实告诉我何时插入了闪存驱动器,但据我所知,没有办法检索它的位置。 FileStore#type
和 FileStore#name
两者看起来都非常不可靠,因为它们的返回值是特定于实现的,但它们似乎是唯一可能返回任何可能有助于查找目录的相关信息的方法。 FileStore
。
考虑到这一点,以下代码:
public class Test {
public static void main(String[] args) throws IOException {
for (FileStore store : FileSystems.getDefault().getFileStores()) {
System.out.println(store);
System.out.println("\t" + store.name());
System.out.println("\t" + store.type());
System.out.println();
}
}
}
给我这个输出:
/ (/dev/sda5)
/dev/sda5
ext4
/* snip */
/media/TI103426W0D (/dev/sda2)
/dev/sda2
fuseblk
/media/flashdrive (/dev/sdb1)
/dev/sdb1
vfat
事实证明, FileStore#type
返回驱动器的格式和 FileStore#name
返回驱动器的设备文件的位置。据我所知,唯一具有驱动器位置的方法是 toString
方法,但从中提取路径名称似乎很危险,因为我不确定该特定解决方案在其他操作系统和未来版本的Java上的表现如何。
有没有我在这里缺少的东西,或者纯粹用Java是不可能的?
系统信息:
$ java -version
java version "1.7.0_03"
OpenJDK Runtime Environment (IcedTea7 2.1.1pre) (7~u3-2.1.1~pre1-1ubuntu2)
OpenJDK Client VM (build 22.0-b10, mixed mode, sharing)
$ uname -a
Linux jeffrey-pc 3.2.0-24-generic-pae #37-Ubuntu SMP Wed Apr 25 10:47:59 UTC 2012 i686 athlon i386 GNU/Linux
这是一个临时工作,直到找到更好的解决方案:
public Path getRootPath(FileStore fs) throws IOException {
Path media = Paths.get("/media");
if (media.isAbsolute() && Files.exists(media)) { // Linux
try (DirectoryStream<Path> stream = Files.newDirectoryStream(media)) {
for (Path p : stream) {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
}
}
} else { // Windows
IOException ex = null;
for (Path p : FileSystems.getDefault().getRootDirectories()) {
try {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
} catch (IOException e) {
ex = e;
}
}
if (ex != null) {
throw ex;
}
}
return null;
}
据我所知,此解决方案仅适用于Windows和Linux系统。
你必须赶上 IOException
在Windows循环中,因为如果CD驱动器中没有CD,则在尝试检索时会抛出异常 FileStore
为了它。在迭代每个根之前可能会发生这种情况。
这是一个临时工作,直到找到更好的解决方案:
public Path getRootPath(FileStore fs) throws IOException {
Path media = Paths.get("/media");
if (media.isAbsolute() && Files.exists(media)) { // Linux
try (DirectoryStream<Path> stream = Files.newDirectoryStream(media)) {
for (Path p : stream) {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
}
}
} else { // Windows
IOException ex = null;
for (Path p : FileSystems.getDefault().getRootDirectories()) {
try {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
} catch (IOException e) {
ex = e;
}
}
if (ex != null) {
throw ex;
}
}
return null;
}
据我所知,此解决方案仅适用于Windows和Linux系统。
你必须赶上 IOException
在Windows循环中,因为如果CD驱动器中没有CD,则在尝试检索时会抛出异常 FileStore
为了它。在迭代每个根之前可能会发生这种情况。
这就是我最终做的事情。这仅限于Windows + UNIX,但避免使用外部工具或其他库调用。它窃取了Java中已有的信息 FileStore
对象
LinuxFileStore
绝对延伸 UnixFileStore
,所以它会起作用。同样的Solaris交易。由于Mac OS X是UNIX,它可能在那里工作,但我不确定,因为我无法在我正在寻找的任何地方看到它的子类。
public class FileStoreHacks {
/**
* Stores the known hacks.
*/
private static final Map<Class<? extends FileStore>, Hacks> hacksMap;
static {
ImmutableMap.Builder<Class<? extends FileStore>, Hacks> builder =
ImmutableMap.builder();
try {
Class<? extends FileStore> fileStoreClass =
Class.forName("sun.nio.fs.WindowsFileStore")
.asSubclass(FileStore.class);
builder.put(fileStoreClass, new WindowsFileStoreHacks(fileStoreClass));
} catch (ClassNotFoundException e) {
// Probably not running on Windows.
}
try {
Class<? extends FileStore> fileStoreClass =
Class.forName("sun.nio.fs.UnixFileStore")
.asSubclass(FileStore.class);
builder.put(fileStoreClass, new UnixFileStoreHacks(fileStoreClass));
} catch (ClassNotFoundException e) {
// Probably not running on UNIX.
}
hacksMap = builder.build();
}
private FileStoreHacks() {
}
/**
* Gets the path from a file store. For some reason, NIO2 only has a method
* to go in the other direction.
*
* @param store the file store.
* @return the path.
*/
public static Path getPath(FileStore store) {
Hacks hacks = hacksMap.get(store.getClass());
if (hacks == null) {
return null;
} else {
return hacks.getPath(store);
}
}
private static interface Hacks {
Path getPath(FileStore store);
}
private static class WindowsFileStoreHacks implements Hacks {
private final Field field;
public WindowsFileStoreHacks(Class<?> fileStoreClass) {
try {
field = fileStoreClass.getDeclaredField("root");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("file field not found", e);
}
}
@Override
public Path getPath(FileStore store) {
try {
String root = (String) field.get(store);
return FileSystems.getDefault().getPath(root);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Denied access", e);
}
}
}
private static class UnixFileStoreHacks implements Hacks {
private final Field field;
private UnixFileStoreHacks(Class<?> fileStoreClass) {
try {
field = fileStoreClass.getDeclaredField("file");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("file field not found", e);
}
}
@Override
public Path getPath(FileStore store) {
try {
return (Path) field.get(store);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Denied access", e);
}
}
}
}
我没有真正探索过java的这个领域,但我发现了 这个,这似乎是相关的。它用 File.listRoots()
似乎也有一些相关问题也存在。