2012-05-21 2 views
10

Я пытаюсь найти способ обнаружить, когда флешка подключена к моему компьютеру. До сих пор решение, которое я нашел, состояло в опросе FileSystem#getFileStores для внесения изменений. Это действительно говорит мне, когда флэш-диск был вставлен, но насколько я могу судить, нет способа найти место для него. FileStore#type и FileStore#name обе кажутся крайне ненадежными, так как их возвращаемое значение является специфичным для реализации, но они являются единственными методами, которые могут возвращать любую релевантную информацию, которая может помочь найти каталог для FileStore.Найти каталог для 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 

ответ

10

Вот временная работа вокруг, пока лучше не будет найдено решение:

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-диске нет компакт-диска, при попытке получить для него исключение выдается. Это может произойти до того, как вы перейдете к каждому корню.

+0

Действительно ли это работает для Windows? Похоже, что он пропустит диск, который я смонтирую на C: \ Data. Весь смысл использования этого нового API заключается в том, что он обещал найти мне все точки монтирования, а не только корни. – Trejkaz

+0

Кроме того,/media? Вы не имеете в виду/mnt? – Trejkaz

+0

@ Трейказ Я не знал, что вы можете это сделать. Он работает в стандартном случае, когда диски монтируются в виде букв. По крайней мере, на Ubuntu, все по умолчанию установлено/media. Вы также можете использовать/etc/mtab для более гибкой работы в Linux-системах (я не очень сильно использую Windows, поэтому я не знаю другого). – Jeffrey

0

Я действительно не исследовал эту область Java, но я нашел this, который, кажется, связаны между собой. Он использует File.listRoots()

Здесь также есть ряд связанных вопросов.

+1

'File.listRoots' будет работать только для Windows, и я рассмотрел эти вопросы безрезультатно.Они все спросили, прежде чем nio2 выйдет – Jeffrey

+0

Ahh> _> Я буду продолжать искать и редактировать этот ответ, если найду что-нибудь –

+0

@Jeffrey это даже не будет работать для Windows, потому что в Windows вы можете иметь диски, не установленные на диске письмо. – Trejkaz

4

Это то, что я сделал. Это ограничивается 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); 
      } 
     } 
    } 
} 
+2

Примечание для других: поскольку частные поля могут быть изменены без предварительного уведомления, это будет работать только для текущей версии Java, пока не будет подтверждено иное. – Jeffrey

+1

Yup. Определенно добавьте единичные тесты для обнаружения изменения поведения, если вы используете это. – Trejkaz

-1

Самый простой способ использования Files.getFileStore(Paths.get("/home/...")

+2

Это обратное тому, что я ищу. Вы берете «Путь» и получаете «FileStore», но я хочу взять «FileStore» и получить «Путь». – Jeffrey

Смежные вопросы