You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中Scanner仅以双引号外换行符为分隔符的实现方案

问题:Java Scanner仅将双引号外的换行符作为分隔符

需求是使用Java的Scanner读取内容时,只把双引号外部的换行符(\r\n或\n)当作分隔符。

输入示例:

"Content1 \r\n block" \r\n Contentn2 \r\n  New Content " \r\n Conetent3"

预期输出:

"Content1 \r\n block"

Content2

New Content " \r\n Conetent3"

你已尝试的代码:

String content = "\"Content1 \r\n block\" \r\n Contentn2 \r\n New conenet \" \r\n Conetent 3\"";
Scanner fileScanner = new Scanner(content);
String regex = "[^\"\\r\\n]+(?:\"[^\"]*\"[^\"\\r\\n]+)*";
while(fileScanner.hasNext())
{
    String rec = fileScanner.findWithinHorizon(regex,0);
    System.out.println(rec);
}

但未得到预期结果。另外在JavaScript中使用正则/(?<=^[^"]*(?:"[^"]*"[^"]*)*)\r?\n/实现了该逻辑,但Java中作为Scanner分隔符时,抛出“Look-behind group does not have obvious maximum length”错误。


可行解决方案

方案1:使用Matcher遍历匹配目标片段

Java的Scanner分隔符不支持变长lookbehind,但可以通过Pattern和Matcher直接匹配所有符合要求的片段,跳过双引号内的换行符。核心思路是:匹配双引号包裹的内容(包含内部换行)或双引号外的非换行内容,组合成完整的分割单元。

代码示例:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String content = "\"Content1 \r\n block\" \r\n Contentn2 \r\n  New Content \" \r\n Conetent3\"";
        // 正则规则:匹配双引号包裹内容,或非引号非换行内容
        Pattern pattern = Pattern.compile("\"[^\"]*\"|[^\"\\r\\n]+");
        Matcher matcher = pattern.matcher(content);
        
        StringBuilder currentSegment = new StringBuilder();
        while (matcher.find()) {
            String part = matcher.group();
            // 处理双引号包裹的内容
            if (part.startsWith("\"")) {
                currentSegment.append(part);
            } else {
                // 处理非引号内容,去除多余空格
                currentSegment.append(part.trim());
            }
            
            // 检查是否到达换行分隔位置
            int nextPos = matcher.end();
            if (nextPos >= content.length() || content.charAt(nextPos) == '\r' || content.charAt(nextPos) == '\n') {
                // 跳过后续的换行符
                while (nextPos < content.length() && (content.charAt(nextPos) == '\r' || content.charAt(nextPos) == '\n')) {
                    nextPos++;
                }
                System.out.println(currentSegment.toString().trim());
                currentSegment.setLength(0);
            }
        }
        // 处理最后一个剩余片段
        if (currentSegment.length() > 0) {
            System.out.println(currentSegment.toString().trim());
        }
    }
}

方案2:预处理内容,替换双引号内的换行符后拆分

先把双引号内部的换行符替换成临时占位符,再用Scanner按换行符拆分,最后还原占位符为换行符。

代码示例:

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String content = "\"Content1 \r\n block\" \r\n Contentn2 \r\n  New Content \" \r\n Conetent3\"";
        // 选一个不会出现在内容中的临时占位符
        String placeholder = "###INNER_NEWLINE###";
        
        // 替换双引号内的所有换行符
        Pattern quotePattern = Pattern.compile("\"([^\"]*)\"");
        Matcher quoteMatcher = quotePattern.matcher(content);
        StringBuffer processedContent = new StringBuffer();
        while (quoteMatcher.find()) {
            String quotedContent = quoteMatcher.group(1)
                    .replace("\r\n", placeholder)
                    .replace("\n", placeholder);
            quoteMatcher.appendReplacement(processedContent, "\"" + quotedContent + "\"");
        }
        quoteMatcher.appendTail(processedContent);
        
        // 按换行符拆分内容,再还原占位符
        Scanner scanner = new Scanner(processedContent.toString());
        scanner.useDelimiter("\\r?\\n");
        
        while (scanner.hasNext()) {
            String segment = scanner.next().trim()
                    .replace(placeholder, "\r\n");
            System.out.println(segment);
        }
        scanner.close();
    }
}

为什么之前的方法失效?

  1. 你尝试的findWithinHorizon正则[^"\r\n]+(?:\"[^\"]*\"[^"\r\n]+)*无法处理双引号内的换行,因为[^"\r\n]+会排除换行符,导致双引号内的内容被截断。
  2. JavaScript支持的变长lookbehind正则在Java中不被兼容,Java要求lookbehind组必须是固定长度(或有限可选长度,比如(?<=a{1,3})),而你使用的正则是无限变长的,因此抛出错误。

内容的提问来源于stack exchange,提问作者Siva Ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:56:13