Files.lines在Java8中跳过断行

Fra*_*sco 10 java file java-8 java-stream

我正在使用Files.lines(...)读取一个非常大的(500mb)文件.它读取文件的一部分,但在某些时候它会破坏java.io.UncheckedIOException:java.nio.charset.MalformedInputException:输入长度= 1

我认为该文件具有不同字符集的行.有没有办法跳过这些断线?我知道返回的流是由Reader支持的,读者我知道如何跳过,但不知道如何从流中获取Reader以便按我喜欢的方式设置它.

    List<String> lines = new ArrayList<>();
    try (Stream<String> stream = Files.lines(Paths.get(getClass().getClassLoader().getResource("bigtest.txt").toURI()), Charset.forName("UTF-8"))) {
        stream
            .filter(s -> s.substring(0, 2).equalsIgnoreCase("aa"))
            .forEach(lines::add);
    } catch (final IOException e) {
        // catch
    }
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 15

当预配置的解码器已经停止解码并发生异常时,您无法在解码过滤带有无效字符的行.您必须CharsetDecoder手动配置以告知它忽略无效输入或用特殊字符替换该输入.

CharsetDecoder dec=StandardCharsets.UTF_8.newDecoder()
                  .onMalformedInput(CodingErrorAction.IGNORE);
Path path=Paths.get(getClass().getClassLoader().getResource("bigtest.txt").toURI());
List<String> lines;
try(Reader r=Channels.newReader(FileChannel.open(path), dec, -1);
    BufferedReader br=new BufferedReader(r)) {
        lines=br.lines()
                .filter(s -> s.regionMatches(true, 0, "aa", 0, 2))
                .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

这只是忽略字符集解码错误,跳过字符.要跳过包含错误的整行,您可以让解码器'\ufffd'为错误插入替换字符(默认值)并过滤掉包含该字符的行:

CharsetDecoder dec=StandardCharsets.UTF_8.newDecoder()
                  .onMalformedInput(CodingErrorAction.REPLACE);
Path path=Paths.get(getClass().getClassLoader().getResource("bigtest.txt").toURI());
List<String> lines;
try(Reader r=Channels.newReader(FileChannel.open(path), dec, -1);
    BufferedReader br=new BufferedReader(r)) {
        lines=br.lines()
                .filter(s->!s.contains(dec.replacement()))
                .filter(s -> s.regionMatches(true, 0, "aa", 0, 2))
                .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

  • 那个API不支持.但即使它是,它也不会比这里的代码更紧凑.请注意,"样板"只是一个额外的行.结果看起来更加冗长,因为我做了更宽松的格式,因为我不喜欢水平滚动.好吧,在为更广泛的受众发布代码示例时,我使用的空白空间比在实际代码中更多.当然,你可以内联`dec`和`path`并使用`import static`作为`StandardCharsets.UTF_8`以及`CodingErrorAction.*`,`Channels.newReader`,`FileChannel.open`等. (2认同)