Вопрос по java – Найти каталог для FileStore

11

Я пытаюсь найти способ определить, когда флэш-накопитель подключен к моему компьютеру. Пока что я нашел решение опросить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

Ваш Ответ

3   ответа
0

этот, который, кажется, связан. Оно используетFile.listRoots()

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

Error: User Rate Limit Exceeded
File.listRootsError: User Rate Limit Exceeded Jeffrey
Error: User Rate Limit Exceeded
4

что я в итоге сделал. Это ограничено Windows + UNIX, но избегает использования внешних инструментов или дополнительных библиотечных вызовов. Он крадет информацию, которую Java уже имеет вFileStore объекты

LinuxFileStore определенно расширяетсяUnixFileStoreтак будет работать. То же самое для Соляриса. Поскольку 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);
            }
        }
    }
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Jeffrey
Error: User Rate Limit Exceeded
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, потому что, если в приводе компакт-дисков нет компакт-диска, при попытке извлечьFileStore для этого. Это может произойти до того, как вы выполните итерацию по каждому корню.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Jeffrey
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы