2012-05-21 8 views
10

フラッシュドライブがコンピュータに接続されていることを検出する方法を見つけようとしています。これまでのところ、私が見つけた解決策は、変更をFileSystem#getFileStoresにポーリングすることでした。これは実際にフラッシュドライブが挿入されたときに私に教えてくれるが、私が知る限り、その場所を検索する方法はない。 FileStore#typeFileStore#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#nameのフォーマットを返しFileStore#typeはの場所を返します。ドライブのデバイスファイル。私が知る限り、ドライブの場所を持つ唯一の方法は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システムのために動作します。

WindowsループでIOExceptionをキャッチする必要があります.CDドライブにCDがない場合は、FileStoreを取得しようとすると例外がスローされるためです。これは、すべてのルートを反復処理する前に発生する可能性があります。

+0

これはWindowsで本当に機能しますか?それは私がC:\ Dataにマウントするドライブが欠けているようです。私がこの新しいAPIを使用している点全体は、ルートだけでなく、すべてのマウントポイントを見つけることを約束したということです。 – Trejkaz

+0

また、/ media?あなたは/ mntを意味しないのですか? – Trejkaz

+0

@Trejkaz私はあなたがそれをすることができたか分からなかった。これは、ドライブが文字としてマウントされる標準的なケースで機能します。少なくともUbuntuでは、/ mediaにデフォルトでマウントされます。また、/ etc/mtabを使用して、Linuxシステム上でより柔軟な作業をすることもできます(私は実際にWindowsをそれほど使用しないので、別のものを知りません)。 – Jeffrey

0

私は本当にジャワのこの地域を探検していませんでしたが、私は関連があると思われる、thisを発見しました。それは使用するFile.listRoots()

そこにも関連する多くの質問があるようです。

+1

'File.listRoots'はWindowsのみのために働くだろう、と私は無駄にこれらの質問を検討してきました。彼らはすべてnio2が出てくる前に尋ねられました – Jeffrey

+0

Ahh> _>何かを見つけたらこの答えを見て編集します。 –

+0

@Jeffrey Windowsでは動作しません.Windowsではドライブをドライブにマウントできないためです文字。 – Trejkaz

4

これは私がやったことです。これはWindows + UNIXに限られていますが、外部ツールや追加のライブラリ呼び出しの使用は避けてください。それは既にJavaが持っている情報を盗みますオブジェクト

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

である。あなたがこれを使うならば、振る舞いの変化を検出するためのユニットテストを確実に追加してください。 – Trejkaz

-1

最も簡単な方法の使用 Files.getFileStore(Paths.get("/home/...")

+2

これは私が探しているものの逆です。あなたは 'Path'を取得して' FileStore'を取得していますが、 'FileStore'を取得して' Path'を取得したいと思います。 – Jeffrey

関連する問題