精细磁头记录时在数据块中拆分文件(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();
}