【问题标题】:Dynamically inserting characters into a StringBuilder and Java Matcher将字符动态插入 StringBuilder 和 Java Matcher
【发布时间】: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 PatternMatcher 将是要走的路。

我使用的是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


【解决方案1】:

尝试全部替换

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

【讨论】:

  • 我试过了,但似乎没有在每个标题之前添加行分隔符。一旦我打开写入的文件,我仍然有一个单行平面文件,每个标题前没有“\r\n”。有什么想法吗?
  • 我不得不对上面列出的代码进行一些修改,并使您的建议生效。感谢朋友的输入!
最近更新 更多