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

How to preserve newlines while reading a file using stream - java 8

      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);
}

我正在尝试替换文件每一行中的多个文本模式。但我观察到“\r\n”(相当于 10 和 13 的字节)被替换为“\r”(仅 10),我的比较测试失败了。

我想保留输入文件中的换行符,不希望 java 修改它们。任何人都可以建议是否有一种方法可以做到这一点而不必使用单独的默认替换“\r\n”。

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

如果 Files.lines() 的方法文档提到这一点就好了。但是,如果你按照实现,它最终会导致BufferedReader.readLine()。该方法记录在 return 行的内容中,not including any line-termination characters.

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

Files.write() method you're calling, as documented in its sibling. You can also get this system-dependent line separator with System.lineSeparator() 使用系统相关的行分隔符

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

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

如果您想要原始文件的行分隔符,您不能只依赖于去除这些分隔符的方法。选项包括:

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

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

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

如果您真的想保留行终止符的原样,即使它们是不同行终止符的混合,您也可以使用正则表达式和 Scanner

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

Pattern pat = Pattern.compile(".*\R|.+\z");

\R 是一个特殊的换行匹配器,它匹配通常的行终止符和一些我从未听说过的 Unicode 行终止符。 :-) 如果您只想要通常的 CRLFCRLF,则可以使用 (\r\n|\r|\n) 之类的东西 个终结符。

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

然后,使用 Scanner 读取行,直到 returns 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.
    }
}