如何读取jar包中的文件
1.getResource
//当前类文件为根目录,取其子目录x下的y文件 Main.class.getResource("x/y") //当前类文件的根目录为根目录,取其子目录x下的y文件 Main.class.getResource("/x/y")
上面的解释有点拗口,其实就是路径不以斜线开头,表示从当前class文件为根目录,然后找文件,路径以斜线开头,则从当前class的文件的根目录,比如当前class如果有包限定的话,那就是从包的最顶层,作为根目录,来加载文件。
2.getResourceAsStream
private static String readFile(String file) throws IOException { InputStream input = null; BufferedInputStream bis = null; StringBuilder sb = new StringBuilder(); try { input = Main.class.getResourceAsStream(file); bis = new BufferedInputStream(input); byte[] temp = new byte[1024]; int len; while ((len = bis.read(temp)) != -1) { sb.append(new String(temp, 0, len, StandardCharsets.UTF_8)); } } finally { if (bis != null) { bis.close(); } if (input != null) { input.close(); } } return sb.toString(); }
这里要注意的是,上面的写法中是Main.class.getResourceAsStream(file),即从当前类的范围内去找file,
如果写成Main.class.getClassLoader().getResourceAsStream(file),则有可能找不到文件,因为已经从加载器的可见范围去找文件了。
3.JarFile
private static String readFile(String file) throws IOException { String jarPath = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(); InputStream input = null; BufferedInputStream bis = null; StringBuilder sb = new StringBuilder(); try { JarFile jarFile = new JarFile(jarPath); ZipEntry zipEntry = jarFile.getEntry(file); //can not find the deserved file if (zipEntry == null) { logger.info("Can not find file {} in {}", file, jarPath); return null; } input = jarFile.getInputStream(zipEntry); bis = new BufferedInputStream(input); byte[] temp = new byte[1024]; int len; while ((len = bis.read(temp)) != -1) { sb.append(new String(temp, 0, len, StandardCharsets.UTF_8)); } } catch (IOException ex) { logger.error("Fail to read file {}:{}", file, ex.getMessage()); logger.error("Exception:", ex); throw new RuntimeException("A valid file " + file + " is unavailable."); } finally { if (bis != null) { bis.close(); } if (input != null) { input.close(); } } return sb.toString(); }
上面这种方式,通过jar包的方式来加载文件,通用性更强一些,在前述两种都不可用的时候,往往还是可用的。