在Java中使用Scanner分隔符,如何将我使用的String保留为分隔符?

时间:2015-03-21 01:30:13

标签: java string java.util.scanner delimiter

我的程序使用标点符号作为分隔符逐句从文件中读取故事。它将句子存储在ArrayList中,然后随机播放ArrayList并打印它,每次运行程序时都会创建一个不同的故事。我的问题是使用分隔符摆脱新故事的标点符号,有没有办法我仍然可以使用分隔符但保持字符串作为我正在阅读的内容的一部分?

2 个答案:

答案 0 :(得分:0)

您可以使用扫描仪的默认空白分隔符扫描文件的内容,然后使用模式/匹配器查找每个扫描仪令牌中标点符号分隔符的位置。

以下是一个例子:

final List<String> sentences = new ArrayList();
final Scanner scanner = new Scanner(new File("story.txt"));
final Pattern pattern = Pattern.compile("[.!?]");

StringBuilder sb = new StringBuilder();

// default white space delimiter
while (scanner.hasNext()) {
    String token = scanner.next().trim();

    // look for pattern in current token
    Matcher matcher = pattern.matcher(token);
    if (matcher.find()) {

        // get end position of match
        int index = matcher.end();

        // add to sentence the substring from beginning of token to the end match position
        sb.append(token.substring(0, index));

        // build and add your sentence
        sentences.add(sb.toString().trim());

        // start new sentence
        sb = new StringBuilder(token.substring(index));

    } else {
        // no punctuation match, add token to sentence
        sb.append(token);
    }

    // add space to sentence
    sb.append(" ");
}

Collections.shuffle(sentences);
for (String sentence : sentences) {
    System.out.println(sentence);
}

如果故事的语言并不总是使用空格(例如中文),您可以随时扫描单个字符。

希望这有帮助!

答案 1 :(得分:0)

我遇到了同样的问题而且落在了这里,但之前的答案并不符合我的需要。经过一些试验和错误后,这就是我想出来的所以我回来分享它,以防它有助于某人,以后:

一般解决方案

使用Scanner#findInLine(甚至Scanner#findWithinHorizon)来捕捉输入流中的分隔符:

/* This method does not close the given scanner. That must happen, elsewhere (typically in a loop that calls this) */
public String getNextPattern(Scanner s, String pattern) {
    s.useDelimiter(pattern);
    if(!s.hasNext()) {
        return null;
    }
    s.next();
    return s.findInLine(pattern);
}

说明

这里值得注意的是,扫描仪实际上在输入流上留下了分隔符。所以这个方法所做的就是:

  1. 将分隔符设置为我们想要在流中匹配的内容
  2. 推进到下一个令牌(即丢弃与分隔符不匹配的输入)
  3. 将分隔符从流中拉出。鉴于Scanner的工作方式,我们知道分隔符将是流中的下一个文本。
  4. 此解决方案是一种从流或文件中提取任何正则表达式模式的方法。

    解决您的具体问题

    在我的情况下,我丢弃了令牌。在您的情况下,这些是您想要保留的句子,因此您可以随时将它们存储在ArrayList中。这些方面的东西可以解决您的具体问题:

    // simplistic approach to handling whitespace
    private static final String PUNCTUATION_PATTERN = "[.!?]\\s*";
    
    // for example purposes, read from stdin and write to stdout
    public void shuffleStory(InputStream input) {
        try(Scanner s = new Scanner(input)) {
            s.useDelimiter(PUNCTUATION_PATTERN);
            List<String> sentences = new ArrayList<>();
            while(s.hasNext()) {
                sentences.add(s.next() + s.findInLine(PUNCTUATION_PATTERN).trim());
            }
            Collections.shuffle(sentences);
            System.out.println(String.join(" ", sentences));
        }
    }