如何使用流读取文件时保留换行符 - java 8

时间:2016-02-10 19:19:55

标签: java java-8 newline java-stream replaceall

      try (Stream<String> lines = Files.lines(targetFile)) {  
     List<String> replacedContent = lines.map(line ->  
                                       StringUtils.replaceEach(line,keys, values))
                                       .parallel()
                                       .collect(Collectors.toList());
    Files.write(targetFile, replacedContent);
}

我试图在文件的每一行中替换多个文本模式。但我观察到&#34; \ r \ n&#34;(字节等效10和13)正被替换为&#34; \ r&#34;(仅为10)并且我的比较测试失败了。

我想保留输入文件中的换行符,并且不希望java触摸它们。任何人都可以建议是否有办法这样做,而不必使用单独的默认替换&#34; \ r \ n&#34;。

2 个答案:

答案 0 :(得分:11)

问题是Files.lines()是在BufferedReader.readLine()之上实现的,Files.write()读取一行直到行终止符并将其抛弃。然后,当您使用类似Scanner的内容编写行时,这会在每行之后提供系统特定的行终止符,这可能与读入的行终止符不同。

如果你真的想要完全保留行终止符,即使它们是不同行终止符的混合,你也可以使用正则表达式和Pattern pat = Pattern.compile(".*\\R|.+\\z");

首先定义一个匹配包含有效行终止符或EOF的行的模式:

\\R

(\\r\\n|\\r|\\n)是一个特殊的换行符匹配器,它匹配常用的行终止符以及一些我从未听说过的Unicode行终止符。 :-)如果您只想要通常的 CRLF CR LF 终止符,您可以使用类似.+\\z的内容。

您必须包含Scanner才能匹配文件中没有行终止符的潜在最后“行”。确保正则表达式始终匹配至少一个字符,以便在扫描程序到达文件末尾时找不到匹配项。

然后,使用null读取行,直到它返回try (Scanner in = new Scanner(Paths.get(INFILE), "UTF-8")) { String line; while ((line = in.findWithinHorizon(pat, 0)) != null) { // Process the line, then write the output using something like // FileWriter.write(String) that doesn't add another line terminator. } }

shape.on('dragstart', function () {
    if (layerDraggable) {
        shape.stopDrag();
        shapeLayer.startDrag();
    }
}

答案 1 :(得分:4)

您的信息流中的行不包含任何换行符。

如果Files.lines()的方法文档提到了这一点,那就太好了。但是,如果您遵循实施,最终会导致BufferedReader.readLine()。记录该方法以返回行not including any line-termination characters

的内容

您可以在编写行时为行添加换行符。

系统相关的行分隔符由您调用的Files.write()方法使用,documented in its sibling。您还可以使用System.lineSeparator()获取此系统相关的行分隔符。

如果您想要一个不同的行分隔符,并知道它是什么,,您可以指定它。例如:

    try ( PrintStream out = new PrintStream( Files.newOutputStream( targetFile ))) 
    {
        lines.forEach( line -> out.print( line + "\r\n") );
    }

如果您想要原始文件的行分隔符,则不能只依赖于剥离它们的方法。选项包括:

  • 读取第一行分隔符,并猜测它在整个文件中是否一致。这允许您继续使用Files.lines()来读取行。
  • 使用允许您使用分隔符获取行的API。
  • 逐个字符读取,而不是逐行读取,以便您可以获取行分隔符。

警告:您的代码从同一文件读取和写入。由于异常终止或错误,您可能会丢失原始数据。