草庐IT

java - 如何导航到 JFileChooser 中的网络主机?

coder 2023-09-02 原文

问题

我有一个 JFileChooser,我需要以编程方式将其 currentDirectory 设置为包含多个 SMB 共享的网络主机(例如 \\blah)。从技术上讲,这不是“目录”,而是代表可用共享列表的 shell 文件夹。

  • JFileChooser 可以毫无问题地导航到特定的共享(例如 \\blah\someShare)但不能处理主机“目录”本身(例如 \\blah).

  • 用户可以通过“网络”shell 文件夹导航到 JFileChooser 中的此类“目录”,或者通过查找特定共享并导航到其父目录。调试显示该目录在后台表示为 Win32ShellFolder2。到目前为止,我所有以编程方式设置 currentDirectory 的尝试都失败了。

  • new File("\\\\blah") 可以创建,但从 Java 的角度来看实际上并不存在。

失败的解决方案尝试

  • chooser.setCurrentDirectory(new File("\\\\blah"));

    失败,因为 JFileChooser 检查给定目录是否存在,并且 new File("\\\\blah").exists() 返回 false。

  • File dir = new File("\\\\blah").getCanonicalFile();

    异常失败:

      java.io.IOException: Invalid argument
      at java.io.WinNTFileSystem.canonicalize0(Native Method)
      at java.io.WinNTFileSystem.canonicalize(WinNTFileSystem.java:428)
      at java.io.File.getCanonicalPath(File.java:618)
      at java.io.File.getCanonicalFile(File.java:643)
    
  • File dir = ShellFolder.getShellFolder(new File("\\\\blah"));

    异常失败:

      java.io.FileNotFoundException
      at sun.awt.shell.ShellFolder.getShellFolder(ShellFolder.java:247)
    
  • File dir = new Win32ShellFolderManager2().createShellFolder(new File("\\\\blah"));

    异常失败:

      java.io.FileNotFoundException: File \\blah not found
      at sun.awt.shell.Win32ShellFolderManager2.createShellFolder(Win32ShellFolderManager2.java:80)
      at sun.awt.shell.Win32ShellFolderManager2.createShellFolder(Win32ShellFolderManager2.java:64)
    
  • 路径 dir = Paths.get("\\\\blah");

    异常失败:

    java.nio.file.InvalidPathException: UNC path is missing sharename: \\blah
    at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:118)
    at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
    at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
    at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
    at java.nio.file.Paths.get(Paths.java:84)
    

最佳答案

曾几何时,我遇到过这样的任务,我可以说这真的很烦人。一开始听起来很容易,但是当你开始挖掘和尝试时,越来越多的问题出现了。我想谈谈我的旅程。
据我了解,这里的问题是 \\ComputerName\ 不是文件系统中的真实位置。它是一个抽象层,其内容取决于您的身份验证凭据。而且它仅适用于 Windows 机器,因此去那里会破坏 Java 的系统独立性法则。总结一下,File 对象无法指向任何东西。 您可以使用 Samba 库 jcifs但在它们的实现中,类 SmbFile 需要用户身份验证,并且与 java File 类不兼容。所以你不能将它与 jFileChooser 一起使用。可悲的是,他们对更改它不感兴趣,您可以阅读 here .
我自己尝试开发一个文件包装器,它充当 FileSmbFile 类的混合体。但我放弃了,因为它给我带来了噩梦。
然后我有了写一个简单的 Dialog 的想法,列出以前用 jcifs 扫描的网络共享,让用户选择其中一个。然后应该显示一个带有所选共享的 jFileChooser

当我实现这个想法时,整个问题的 super 简单解决方案让我感到震惊。

由于指向 \\ComputerName\ShareName 并单击 更高一级 按钮绝对没有问题,因此必须可以重现此步骤。它是。实际上,在查看 jFileChooser 的底层时,我了解到像 MyComputerNetwork 这样的地方是 ShellFolders,它们是特殊情况File 对象。但是这些 Shell 文件夹是 protected ,不是 Java API 的一部分。
所以我不能直接实例化这些。但是我可以访问 FileSystemView 来处理文件系统上的系统相关 View ,例如为特殊位置创建这些 Shell 文件夹。
这么长的文字简短的回答。如果您知道一个共享名,请为该共享名创建一个文件。然后使用 FileSystemView 获取其父文件。瞧,你可以使用生成的 File 对象,它扩展了一个 ShellFolder jFileChooser.

File f = new File("\\\\ComputerName\\ShareFolder");
FileSystemView fsv = FileSystemView.getFileSystemView();
f = fsv.getParentDirectory(f);
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(f);

最后一点:此解决方案不会要求您提供登录信息。因此,必须先在 Windows 中访问这些共享,然后才能在此处使用它们。

编辑:抱歉文本太长。除夕夜,我喝醉了。现在我想补充一点,我发现了相反的情况。

FileSystemView fsv = FileSystemView.getFileSystemView();
File Desktop = fsv.getRoots()[0];

在 Windows 系统上,这应该会为您提供桌面文件夹。如果您在此处列出所有文件:

for(File file : Desktop.listFiles())
    System.out.println(file.getName());

您会注意到一些具有奇怪名称的条目:

::{20D04FE0-3AEA-1069-A2D8-08002B30309D}   // My Computer
::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}   // Network
::{031E4825-7B94-4DC3-B131-E946B44C8DD5}   // User Directory

我不知道这些代码是否适用于所有 Windows 版本,但它们似乎适用于 Windows7。因此,您可以使用它来获取 Network Shell 文件夹,然后获取具有共享的计算机。

File Network = fsv.getChild(Desktop, "::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}");
File Host = fsv.getChild(Network, "COMPUTERNAME");  // Must be in Capital Letters

这里的问题是这将花费大约 10 秒,因为会扫描网络文件夹中的内容。

关于java - 如何导航到 JFileChooser 中的网络主机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33640908/

有关java - 如何导航到 JFileChooser 中的网络主机?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  6. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  7. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  10. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

随机推荐