在Java8中逐行读取Spring多部分文件的最佳方法
csv Spring多部分文件的最佳处理方式是什么? 我以前用过类似的方法:在Java8中逐行读取Spring多部分文件的最佳方法,java,spring,java-8,Java,Spring,Java 8,csv Spring多部分文件的最佳处理方式是什么? 我以前用过类似的方法: public void handleFile(MultipartFile multipartFile){ try{ InputStream inputStream = multipartFile.getInputStream(); IOUtils.readLines(inputStream, StandardCharsets.UTF_8) .str
public void handleFile(MultipartFile multipartFile){
try{
InputStream inputStream = multipartFile.getInputStream();
IOUtils.readLines(inputStream, StandardCharsets.UTF_8)
.stream()
.forEach(this::handleLine);
} catch (IOException e) {
// handle exception
}
}
private void handleLine(String s) {
// do stuff per line
}
据我所知,这首先将整个文件加载到内存中的一个列表中,然后再对其进行处理,对于具有数万行的文件,这可能需要相当长的时间
有没有一种方法可以一行一行地处理它,而不用手动实现迭代(即使用read()
,hasNext(
),…)之类的工具)?
我正在为文件系统中的文件寻找类似于此示例的简明内容:
try (Stream<String> stream = Files.lines(Paths.get("file.csv"))) {
stream.forEach(this::handleLine);
} catch (IOException e) {
// handle exception
}
try(Stream=Files.line(path.get(“file.csv”)){
forEach(这个::handleLine);
}捕获(IOE异常){
//处理异常
}
公共静态列表readCSV(字符串文件名)引发IOException{
列表记录=新的ArrayList();
try(BufferedReader br=新的BufferedReader(
新文件读取器(文件名))){
弦线;
而((line=br.readLine())!=null){
记录。添加(行);
}
}
退货记录;
}
如果您有InputStream,则可以使用此选项:
InputStream inputStream = multipartFile.getInputStream();
new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.forEach(this::handleLine);
在其他情况下:
无论是多部分文件还是有多个独立文件,在Java 8中使用Stream
API有很多方法可以实现这一点:
解决方案1:
如果您的文件位于不同的目录中,您可以这样做:
try (Stream<Path> stream = Files.walk(Paths.get("/test/ehsan"))) {
stream.filter(Files::isRegularFile)
.flatMap(path -> {
try {
return Files.lines(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
dirs.stream()
.map(Paths::get)
.flatMap(path -> {
try {
return Files.walk(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.filter(Files::isRegularFile)
.flatMap(path -> {
try {
return Files.lines(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.forEach(System.out::println);
假设您有一个字符串的列表
,其中包含文件的路径,如下所示:
List<String> files = Arrays.asList(
"/test/test.txt",
"/test2/test2.txt");
解决方案2:
您还可以使用files.walk
以以下方式读取/test/ehsan
目录中存在的所有文件行:
try (Stream<Path> stream = Files.walk(Paths.get("/test/ehsan"), 1)) {
stream.filter(Files::isRegularFile)
.flatMap(path -> {
try {
return Files.lines(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
正如您所看到的,文件的第二个参数。walk
指定要访问的最大目录级别数,如果您不传递它,将使用默认值,即整数。最大值
解决方案3:
我们不要到此为止,我们可以走得更远。如果我们想读取存在于两个完全不同的目录中的所有文件行,例如/test/ehsan
和/test2/ehsan1
我们可以这样做,但我们应该谨慎,流
不应该太长(因为它会降低我们程序的可读性),最好将它们分解为单独的方法,但是,因为这里不可能编写多个方法,我将在一个地方编写如何做到这一点:
假设您有一个列表
的字符串
,其中包含目录的路径,如下所示
list<String> dirs = Arrays.asList(
"/test/ehsan",
"/test2/ehsan1");
您确定要自己处理每一行,而不是让CSV解析库处理InputStream吗?它是否适合您的需要@你能推荐一个我可以研究的库吗?你知道Java8有多老吗?6岁;)我发现它相当可靠。这基本上是IOUtils.readLines的实现。不是我要找的。你的解决方案都考虑文件系统上的文件。我说的是SpringMultipartFile(),通常不是。我编辑了我的问题以澄清这一点。@Schlaagi我刚刚添加了可用于特殊情况的更新
list<String> dirs = Arrays.asList(
"/test/ehsan",
"/test2/ehsan1");
dirs.stream()
.map(Paths::get)
.flatMap(path -> {
try {
return Files.walk(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.filter(Files::isRegularFile)
.flatMap(path -> {
try {
return Files.lines(path);
} catch (IOException e) {
e.printStackTrace();
}
return Stream.empty();
})
.forEach(System.out::println);