我找到了Windows特定的解决方案,该解决方案允许仅从名称(例如
\blah或
\blah)导航到任何可访问的计算机节点,而无需枚举Network
shell文件夹或给定节点上的网络共享的任何高级知识。为计算机路径创建ShellFolder
在调试此问题时,我发现
ShellFolder必须为给定的计算机路径创建一个才能导航到它。
Win32ShellFolderManager2.createShellFolder()将调用
File.getCanonicalPath()给定的文件,该文件又将调用
WinNTFileSystem.canonicalize()。最后一次调用在计算机路径上始终失败。经过大量的实验,
ShellFolder通过将File对象包装在绕过的东西中,我能够为任何可访问的计算机路径创建一个
WinNTFileSystem.canonicalize():
public static ShellFolder getComputerNodeFolder(String path) throws FileNotFoundException { File file = new NonCanonicalizingFile(path); if (ShellFolder.isComputerNode(file)) { return new Win32ShellFolderManager2().createShellFolder(file); } else { throw new IllegalArgumentException("Given path is not a computer node."); }}private static final class NonCanonicalizingFile extends File { public NonCanonicalizingFile(String path) { super(path); } @Override public String getCanonicalPath() throws IOException { // Win32ShellFolderManager2.createShellFolder() will call getCanonicalPath() on this file. // base implementation of getCanonicalPath() calls WinNTFileSystem.canonicalize() which fails on // computer nodes (e.g. "\blah"). We skip the canonicalize call, which is safe at this point because we've // confirmed (in approveSelection()) that this file represents a computer node. return getAbsolutePath(); }}
诚然,此解决方案有两个边缘情况(例如可行,
\blah但
\blahsomeShare..没有),理想情况下,OpenJDK应该在其末尾解决这些怪癖。这也是特定于 *** 作系统和特定于实现的解决方案,在Windows上的OpenJDK安装程序之外无法使用。与JFileChooser集成:选项1
与之集成的最简单方法
JFileChooser是覆盖其
approveSelection()方法。这样,用户可以在对话框中输入计算机路径(
\blah或
\blah),然后按Enter键导航到该位置。当给出了不存在或不可访问的路径时,将显示一条警报消息。
与JFileChooser集成:选项2JFileChooser chooser = new JFileChooser() { @Override public void approveSelection() { File selectedFile = getSelectedFile(); if (selectedFile != null && ShellFolder.isComputerNode(selectedFile)) { try { // Resolve path and try to navigate to it setCurrentDirectory(getComputerNodeFolder(selectedFile.getPath())); } catch (FileNotFoundException ex) { // alert user if given computer node cannot be accessed JOptionPane.showMessageDialog(this, "Cannot access " + selectedFile.getPath()); } } else { super.approveSelection(); } }};chooser.showOpenDialog(null);
或者,
FileSystemView可以通过覆盖其
createFileObject(String)方法来检查计算机路径来增强此功能。这允许将计算机路径传递给
JFileChooser(String,FileSystemView)构造函数,并且仍然允许用户导航到可访问的计算机路径。但是,仍然没有一种简单的方法可以在不覆盖的情况下向用户发送有关不可访问的计算机路径的消息
JFileChooser.approveSelection():
public static class ComputerNodeFriendlyFileSystemView extends FileSystemView { private final FileSystemView delegate; public ComputerNodeFriendlyFileSystemView(FileSystemView delegate) { this.delegate = delegate; } @Override public File createFileObject(String path) { File placeholderFile = new File(path); if (ShellFolder.isComputerNode(placeholderFile)) { try { return getComputerNodeFolder(path); } catch (FileNotFoundException ex) { return placeholderFile; } } else { return delegate.createFileObject(path); } } // All pre below simply delegates everything to the "delegate" @Override public File createNewFolder(File containingDir) throws IOException { return delegate.createNewFolder(containingDir); } @Override public boolean isRoot(File f) { return delegate.isRoot(f); } @Override public Boolean isTraversable(File f) { return delegate.isTraversable(f); } @Override public String getSystemDisplayName(File f) { return delegate.getSystemDisplayName(f); } @Override public String getSystemTypeDescription(File f) { return delegate.getSystemTypeDescription(f); } @Override public Icon getSystemIcon(File f) { return delegate.getSystemIcon(f); } @Override public boolean isParent(File folder, File file) { return delegate.isParent(folder, file); } @Override public File getChild(File parent, String fileName) { return delegate.getChild(parent, fileName); } @Override public boolean isFileSystem(File f) { return delegate.isFileSystem(f); } @Override public boolean isHiddenFile(File f) { return delegate.isHiddenFile(f); } @Override public boolean isFileSystemRoot(File dir) { return delegate.isFileSystemRoot(dir); } @Override public boolean isDrive(File dir) { return delegate.isDrive(dir); } @Override public boolean isFloppyDrive(File dir) { return delegate.isFloppyDrive(dir); } @Override public boolean isComputerNode(File dir) { return delegate.isComputerNode(dir); } @Override public File[] getRoots() { return delegate.getRoots(); } @Override public File getHomeDirectory() { return delegate.getHomeDirectory(); } @Override public File getDefaultDirectory() { return delegate.getDefaultDirectory(); } @Override public File createFileObject(File dir, String filename) { return delegate.createFileObject(dir, filename); } @Override public File[] getFiles(File dir, boolean useFileHiding) { return delegate.getFiles(dir, useFileHiding); } @Override public File getParentDirectory(File dir) { return delegate.getParentDirectory(dir); }}
用法:
ComputerNodeFriendlyFileSystemView fsv = new ComputerNodeFriendlyFileSystemView(FileSystemView.getFileSystemView());JFileChooser chooser = new JFileChooser("\blah", fsv);chooser.showOpenDialog(null);
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)