暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

nio使用中的java.nio.file.FileSystemNotFoundException分析析

开发架构二三事 2019-06-26
2997

在使用nio加载文件时,在idea中运行没有问题,但打成jar包后在windows和linux下都有问题:

  1. public static void main(String[] args) throws Exception{

  2. // SpringApplication.run(MarketCollectApplication.class,args);

  3. URI uri = MarketCollectApplication.class.getClassLoader().getResource("conf/sh.txt").toURI();

  4. FileSystem aDefault = FileSystems.getDefault();

  5. System.out.println(aDefault.getClass());

  6. FileSystemProvider provider = FileSystems.getDefault().provider();

  7. System.out.println(provider.getClass());

  8. System.out.println("====================" + uri.getScheme());

  9. List<FileSystemProvider> fileSystemProviders = FileSystemProvider.installedProviders();

  10. fileSystemProviders.forEach(p -> {

  11. System.out.println(p.getClass());

  12. });

  13. Path path = Paths.get(uri);

  14. }

这种情况下在idea中没有问题:

  1. class sun.nio.fs.WindowsFileSystem

  2. class sun.nio.fs.WindowsFileSystemProvider

  3. ====================file

  4. class sun.nio.fs.WindowsFileSystemProvider

  5. class com.sun.nio.zipfs.ZipFileSystemProvider

但是在打成jar包运行时Path path = Paths.get(uri)这一行会抛出异常:

  • windows环境下: 

  • linux环境下: 

究其原因,是FileSystemProvider的使用问题,先看java.nio.file.Paths#get(java.net.URI):

  1. public static Path get(URI uri) {

  2. String scheme = uri.getScheme();

  3. if (scheme == null)

  4. throw new IllegalArgumentException("Missing scheme");


  5. // check for default provider to avoid loading of installed providers

  6. if (scheme.equalsIgnoreCase("file"))

  7. return FileSystems.getDefault().provider().getPath(uri);


  8. // try to find provider

  9. for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {

  10. if (provider.getScheme().equalsIgnoreCase(scheme)) {

  11. return provider.getPath(uri);

  12. }

  13. }


  14. throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");

  15. }

  • uri.getScheme()在idea中是file,在打成jar包后变成了jar。

  • 当前缀以file开头时,会使用FileSystems.getDefault().provider()来处理,这个provider在windows环境下是WindowsFileSystemProvider, 在linux环境下是LinuxFileSystemProvider。

  • FileSystemProvider.installedProviders()对应windows中的WindowsFileSystemProvider和ZipFileSystemProvider,对应linux中的LinuxFileSystemProvider和ZipFileSystemProvider。

  • 当前缀不以file开头时,会使用FileSystemProvider.installedProviders()中与uri.getScheme()匹配的provider来处理,对应的就是ZipFileSystemProvider。

  • ZipFileSystemProvider对应的FileSystem需要自己创建,使用和创建方式参考:https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html

解决办法:在Path path = Paths.get(uri)中进行处理

  1. Path path = null;

  2. try{

  3. path = Paths.get(uri);

  4. }catch (Exception e){

  5. //@see https://stackoverflow.com/questions/25032716/getting-filesystemnotfoundexception-from-zipfilesystemprovider-when-creating-a-p

  6. //@see http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html

  7. FileSystem zipfs = FileSystems.newFileSystem(uri, env);

  8. path = Paths.get(uri);

  9. }

或者使用其他办法加载资源文件:

  1. byte[] data;

  2. try (InputStream in = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json")) {

  3. data = IOUtils.toByteArray(in);

  4. }

参考:https://stackoverflow.com/questions/25032716/getting-filesystemnotfoundexception-from-zipfilesystemprovider-when-creating-a-p


文章转载自开发架构二三事,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论