【发布时间】:2025-11-30 14:15:01
【问题描述】:
我有以下场景:
我有一个单行平面文件。该行是结构化的,例如它有一个标题,然后是相应的数据。它看起来像这样:
HEADER1 data data data data data HEADER2 data data HEADER3 data HEADER4 data ....
我必须将这一行转换为一种格式,其中每个标题及其数据位于单独的行上。所以,它应该是这样的:
HEADER1 data data data data data
HEADER2 data data
HEADER3 data
“HEADER”本身在长度和可以使用的字符类型上遵循一致的模式。所以,我认为Java Regex Pattern 和Matcher 将是要走的路。
我使用的是StringBuilder,因为它有一个insert() 方法,我用它来插入行分隔符。
我遇到的问题是,我新创建的文件(插入了行分隔符的文件)的末尾总是有一行包含多个标题,即它们似乎没有被分成新行。原因似乎是,一旦Matcher.find() 偶然发现一个开始索引在Matcher's region 之外的匹配项,执行就会退出插入新行的代码。
这种行为非常不一致。我有相当短的平面文件(大约 50 行),没有出现问题。然后我有一个 20K 字节/字符的平面文件,出现问题。
似乎Matcher 确实Matcher.find() 它是在读取一个衬里时提供的初始数据(区域)。假设Matcher region is from 0 to 19688。但是,当我插入 System.lineSeparator() 时,StringBuilder 的大小动态增加了 2 个字节 (\r\n)
我尝试过使用Matcher.reset() 或修改Matcher's region,正如这里建议的那样:
Replace text in StringBuilder via regex
我该如何以最有效和正确的方式处理这个问题? 谢谢
附言正则表达式不是问题。我的正则表达式匹配我在一个衬里中的每个标题。只是想我会指出这一点以避免讨论正则表达式本身。
这是我的代码:
BufferedReader br = new BufferedReader(new FileReader(Constants.SOURCE_LOCATION+fileName));
try {
String origLine = br.readLine();
StringBuilder line = null;
while (origLine != null) {
line = new StringBuilder(origLine);
Pattern pattern = Pattern.compile(Constants.AL3GROUP_REGEX_PATTERN);
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
line.insert(matcher.start(), System.lineSeparator());
}
origLine = br.readLine();
}
converterFileContents = line.toString();
PrintWriter writer = new PrintWriter("sample\\output.txt");
writer.println(converterFileContents);
writer.close();
System.out.println(converterFileContents);
} finally {
br.close();
}
【问题讨论】:
-
我会将整个文件读入
String,并在标题Pattern上拆分。然后在新行上输出结果数组的每个元素,并在前面加上您的 HEADER 信息。 -
@LanguidSquid 这听起来不错。我能够使 Evgeniy 在下面提出的建议发挥作用,但也会考虑你的想法,看看什么最适合我。我确实需要一个衬里的数据部分,所以如果我已经将它填充到一个字符串数组中,可能会为我节省一两步。感谢您的回答!
标签: java regex insert stringbuilder matcher