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包的方式來加載文件,通用性更強一些,在前述兩種都不可用的時候,往往還是可用的。