多种方式实现java读取文件
本文介绍java多种方式从classpath、url以及jar中读取文件。
准备
我们仅使用java类实现一组测试示例,在测试类中,我们使用Hamcrest工具进行匹配验证。
测试类共享使用readFromInputStream方法,实现传输输入流至字符串,方便断言结果。
private String readFromInputStream(InputStream inputStream)
throws IOException {
StringBuilder resultStringBuilder = new StringBuilder();
try (BufferedReader br
= new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line).append("\n");
}
}
return resultStringBuilder.toString();
}
当然,还有其他方式可以实现通用功能,你可以参考本系列其他文章。
从Classpath读取文件
本节解释如何从Classpath读文件,假设“fileTest.txt”在src/main/resources路径下:
@Test
public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() {
String expectedData = "Hello World from fileTest.txt!!!";
Class clazz = FileOperationsTest.class;
InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt");
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
上面代码片段,我们使用当前类的getResourceAsStream 方法载入文件,并传递文件的绝对路径作为参数。我们也可以使用ClassLoader实例:
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt");
String data = readFromInputStream(inputStream);
我们获取当前类classLoader,通过使用getClass().getClassLoader()方法.两者的差异是当在ClassLoader实例上使用getResourceAsStream 方法,路径表示classpath的绝对路径。而通过类实例,路径是相对于包或通过反斜杠开头指明是绝对路径。
使用jdk7读文件
在jdk7中NIO包有很大的改进。让我们看一个示例,使用Files类和readAllBetes方法。readAllBetes方法接收Path参数,Path类被认为是 java.io.File的升级,并增加了额外的操作:
@Test
public void givenFilePath_whenUsingFilesReadAllBytes_thenFileData() {
String expectedData = "Hello World from fileTest.txt!!!";
Path path = Paths.get(getClass().getClassLoader()
.getResource("fileTest.txt").toURI());
byte[] fileBytes = Files.readAllBytes(path);
String data = new String(fileBytes);
Assert.assertEquals(expectedData, data.trim());
}
jdk8读文件
jdk8中Files类的lines()方法,可以获取字符串流。下面通过示例读文件值字节,然后用utf-8编码生成字符。
@Test
public void givenFilePath_whenUsingFilesLines_thenFileData() {
String expectedData = "Hello World from fileTest.txt!!!";
Path path = Paths.get(getClass().getClassLoader()
.getResource("fileTest.txt").toURI());
StringBuilder data = new StringBuilder();
Stream<String> lines = Files.lines(path);
lines.forEach(line -> data.append(line).append("\n"));
lines.close();
Assert.assertEquals(expectedData, data.toString().trim());
}
使用io通道的Stream,如文件操作,我们需要使用close()显示地关闭流。
使用FileUtils读文件
另一个常用的方法是使用FileUtils类,需要增加依赖:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
可以应用最新的版本。
@Test
public void givenFileName_whenUsingFileUtils_thenFileData() {
String expectedData = "Hello World from fileTest.txt!!!";
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileTest.txt").getFile());
String data = FileUtils.readFileToString(file);
Assert.assertEquals(expectedData, data.trim());
}
我们传递File对象给FileUtils类的方法readFileToString()。这个工具类负责加载内容,无需写任何模板代码,创建InputStream实例,读数据。
从url读数据
从url读内容,示例中我们使用“/”作为url:
@Test
public void givenURLName_whenUsingURL_thenFileData() {
String expectedData = "Baeldung";
URL urlObject = new URL("/");
URLConnection urlConnection = urlObject.openConnection();
InputStream inputStream = urlConnection.getInputStream();
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
除了使用标准sdk的URL和URLConnection类,还有其他方式可以实现。
从jar中读文件
从本地jar文件读文件内容,需jar中带有文件。示例中我们读取 “hamcrest-library-1.3.jar” 中“LICENSE.txt”文件:
@Test
public void givenFileName_whenUsingJarFile_thenFileData() {
String expectedData = "BSD License";
Class clazz = Matchers.class;
InputStream inputStream = clazz.getResourceAsStream("/LICENSE.txt");
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
这里我们加载Hamcrest库中的LICENSE.txt文件,所以我们使用Matcher获取resource。同样也可以使用ClassLoader加载。
总结
本文我们介绍了如何从不同位置读取文件,classpath,URL以及jar,并使用java核心api演示如何从文件中获取内容。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/79601499