Java Scanner头痛

时间:2009-10-09 17:11:10

标签: java java.util.scanner delimiter

我有一个文本文件,如下所示:

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(尽管可能不是)。

如何使用扫描仪获取每个名称+行块?是否有任何优雅的方法来强制行数的一致性(如果它们不一致,则提供某种反馈)?

我认为可能有一种方便的方法可以使用聪明的分隔符规范,但我似乎无法使其正常工作。

3 个答案:

答案 0 :(得分:1)

我会以简单的方式做到这一点。将每一行作为String抓取,然后通过匹配1-or-0-by-by-space模式的正则表达式来提供它。如果匹配,则将其视为一行。如果没有,请将其视为明文标签。通过检查每个标签的数据数组是否与第一个标签的数据数组的大小相匹配,检查事后的行列大小一致性。

编辑:我不知道Scanner课程,虽然听起来很方便。我认为基本思想应该大致相同...使用Scanner来解析你的输入,并自己处理大小的问题。

另外,从理论上讲,你可以生成一个与标签和整个数组匹配的正则表达式,虽然我不知道你是否可以生成一个能保证它只匹配具有相同数量的数组的行每行中的值。但是,为了设置更多自动检查,您可能需要构造第二个正则表达式,该表达式与第一个条目的数组大小完全匹配,并将其用于所有其他条目。我认为这是治愈比疾病更糟的情况。

答案 1 :(得分:1)

更好的是,在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;
}

答案 2 :(得分:0)

您需要打开文件并使用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");
    }
}

如果您不知道每行所需的大小,并添加一些逻辑来查找最常见的大小,然后找出不匹配的内容,您还可以添加另一个循环。我不确定你的一致性检查有多复杂。