将字符动态插入 StringBuilder 和 Java Matcher

Dynamically inserting characters into a StringBuilder and Java Matcher

我有以下场景:

我有一个单行平面锉。该行的结构是,它有一个 header,然后是相应的数据。它看起来像这样:

HEADER1 data data data data data HEADER2 data data HEADER3 data HEADER4 data ....

我必须将这个衬里转换为一种格式,其中每个 header 与其数据一起在单独的一行上。所以,它应该是这样的:

HEADER1 data data data data data
HEADER2 data data 
HEADER3 data

"HEADER" 本身在长度和它可以使用的字符类型方面遵循一致的模式。所以,我认为 Java Regex PatternMatcher 是正确的选择。

我正在使用 StringBuilder,因为它有一个 insert() 方法,我用它来插入行分隔符。

我遇到的问题是我新创建的文件(带有行分隔符插入的文件)的末尾总是有一行由几个 header 组成,即它们似乎没有进入新的行。这似乎是因为一旦 Matcher.find() 偶然发现起始索引在 Matcher's region 之外的匹配项,执行就会退出插入新行的代码。

这种行为非常不一致。我有相当短的平面文件(大约 50 行),但没有出现问题。然后我有一个 20K bytes/characters 的平面文件,问题出现了。

似乎 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

如何以最有效和正确的方式处理这个问题? 谢谢

p.s。正则表达式不是问题。我的正则表达式匹配我在一个班轮中的每一个 header 。我只是想指出这一点以避免讨论正则表达式本身。

这是我的代码:

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

尝试全部替换

    str = str.replaceAll(" (HEADER\d+)", "\r\n");