Java 8中到处都有流。只需四处看看,可以肯定地找到它们。 它也适用于java.io.BufferedReader
。 使用Stream API在Java 8中解析文件非常容易。
我有一个要读取的CSV文件。 下面的例子:
username;visited
jdoe;10
kolorobot;4
我的阅读器的一项合同是提供标头作为字符串列表,并提供所有记录作为字符串列表。 我的阅读器接受java.io.Reader
作为阅读源。
我将从阅读标题开始。 读取标头的算法如下:
- 打开阅读源,
- 获取第一行并进行解析,
- 用分隔符分割线,
- 获取第一行并进行解析,
- 将行转换为字符串列表并返回。
并执行:
class CsvReader {private static final String SEPARATOR = ";";private final Reader source;CsvReader(Reader source) {this(source);}List<String> readHeader() {try (BufferedReader reader = new BufferedReader(source)) {return reader.lines().findFirst().map(line -> Arrays.asList(line.split(SEPARATOR))).get();} catch (IOException e) {throw new UncheckedIOException(e);}}
}
很简单。 不言自明。 同样,我创建了一种读取所有记录的方法。 读取记录的算法如下:
- 打开阅读源,
- 跳过第一行,
- 用分隔符分割线,
- 在将行映射到字符串列表的每一行上应用一个映射器。
并执行:
class CsvReader {List<List<String>> readRecords() {try (BufferedReader reader = new BufferedReader(source)) {return reader.lines().substream(1).map(line -> Arrays.asList(line.split(separator))).collect(Collectors.toList());} catch (IOException e) {throw new UncheckedIOException(e);}}
}
这里没什么好看的。 您可能会注意到,这两种方法中的映射器完全相同。 实际上,可以很容易地将其提取为变量:
Function<String, List<String>> mapper = line -> Arrays.asList(line.split(separator));
最后,我创建了一个简单的测试。
public class CsvReaderTest {@Testpublic void readsHeader() {CsvReader csvReader = createCsvReader();List<String> header = csvReader.readHeader();assertThat(header).contains("username").contains("visited").hasSize(2);}@Testpublic void readsRecords() {CsvReader csvReader = createCsvReader();List<List<String>> records = csvReader.readRecords();assertThat(records).contains(Arrays.asList("jdoe", "10")).contains(Arrays.asList("kolorobot", "4")).hasSize(2);}private CsvReader createCsvReader() {try {Path path = Paths.get("src/test/resources", "sample.csv");Reader reader = Files.newBufferedReader(path, Charset.forName("UTF-8"));return new CsvReader(reader);} catch (IOException e) {throw new UncheckedIOException(e);}}
}
翻译自: https://www.javacodegeeks.com/2014/05/parsing-a-file-with-stream-api-in-java-8.html