Java的扫描仪头痛
我有一个文本文件,它看起来像:Java的扫描仪头痛
name1
1 0 1 0 1
0 1 1 1 0
0 0 0 0 0
name2
1 0 1 0 1
0 0 1 1 0
0 0 0 0 1
即明文标签,然后用1/0用空格隔开几行。 1/0的行数是可变的,但是任何两个特定标签之间的每行应该具有相同数量的1/0(尽管可能不会)。
如何用扫描仪抓取每个名称+行块?是否有任何优雅的方式来强化行数的一致性(并在不一致时提供某种反馈)?
我在想可能有一个方便的方式与聪明的分隔符规范,但我似乎无法得到那个工作。
更妙的是,一个helpful answer to another question(感谢Bart)后:
static final String labelRegex="^\\s*\\w+$";
static final Pattern labelPattern = Pattern.compile(labelRegex, Pattern.MULTILINE);
Matcher labelMatcher = labelPattern.matcher("");
static final String stateRegex = "([10])+[10]\\s+";
static final String statesRegex = "("+stateRegex+")+";
static final Pattern statesPattern = Pattern.compile(statesRegex, Pattern.MULTILINE);
Matcher stateMatcher = statesPattern.matcher("");
static final String chunkRegex = "(?="+labelRegex+")";
static final Pattern chunkPattern = Pattern.compile(chunkRegex,Pattern.MULTILINE);
Scanner chunkScan;
public void setSource(File source) {
if(source!=null && source.canRead()) {
try {
chunkScan = new Scanner(new BufferedReader(new FileReader(source)));
chunkScan.useDelimiter(chunkPattern);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Map<String, List<GraphState>> next(int n) {
Map<String,List<GraphState>> result = new LinkedHashMap<String,List<GraphState>>(n);
String chunk, rows;
int i=0;
while (chunkScan.hasNext()&&i++<n) {
chunk = chunkScan.next().trim();
labelMatcher.reset(chunk);
stateMatcher.reset(chunk);
if (labelMatcher.find()&&stateMatcher.find()) {
rows = stateMatcher.group().replace(" ", "");
result.put(labelMatcher.group(), rowsToList(rows.split("\\n")));
}
}
return result;
}
我会这样做的简单方法。将每行抓取为String
,并将其填入,例如,匹配1或0后续空间模式的正则表达式。如果匹配,就像一排一样对待它。如果没有,请将其当作明文标签对待。通过检查每个标签的数据数组是否与第一个标签数据数组的大小相匹配,检查事后的行列大小一致性。
编辑:我没有意识到Scanner
类,虽然听起来很方便。我认为基本想法应该仍然大致相同......使用Scanner
解析您的输入,并自己处理大小问题。
此外,理论上,您可以生成一个匹配标签和整个数组的正则表达式,但我不知道是否可以生成一个能够保证它只匹配具有相同编号的行集的正则表达式的每行中的值。但是,为了设置更多的自动检查,您可能需要构建第二个正则表达式,该正则表达式与第一个条目的数组大小完全匹配,并将其用于所有其他正则表达式。我认为这是一种治疗比疾病更糟的情况。
您需要打开文件并使用readLine()遍历每一行,直到您点击文件结尾。
- 我假设你在遍历文件时做的是一致的。如果你想存储信息并在以后使用它,我会考虑使用某种类型的数据结构。
当你遍历这个时,你可以用一个简单的正则表达式来检查这行是否是一个标签名。如果不是,则根据''(空格字符)拆分该行,然后它将以数组的形式返回给您。然后根据一致的尺寸检查尺寸。
基本伪代码:
int consistentSize = 5; // assume you have a size in mind
while ((line = readLine()) != EOF)
{
// check for if label, if it's a simple name, you won't really need a regex
if (line == label)
{
// not sure if you want to do any consistency checking in here
} else {
String[] currLine = line.split(' ');
bool consist = true;
// now loop through currLine and do a check if each character is a number
for (int i = 0; i < currLine.size(); i++)
{
// can't remember java function for this (isNum() I think)
if (!currLine[i].isNum) { consist = false; break; }
}
// if got past this, the row has all numbers, therefore it is ok
// could easily add another array to keep track of rows that didn't have valid numbers and suhc
if (currLine.size() < consistentSize) System.out.println("row "+j + " is inconsistent");
}
}
你也可以加入另一个循环,如果你不知道你期望每一行的大小,并把一些逻辑中找到最常见的尺寸,然后找出没有按不匹配。我不确定你的一致性检查需要多复杂。