当前位置: 首页 > 知识库问答 >
问题:

使用垂直空白字符作为java扫描程序定界符,在每个endpoint扫描空字符串

万阳嘉
2023-03-14

我正在尝试使用Java中的Scanner类扫描一个文件,其中的数据字段由“@”或“endline”分隔。以下是一个示例输入文件:

Student @ Codey @ Huntting
Student @ Sarah @ Honsinger

为了正确扫描如下所示的输入文件,我尝试将Java扫描程序上的分隔符更改为正则表达式“[@\\v]”,它应该匹配@或任何垂直空白,包括\n\r

下面是我用来测试它的代码:

Scanner scanner = new Scanner(new File("data/initialize.txt"));
int tokenNum = 0;

scanner.useDelimiter("[@\\v]");

while(scanner.hasNext()) {
    System.out.println("Token #" + tokenNum++ + ": " + scanner.next());
}

scanner.close();

我希望扫描的令牌是:

Token #1: Student
Token #2:  Codey 
Token #3:  Huntting
Token #4: Student
Token #5:  Sarah
Token #6:  Honsinger

但实际收到的代币是:

Token #1: Student
Token #2:  Codey 
Token #3:  Huntting
Token #4
Token #5: Student
Token #6:  Sarah
Token #7:  Honsinger
Token #8: 

我本来希望扫描器在扫描hunting时,在搜索之后,以及在下一次调用input时,向上移动到换行符。next(),跳过该换行符,但由于某种原因,扫描程序似乎在该行末尾捕获了一个空字符串。

我检查了多次,文件在任何一行之后都没有空格。我尝试过不同的模式,如[@[\\v]]][@][\\v],但这些模式总是给出具有相同空字符串错误的数据,或者输出完全不正常。

共有3个答案

宇文嘉勋
2023-03-14

您的文件可能包含形式\r\n的换行符。在这种情况下,扫描仪会找到分隔符\r并输出\r之前的任何内容。然后它找到分隔符\n并输出\r\n之间的空令牌,然后在\n之后继续。

为了允许\r\n中断,我建议您将\r\n |[@\v]按该确切顺序作为分隔符regex。当然,在转义之后,它会变成“\r\n|[@\\v]”

正如Andreas提到的,您可以使用的另一个正则表达式是@\R,因为\R匹配任何unicode换行符,包括\R\n。这可能是最好的解决方案。

辛承志
2023-03-14

如果我理解正确,我们可能只想删除@和后面的空格,然后用新行替换它,并在它前面附加一个文本。也许,这个表达会有帮助:

([\S\s]*?)(?:@\s|$)

如果不需要此表达式,可以在regex101.com.中修改/更改表达式

您还可以在jex.im可视化您的表情:

这个片段显示我们可能有一个有效的表达式:

const regex = /([\S\s]*?)(?:@\s|$)/gm;
const str = `Student @ Codey @ Huntting
Student @ Sarah @ Honsinger`;
const subst = `\n$1`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);
吕扬
2023-03-14

您的问题是换行符是一对\r\n,并且\v单独匹配它们。为了复制这一点,让我们更改代码,为测试数据使用内联字符串:

String input = "Student @ Codey @ Huntting\r\n" +
               "Student @ Sarah @ Honsinger\r\n";
try (Scanner scanner = new Scanner(input).useDelimiter("[@\\v]")) {
    for (int tokenNum = 0; scanner.hasNext(); tokenNum++) {
        System.out.println("Token #" + tokenNum + ": \"" + scanner.next() + "\"");
    }
}

输出

Token #0: "Student "
Token #1: " Codey "
Token #2: " Huntting"
Token #3: ""
Token #4: "Student "
Token #5: " Sarah "
Token #6: " Honsinger"
Token #7: ""

解决此问题的一种方法是首先尝试匹配\r\n对:

useDelimiter("\r\n|[@\\v]")

输出

Token #0: "Student "
Token #1: " Codey "
Token #2: " Huntting"
Token #3: "Student "
Token #4: " Sarah "
Token #5: " Honsinger"

但是,这将花费时间检查两次\r,因此最好使用内置\r(任何Unicode换行符序列,相当于\u000D\u000A |[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]):

useDelimiter("@|\\R")

同样的结果,但更清楚地反映了你想如何匹配。

您当然可以使用trim()bar()来删除前导空格和尾随空格,但是为什么不让Scanner来完成这项工作呢?使用|需要一个(非捕获)组来保持它与空白匹配分开:

useDelimiter("\\s*(?:@|\\R)\\s*")

输出

Token #0: "Student"
Token #1: "Codey"
Token #2: "Huntting"
Token #3: "Student"
Token #4: "Sarah"
Token #5: "Honsinger"
 类似资料:
  • 问题内容: 我正在使用嵌套循环从字符串行(从文本文件)中提取数字,如下所示: 问题在于此代码将跳过所有空格,但是我也需要使用这些“空格”。那么可以返回空格还是我需要使用其他东西? 我的文本文件可能包含以下内容: 这些空白行各包含1条,这就是我需要返回的行。 问题答案: 使用扫描仪和方法,您将找到解决方案,因为这将使您能够捕获空白行或空白行。

  • 问题内容: 我正在编写一个使用Event类的程序,该类中有一个日历实例和一个String类型的描述。创建事件的方法使用扫描仪获取月,日,年,小时,分钟和说明。我遇到的问题是Scanner.next()方法仅返回空格之前的第一个单词。因此,如果输入为“我的生日”,则该事件实例的描述就是“我的”。 我做了一些研究,发现人们使用Scanner.nextLine()解决此问题,但是当我尝试这样做时,它只是

  • 我正试图用Java中的扫描器将一个字符串分成另外两个字符串。好像不起作用。我只能通过谷歌找到扫描仪用来读取控制台输入的例子。我从扫描仪的手册中找出了我做事情的方式,我不确定我错了什么。 第一个和第二个是空白的,我不知道为什么。

  • 问题:编写一个名为wordWrap的方法,该方法接受表示输入文件的扫描器作为其参数,并将文件的每一行输出到控制台,对超过60个字符的所有行进行文字包装。例如,如果一行包含112个字符,则方法应将其替换为两行:一行包含前60个字符,另一行包含最后52个字符。包含217个字符的行应该被包装成四行:三行的长度为60,最后一行的长度为37。 我的代码: 输出中的问题: 预期产出: 生产产量: 我哪里做错了

  • 我试图为字符串创建一个扫描器方法,它只在用户输入的值不为空时才返回该值(空白,用户立即点击“Enter”等)。如果用户这样做,我希望打印出一条错误消息,并让循环再次返回开始,等待新的用户输入。如果正确,我希望方法返回正确的输入值。 我的代码是这样的:

  • 问题内容: 我试图找到一种方法来从键盘输入。 我尝试使用: 该方法不存在。 我尝试了作为。但是,它并不总是在每种情况下都可行,因为我从我的方法中调用的另一个方法需要作为输入。因此,我必须找到一种显式将char作为输入的方法。 有什么帮助吗? 问题答案: 你可以从中提取第一个字符: 消耗正好一个字符,你可以使用: 要严格使用一个字符,可以使用: