如何在 Java 9+ 中使用 JFileChooser 显示网络共享?

     2023-02-18     168

关键词:

【中文标题】如何在 Java 9+ 中使用 JFileChooser 显示网络共享?【英文标题】:How to display network shares using JFileChooser in Java 9+? 【发布时间】:2019-04-10 09:42:44 【问题描述】:

我们软件的用户需要在我们的 Java swing 应用程序中浏览 Windows 10 上的网络共享,但是 swing 的 JFileChooser 默认不具备此功能。

在此相关帖子中 How to navigate to a network host in JFileChooser? 一个不错的解决方案是使用 ShellFolder(sun 私有 API)来设置 JFileChooser 的当前目录,过去几年我们一直在使用这种方法并进行了一些修改,没有任何问题。

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException 
  final File file = new NonCanonicalizingFile( folder.getPath() );
  if( isNetworkShareFolder( file ) )  // assume Win32ShellFolderManager2 will be present
     try 
        // JRE-13272 -PRIVATE API that must eventually be swapped for Java 9 alternative
        // Using reflection because Win32ShellFolderManager2 may not exist in rt.jar on Linux build server
        final Class win32ShellMgr = Class.forName( "sun.awt.shell.Win32ShellFolderManager2" );
        // get static creation method from class, execute it
        final Method cfMethod = win32ShellMgr.getMethod( "createShellFolder", File.class );
        return (ShellFolder) cfMethod.invoke( win32ShellMgr.newInstance(), file );
      catch( final Exception xx ) 
        xx.printStackTrace();
     
  
  throw new IllegalArgumentException( "Given path is not a Windows network share folder." ); 
 

但是,我们正在迁移到 Java 11,并且在 Java 9 中,私有 API 被封装,我们被要求不再使用它们。不用担心,OpenJDK 中的替换 API 已进入 FileSystemView,在 swing filechooser 的子包中。

sun.awt.shell.ShellFolder.isComputerNode( 文件 ) -> javax.swing.filechooser.FileSystemView.getFileSystemView().isComputerNode( 文件 ) sun.awt.shell.ShellFolder.getShellFolder( 文件 ) -> javax.swing .filechooser.FileSystemView.getFileSystemView().getLinkLocation(文件)

所以之前的代码现在变成了

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException 
   final File file = new NonCanonicalizingFile( folder.getPath() );
   if( isNetworkShareFolder( file ) )  
      try 
         return FileSystemView.getFileSystemView().getLinkLocation( file );
       catch( final Exception xx ) 
         xx.printStackTrace();
      
   
   throw new IllegalArgumentException( "Given path is not a Windows network share folder." );


public static boolean isNetworkShareFolder( final File folder ) 
   return FileSystemView.getFileSystemView().isComputerNode( new NonCanonicalizingFile( folder.getPath() ) );

这会很棒,但不幸的是 getShellFolder() 和 getLinkLocation() 在 Java 11 下都会抛出一个在 Java 8 下没有抛出的异常。

java.nio.file.InvalidPathException:UNC 路径缺少共享名: \100.212.51.37 在 java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:118) 在 java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77) 在 java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92) 在 java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:229) 在 java.base/java.nio.file.Path.of(Path.java:147) 在 java.base/java.nio.file.Paths.get(Paths.java:69) 在 java.desktop/sun.awt.shell.ShellFolder.getShellFolder(ShellFolder.java:247) 在 java.desktop/javax.swing.filechooser.FileSystemView.getLinkLocation(FileSystemView.java:641)

它现在似乎认为 UNC 路径无效,除非它具有实际的共享名称,即“\\100.212.51.37\”是无效的,但“\\100.212.51.37\myShare”是可以的。

现在,如果您获得 UNC 路径“\\100.212.51.37\myShare”的 shell 文件夹,然后 getParent(),您将获得我们最初想要的“\\100.212.51.37\”的 shell 文件夹.不幸的是,这种解决方法对于我们的客户来说是不可行的,因为存在先有鸡还是先有蛋的问题 - 用户通常还不知道任何实际的共享名称,这是他们首先想要浏览的内容!

Argh - 这在 Java 8 下运行良好,但在 Java 11 中,即使您打破封装以使用原始的 ShellFolder 私有 API,使用

'--add-exports', 'java.desktop/sun.awt.shell=ALL-UNNAMED'

这没有帮助,因为以前的解决方案现在在 Java 11 (9+) 下抛出相同的异常。

我们在 *** 上看到的另一个解决方案是使用 JCIFS 中的 SmbFile 类,但由于安全限制,我们很难使用 3rd 方代码。特别是如果它没有针对 Java 11 JPMS 进行更新,并且不使用私有 API。

有趣的是,JavaFX 中的 DirectoryChooser 没有这个问题。如果用户手动输入网络主机,它会很乐意显示该主机的所有共享名称。如果必须,我们将采用这种方式,但处理 FX Stage 与 Swing 应用程序之间的模态是丑陋的,并且可能需要大量工作。

仍然希望有一个更简单的解决方法,让 JFileChooser 在 Java 11(Java 9+)中显示网络共享!也许有人知道 FX DirectoryChooser 使用的技巧,它可以应用于 JFileChooser?

【问题讨论】:

【参考方案1】:

仍在寻找更好的解决方案,但与此同时,由于网络共享,我们决定在 Java 11 中将 JFileChooser 替换为 JavaFX 的 DirectoryChooser。 DirectoryChooser 非常乐意允许用户输入根网络共享,它将显示所有网络共享名称。启动 DirectoryChooser 的 UI 仍然是一个摆动 UI,但我们没有遇到模式或焦点问题,至少在 Windows 10 下是这样。

但是,除了必须仔细管理 JavaFX Platform.runLater() 和 SwingUtilities.invokeLater() 之间的线程之外,我们还有很多缺点

1) DirectoryChooser 不允许多选。 JFileChooser 可以。

2) DirectoryChooser 只允许选择目录而不是文件。 耸耸肩 谁需要允许选择目录或文件?愚蠢的。只有这正是我们的客户在不止一种情况下需要做的事情。 JFileChooser 支持这一点。

3) DirectoryChooser 不允许输入无效路径。嗯?是的,事实上,我们的一位客户有一个特定的要求,即输入一个尚不存在的路径(预配置),但只要将任务驱动器插入网络就会立即出现。 JFileChooser 允许这样做,并且可以非常方便地导航到您需要的根目录,然后只需键入路径的最后一部分(目录或共享名称)。

4) DirectoryChooser 与应用程序样式不匹配。在 JavaFX 中,您可以在场景的根节点上设置自己的 CSS,但不能在 DirectoryChooser 上设置。看起来 DirectoryChooser 实际上是在调用本机文件选择器,它应该使用系统配色方案。不幸的是,对于我们在夜间使用“暗模式”操作的飞行员来说,Windows 10 文件资源管理器直到版本 1809 才尊重“暗模式”设置,而我们的客户几乎没有。

【讨论】:

使用 JAVA 9 中的模块在 JAVA 中创建库

...我还能够在Eclipse中使用Maven创建一个模块。现在我不确定如何从中创建一个JAR。或者对于这样的 查看详情

如何在 Eclipse 中获取 Javafx 9?

】如何在Eclipse中获取Javafx9?【英文标题】:HowtogetJavafx9inEclipse?【发布时间】:2018-09-0320:34:24【问题描述】:我在Eclipse中创建了一个Java9项目,生成了一个module-info.java并添加了一些测试依赖项,一切正常。但如果我添加requiresjav... 查看详情

在java中,如何使用javascript判断一个字符串是不是类似于电话号码?

/* *用途:检查输入手机号码是否正确输入:s:字符串返回:如果通过验证返回true,否则返回false */ functioncheckMobile(s) varregu=/^[1][0-9][0-9]9$/; varre=newRegExp(regu); if(re.test(s)) returntrue; else returnfalse; 参考技术A有个东西叫正则表达式去看... 查看详情

如何在我的java项目中使用两个版本的jar

】如何在我的java项目中使用两个版本的jar【英文标题】:Howtousetwoversionsofjarinmyjavaproject【发布时间】:2013-10-2401:42:08【问题描述】:在我的java项目中,我需要使用依赖于lucene-3.6.2的neo4j-1.9.3和ElasticSearch取决于lucene-4.4.0。我知道... 查看详情

如何在 chart.js 2.9.3 中使用主要刻度线?

】如何在chart.js2.9.3中使用主要刻度线?【英文标题】:Howtousemajortickmarksinchart.js2.9.3?【发布时间】:2020-08-3101:23:43【问题描述】:我使用最新的Chart.js2.9.3。我尝试了以下带有主要刻度的代码:varctx=document.getElementById(\'chart\').getCo... 查看详情

如何在java中提取网页文本内容? [关闭]

】如何在java中提取网页文本内容?[关闭]【英文标题】:howtoextractwebpagetextualcontentinjava?[closed]【发布时间】:2011-03-0311:21:02【问题描述】:我正在寻找一种使用jdk或其他库从网页(最初是html)中提取文本的方法。请帮忙谢谢【... 查看详情

如何在 PostgreSQL 9.1 中使用 pgFouine?

】如何在PostgreSQL9.1中使用pgFouine?【英文标题】:HowtousepgFouinewithPostgreSQL9.1?【发布时间】:2012-05-1811:34:33【问题描述】:使用pgFouine1.2、PostgreSQL9.1.3。postgresql.conf设置:log_min_duration_statement=0log_duration=onlog_line_prefix=\'%t[%p]:[% 查看详情

java示例代码_在Java应用程序中使用Microsoft PKCS#9 SignerInfo属性

java示例代码_在Java应用程序中使用Microsoft PKCS#9 SignerInfo属性 查看详情

如何使用照片框架在 iOS 9 中获取图像元数据

】如何使用照片框架在iOS9中获取图像元数据【英文标题】:HowtogetimagemetadatainiOS9usingPhotosFramework【发布时间】:2016-07-0308:16:46【问题描述】:我想在Swift中使用UIImagePickerController显示图像元数据。其中图像是从图库中选择的,并... 查看详情

如何在 Xcode 9 中使用 Xcode 服务器?我们是不是需要始终打开 Xcode 9?

】如何在Xcode9中使用Xcode服务器?我们是不是需要始终打开Xcode9?【英文标题】:HowtoworkwithXcodeserverinXcode9?DoweneedtohaveXcode9openalways?如何在Xcode9中使用Xcode服务器?我们是否需要始终打开Xcode9?【发布时间】:2017-07-1707:21:53【问题... 查看详情

如何在 kafka 0.9.0 中使用多线程消费者?

】如何在kafka0.9.0中使用多线程消费者?【英文标题】:Howtousemulti-threadconsumerinkafka0.9.0?【发布时间】:2016-07-1609:38:50【问题描述】:kafka的文档给出了一个方法,描述如下:每个线程一个消费者:一个简单的选择是为每个线程提... 查看详情

如何在 iOS 9 中使用新的 San Francisco 字体?

】如何在iOS9中使用新的SanFrancisco字体?【英文标题】:HowtousenewSanFranciscofontiniOS9?【发布时间】:2015-09-3021:52:14【问题描述】:在iOS9之前我们使用fontWithName的UIFont引用字体:[UIFontfontWithName:@"HelveticaNeue"size:18]现在我们正在迁移到i... 查看详情

如何在 9.414 版本中使用 executemany 忽略 postgres 中的重复项?

】如何在9.414版本中使用executemany忽略postgres中的重复项?【英文标题】:howtoignoreduplicatesinpostgreswithexecutemanyinversion9.414?【发布时间】:2018-11-0508:19:14【问题描述】:我正在使用postgres9.414。我知道插入命令中的“冲突”命令,但... 查看详情

如何在 Azure 应用服务 java11 tomcat 9 堆栈中配置 java ENV 变量

】如何在Azure应用服务java11tomcat9堆栈中配置javaENV变量【英文标题】:howtoconfigurejavaENVvariableinAzureAppServicesjava11tomcat9stack【发布时间】:2021-07-1407:41:23【问题描述】:我有一个java-11tomcat-9堆栈应用服务。我想为此设置xxx(最大堆内... 查看详情

在 CMD 批处理脚本中调用标签时如何使用超过 9 个参数?

】在CMD批处理脚本中调用标签时如何使用超过9个参数?【英文标题】:Howdoyouutilizemorethan9argumentswhencallingalabelinaCMDbatch-script?【发布时间】:2012-01-0919:55:32【问题描述】:我想知道在调用标签时如何在批处理脚本中调用超过9个参... 查看详情

没有关于在 Android 项目中使用 Java 9 方法的警告

】没有关于在Android项目中使用Java9方法的警告【英文标题】:NowarningaboutusingJava9methodsinAndroidprojects【发布时间】:2021-12-2220:17:56【问题描述】:我在针对SDK31的Android项目中使用了java.time.Duration.toMinutesPart()方法,从IDE/编译器的角... 查看详情

如何在 VueJS 3 中使用 9.0.1 Firebase 方法

】如何在VueJS3中使用9.0.1Firebase方法【英文标题】:Howtouse9.0.1FirebasemethodswithVueJS3【发布时间】:2021-11-0113:02:33【问题描述】:我是Vue的新手,这是我要学习的第二个教程,它将firebase后端与Vue集成。但是本教程使用的是Vue2和旧版... 查看详情

如何在c#9中使用record类型?(代码片段)

原文链接:https://www.infoworld.com/article/3607372/how-to-work-with-record-types-in-csharp-9.html原文标题:HowtoworkwithrecordtypesinC#9翻译:沙漠尽头的狼(谷歌翻译加持)利用C#9中的record类型来构建不可变类型和线程安全对象。不可变性 查看详情