精细磁头记录时在数据块中拆分文件(java 8)

精细磁头记录时在数据块中拆分文件(java 8),java,lambda,java-8,Java,Lambda,Java 8,我有一段代码,当找到开始记录时,它会将一个文件分成若干块 List<StringBuilder> list = new ArrayList<>(); StringBuilder jc = null; try (BufferedReader br = Files.newBufferedReader(Paths.get("")) { for (String line = br.readLine(); line != null; line = br.readLine()

我有一段代码,当找到开始记录时,它会将一个文件分成若干块

List<StringBuilder> list = new ArrayList<>();
StringBuilder jc = null;
try (BufferedReader br = Files.newBufferedReader(Paths.get("")) {
    for (String line = br.readLine(); line != null; line = br.readLine()) {
        if (line.startsWith("REQ00")) {
            jc = new StringBuilder();
            list.add(jc);
        }
        jc.append(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}
有没有办法将这段代码转换成Java8流方式

Map<Integer, String> chunks = Files.lines(Paths.get("")).collect(
    Collectors.groupingBy(
        new Function<String, Integer>(){
            Integer lastKey = 0;
            public Integer apply(String s){
                if(s.startsWith("REQ00")){
                    lastKey = lastKey+1;
                }
                return lastKey;
            }
        }, Collectors.joining()));

我刚刚使用了连接,它创建了一个字符串而不是一个字符串生成器。可以用使用字符串生成器的收集器替换它,也可以在以后将字符串更改为字符串生成器。

使用正确的工具进行作业。有了扫描仪,它就像

List<String> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
    s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
    while(s.hasNext()) list.add(s.next());
} catch (IOException e) {
    e.printStackTrace();
}
一种更有效的变体是

List<StringBuilder> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
    s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
    while(s.hasNext()) list.add(toStringBuilderWithoutLinebreaks(s.next()));
} catch (IOException e) {
    e.printStackTrace();
}

…

static final Pattern LINE_BREAK = Pattern.compile("\\R");
static StringBuilder toStringBuilderWithoutLinebreaks(String s) {
    Matcher m = LINE_BREAK.matcher(s);
    if(!m.find()) return new StringBuilder(s);
    StringBuilder sb = new StringBuilder(s.length());
    int last = 0;
    do { sb.append(s, last, m.start()); last = m.end(); } while(m.find());
    return sb.append(s, last, s.length());
}

首先,这段代码中有很多bug,而且代码的行为似乎不像您所解释的那样。你介意修一下吗。例如,如果第一行不是以REQ00开头,那么这段代码将有NPE,因为jc.appendlineTry try Stream=Files.linesPaths.get{Stream.filterline->line.startsWithREQ00.collectCollectors.toList;}@pvpkiran u r是的,这段代码编写得非常快,可以解释我想要什么。放松点@HadiJ我不想只收集REQ00记录,但我想获得从REQ00到另一行的所有记录。第一行是否总是以REQ00开始?这假设函数以正确的顺序求值,但不能保证……函数求值会被排序吗?如果流不是无序的,或并发的。而且收集器没有被标记为并发的,看起来函数将按顺序调用。我正在尝试跟踪您的答案以及您链接的后续文档。但我不清楚,功能评估的顺序是处理顺序。这是无法保证的。对于有序流,将保持相遇顺序,这意味着最终结果将反映它。这只有在函数产生正确结果时才有效,而不管它们的求值顺序如何。您的代码可能会在顺序求值中产生预期的结果,尽管无法保证,但在并行求值中肯定会中断,几乎可以肯定,因为即使这样也无法保证。因为它能够跨行边界处理文本。处理任务的行流时,需要跨多个流元素工作。相比之下,扫描仪会生成多行元素,范围从您的分隔符出现的位置到下一个位置。如果您至少没有消除换行符的要求,那么您的原始代码会消除这些换行符,扫描仪生成的字符串已经是最终结果,这比将文本拆分成行然后再连接它们要有效得多。
List<StringBuilder> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
    s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
    while(s.hasNext()) list.add(toStringBuilderWithoutLinebreaks(s.next()));
} catch (IOException e) {
    e.printStackTrace();
}

…

static final Pattern LINE_BREAK = Pattern.compile("\\R");
static StringBuilder toStringBuilderWithoutLinebreaks(String s) {
    Matcher m = LINE_BREAK.matcher(s);
    if(!m.find()) return new StringBuilder(s);
    StringBuilder sb = new StringBuilder(s.length());
    int last = 0;
    do { sb.append(s, last, m.start()); last = m.end(); } while(m.find());
    return sb.append(s, last, s.length());
}
List<StringBuilder> list;
try(Scanner s = new Scanner(Paths.get(path))) {
    list = s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE))
            .tokens()
            .map(string -> toStringBuilderWithoutLinebreaks(string))
            .collect(Collectors.toList());
} catch (IOException e) {
    e.printStackTrace();
    list = List.of();
}