2009-10-09 4 views
1

У меня есть текстовый файл, который выглядит следующим образом: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/0s (хотя потенциально это может быть не так).

Как я могу захватить каждое имя + ряд строк со сканером? Есть ли элегантный способ обеспечить согласованность количества строк (и обеспечить некоторую обратную связь, если они не соответствуют)?

Я думаю, что может быть удобный способ с умной спецификацией разделителя, но я не могу показаться, что это работает.

ответ

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; 
} 
1

Я бы сделал это простым способом. Возьмите каждую строку как String и проведите через, скажем, регулярное выражение, которое соответствует шаблону 1 или 0 после пробела. Если он соответствует, относитесь к нему как к ряду. Если нет, относитесь к нему как к ярлыку с открытым текстом. Проверьте соответствие последовательности столбцов строки и столбца, проверив, что массив данных каждого ярлыка соответствует размеру массива данных первого ярлыка.

EDIT: Я не знал о классе Scanner, хотя он звучит удобно. Я думаю, что основная идея должна быть примерно одинаковой ... используйте Scanner, чтобы проанализировать ваш ввод и сами обрабатывать вопрос о размерах.

Кроме того, теоретически вы можете создать регулярное выражение, которое будет соответствовать ярлыку и всему массиву, хотя я не знаю, можно ли создать тот, который гарантирует, что он соответствует только наборам строк с одинаковым числом значений в каждой строке. Но тогда, чтобы настроить более автоматическую проверку, вам, вероятно, потребуется создать второе регулярное выражение, которое точно соответствует размеру массива первой записи и использовать его для всех остальных. Я думаю, что это случай, когда лечение хуже, чем болезнь.

0

Вам нужно будет открыть файл и пропустить через каждую строку с readLine(), пока вы не достигнете конца файла.

- Я предположил, что вы выполняете согласованность при перемещении файла. Если вы хотите сохранить информацию и использовать ее позже, я бы рассмотрел возможность использования какой-либо структуры данных.

По мере этого вы можете проверить строку простым регулярным выражением, чтобы проверить, является ли это именем метки. Если нет, разделите строку на основе символа '' (пробел) и он вернется к вам в массиве. Затем проверьте размер на основе согласованного размера.

Basic псевдокод:

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"); 
    } 
} 

Вы также мог бы добавить еще один цикл, если вы не знаете размера вы ожидаете для каждой строки и поставить определенную логику, чтобы найти наиболее общий размер, а затем выяснить, что оленья кожу 't матч. Я не уверен, насколько сложна ваша проверка согласованности.