Find the directory for a FileStore

走远了吗. 提交于 2019-11-29 03:56:47
Jeffrey

Here's a temporary work around until a better solution is found:

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;
}

As far as I know, this solution will only work for Windows and Linux systems.

You have to catch the IOException in the Windows loop because if there is no CD in the CD drive an exception is thrown when you try to retrieve the FileStore for it. This might happen before you iterate over every root.

This is what I have ended up doing. This is limited to Windows + UNIX but avoids using external tools or additional library calls. It steals the information Java already has in the FileStore objects

LinuxFileStore definitely extends UnixFileStore, so it will work. Same deal for Solaris. Since Mac OS X is UNIX, it probably works there but I'm not sure because I couldn't see its subclass in any place I was looking.

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);
            }
        }
    }
}
Perry Monschau

I've not really explored this area of java, but I found this, which seems to be related. It uses File.listRoots()

There also seems to be a number of related questions linked there too.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!