2009-10-09 7 views
1

J'ai un fichier texte qui ressemble à:Java Scanner Maux de tête

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 

à savoir, une étiquette suivie d'un texte clair quelques lignes avec 1/0 séparées par des espaces. Le nombre de lignes de 1/0 est variable, mais chaque ligne entre deux étiquettes particulières devrait avoir le même nombre de 1/0 (mais potentiellement pas).

Comment puis-je saisir chaque morceau de nom + lignes avec un scanner? Existe-t-il un moyen élégant de renforcer la cohérence sur le nombre de lignes (et de fournir une sorte de retour si elles ne sont pas cohérentes)?

Je pense qu'il pourrait y avoir un moyen pratique avec une spécification intelligente de délimiteur, mais je ne peux pas sembler fonctionner.

Répondre

1

Mieux encore, après une helpful answer to another question (merci 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

Je le ferais de la manière la plus simple. Saisissez chaque ligne sous la forme String et faites-la passer par, disons, une expression régulière correspondant au modèle 1-or-0-suivi-par-espace. Si cela correspond, traitez-le comme une rangée. Si ce n'est pas le cas, traitez-le comme une étiquette en texte clair. Vérifiez la cohérence taille-colonne-taille après le fait en vérifiant que le tableau de données de chaque étiquette correspond à la taille du tableau de données de la première étiquette.

EDIT: Je n'étais pas au courant de la classe Scanner, bien que cela semble pratique. Je pense que l'idée essentielle devrait toujours être à peu près la même ... utiliser le Scanner pour analyser votre entrée, et gérer vous-même la question des tailles. En outre, en théorie, vous pourriez produire une expression régulière qui correspondrait à l'étiquette et au tableau entier, bien que je ne sache pas si vous pouvez en produire une qui garantira qu'elle ne correspond qu'à des ensembles de lignes ayant le même numéro des valeurs dans chaque rangée. Mais alors, pour mettre en place une vérification plus automatisée, vous auriez probablement besoin de construire une seconde expression régulière qui correspond exactement à la taille du tableau de la première entrée, et l'utiliser pour tous les autres. Je pense que c'est un cas où le remède est pire que la maladie.

0

Vous devez ouvrir le fichier et faire une boucle sur chaque ligne avec readLine() jusqu'à ce que vous atteigniez la fin du fichier.

- Je suppose que vous faites de la cohérence lorsque vous parcourez le fichier. Si vous voulez stocker les informations et les utiliser plus tard, j'utiliserais un type de structure de données. Lorsque vous parcourez cela, vous pouvez vérifier la ligne avec une simple regex pour vérifier s'il s'agit d'un nom d'étiquette. Si ce n'est pas le cas, divisez la ligne en fonction de l'espace ('' (caractère espace) et il vous reviendra dans un tableau. Ensuite, vérifiez la taille en fonction d'une taille cohérente.

pseudocode de base:

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

Vous pouvez également ajouter une autre boucle si vous ne connaissez pas la taille que vous attendez pour chaque ligne et de mettre une certaine logique pour trouver la taille la plus commune et comprendre alors ce doesn ne correspond pas. Je ne suis pas sûr de la complexité de la vérification de la cohérence.

Questions connexes