一般获取工程resource的方式
1、首先拿到工程根目录
String rootPath = System.getProperty("user.dir") // D:\temp\repo\demo
2、拼接具体的文件相对路径地址
/src/main/resources/demo.txt
这种一般的方式在普通的maven or gradle工程中运行是没有问题的,但工程一旦打包之后作为jar包依赖,该"user.dir"拿到的不再是打包工程的根目录,无法获取打包工程相应的资源文件。
如果是在Android Studio插件中,拿到的rootPath就是运行时的"user.dir"了,显然这是不正确的,那么就插件的相关功能就无法使用。
JVM启动时通过执行本地方法自动初始化了这个系统属性,"user.dir"代表用户当前的工作目录。
文件流的包装玩法
stream结尾都是采用字节流,reader和writer结尾都是采用字符流
常见的字符输入流用途与区别
(1)Reader:是字符流的抽象基类,它包含了重要方法有read和close
(2)InputStreamReader:可以把InputStream中的字节数据流根据字符编码方式转换成字符数据流。
(3)FileReader:可以把FileInputStream中的字节数据转换成根据字符编码方式转成字符数字流。
(4)BufferedReader:可以把字符输入流进行封装,将数据进行缓冲,提高读取效率。它含有read(末尾返回-1)和readLine()(末尾返回null)。
通过classloader获取工程resource的方式
这里不叙述原理,直接上代码,
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
jar中读取resource内容与常规读取disk内容
-
@since 2020-10-09
*/
public class TestJar {
private static final Logger LOGGER = LoggerFactory.getLogger(TestJar.class);/**
- <h2>scan file in jar by resSubdirectory</h2>
- @param resSubdirectory resSubdirectory, like "config" not "resource/config"
- @return filePaths
*/
public static List<String> scanFilePathsInJar(String resSubdirectory) {
List<String> filePaths = new ArrayList<>();
URL url = TestJar.class.getResource(File.separator + resSubdirectory);
if (url.getPath().contains(".jar!")) {
try {
if (url.openConnection() instanceof JarURLConnection) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
for (Enumeration<JarEntry> enumeration = jarFile.entries(); enumeration.hasMoreElements();) {
JarEntry jarEntry = enumeration.nextElement();
if (!jarEntry.isDirectory() && jarEntry.getName().startsWith(resSubdirectory)) {
filePaths.add(File.separator + jarEntry.getName());
}
}
}
} catch (IOException e) {
LOGGER.error("Failed to scan jar!");
}
}
return filePaths;
}
/**
- <h2>read file text from resource</h2>
- @param subdirectory resource subdirectory path, under the "/src/main/resources/" like "/config"
- @param resourceName resource file name
- @return file text
*/
public String readFileText(String subdirectory, String resourceName) {
String resourcePath = subdirectory + resourceName;
final StringBuilder sb = new StringBuilder();
try (InputStream is = this.getClass().getResourceAsStream(resourcePath)) {
byte[] bytes = new byte[2048];
int n;
while ((n = is.read(bytes, 0, bytes.length)) != -1) {
String str = new String(bytes, 0, n, StandardCharsets.UTF_8);
sb.append(str);
}
} catch (IOException e) {
LOGGER.error("File read failed!");
}
return sb.toString();
}
/**
- <h2>read file text from disk</h2>
- @param file file absolute path
- @return file text
*/
public String readFileText(File file) {
final StringBuilder sb = new StringBuilder();
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
byte[] bytes = new byte[2048];
int n;
while ((n = in.read(bytes, 0, bytes.length)) != -1) {
String str = new String(bytes, 0, n, StandardCharsets.UTF_8);
LOGGER.info(str);
sb.append(str);
}
} catch (IOException e) {
LOGGER.error("File read failed!");
}
return sb.toString();
}
/**
- <h2>read section text from jar</h2>
- @param filePath jar inner file path
- @param sectionFlag section flag
- @return section text
*/
public String readSectionFromJar(String filePath, String sectionFlag) {
try (InputStream inputStream = this.getClass().getResourceAsStream(filePath)) {
return getSectionText(sectionFlag, inputStream);
} catch (IOException e) {
LOGGER.error("Section read failed!");
}
return "";
}
/**
- <h2>read section text from disk</h2>
- @param filePath disk file absolute path
- @param sectionFlag section flag
- @return section text
*/
public String readSectionFromDisk(String filePath, String sectionFlag) {
try (InputStream inputStream = new FileInputStream(new File(filePath))) {
return getSectionText(sectionFlag, inputStream);
} catch (IOException e) {
LOGGER.error("Section read failed!");
}
return "";
}
private String getSectionText(String sectionFlag, InputStream inputStream) {
final StringBuilder sb = new StringBuilder();
try (BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
String str;
boolean flag = false;
while ((str = bufferedReader.readLine()) != null) {
if (str.contains(sectionFlag)) {
flag = true;
continue;
}
if (str.contains("##END")) { // hard code
flag = false;
continue;
}
if (flag) {
sb.append(str).append(System.lineSeparator()); // "\r\n"
}
}
} catch (IOException e) {
LOGGER.error("Get file section failed!");
}
return deleteStrEndLineSeparator(sb.toString());
}private String deleteStrEndLineSeparator(String str) {
return str != null && !str.isEmpty() ? str.substring(0, str.length() - System.lineSeparator().length()) : "";
}
}
参考
https://www.cnblogs.com/Hermioner/p/9773188.html
//www.greatytc.com/p/28693aad491b
https://blog.csdn.net/b_h_l/article/details/7767829
https://my.oschina.net/u/3505620/blog/3275265