2009-08-24 8 views
1

Je passe une chaîne dans ma méthode de parser de chanson et elle échoue et je n'arrive pas à comprendre pourquoi. Tout est de retour nul ou 0.Pourquoi mon matcher échoue-t-il?

Ma méthode d'analyse syntaxique est

public static Song parseSong(String songString){ 
    Map<String, String> songMap = new HashMap<String, String>(); 
    Pattern pattern = Pattern.compile(".*<key>(.+)</key><(.+)>(.+)</.+>.*\n"); 
    Scanner scanner = new Scanner(songString); 
    if(scanner.hasNext(pattern)) 
    { 
    String line = scanner.next(pattern); 
    Matcher matcher = pattern.matcher(line); 
    MatchResult result = matcher.toMatchResult(); 
    songMap.put(result.group(1), result.group(3)); 
    } 
    int count = 0, rating = 0; 
    try{ 
    count = Integer.parseInt(songMap.get("Play Count")); 
    } 
    catch(Exception e) 
    { 
    //bury this for now will handle when rest is working 
    } 
    try{ 
    rating = Integer.parseInt(songMap.get("Rating")); 
    } 
    catch(Exception e) 
    { 
    //bury this for now will handle when rest is working 
    } 
    return new Song(songMap.get("Name"), songMap.get("Artist"), songMap.get("Album"), 
     songMap.get("Genre"), count, rating, songMap.get("Location")); 

}

 String songString = "<key>Track ID</key><integer>160</integer>\n"+ 
    "<key>Name</key><string>Ashley</string>\n"+ 
    " <key>Artist</key><string>Escape the Fate</string>\n"+ 
    " <key>Composer</key><string>Luca Gusella</string>\n"+ 
    " <key>Album</key><string>This War Is Ours</string>\n"+ 
    " <key>Genre</key><string>Metal</string>\n"+ 
    "<key>Kind</key><string>AAC audio file</string>\n"+ 
    " <key>Size</key><integer>7968219</integer>\n"+ 
    " <key>Total Time</key><integer>246503</integer>\n"+ 
    " <key>Track Number</key><integer>17</integer>\n"+ 
    " <key>Year</key><integer>2005</integer>\n"+ 
    " <key>Date Modified</key><date>2009-07-27T01:17:29Z</date>\n"+ 
    " <key>Date Added</key><date>2009-07-27T01:17:00Z</date>\n"+ 
    "<key>Play Count</key><integer>150</integer>\n"+ 
    " <key>Bit Rate</key><integer>256</integer>\n"+ 
    " <key>Sample Rate</key><integer>44100</integer>\n"+ 
    " <key>Comments</key><string>\"Amanda\" performed by Aisha Duo from the CD Quiet Songs, courtesy of Obliq Sound. Written by Luca Gusella, published by Editions ObliqMusic (GEMA). All Rights Reserved. Used by Permission. </string>\n"+ 
    " <key>Skip Count</key><integer>1</integer>\n"+ 
    " <key>Skip Date</key><date>2009-07-27T01:46:32Z</date>\n"+ 
    " <key>Artwork Count</key><integer>1</integer>\n"+ 
    " <key>Persistent ID</key><string>A4D6F35FE9F41B58</string>\n"+ 
    " <key>Track Type</key><string>File</string>\n"+ 
    " <key>Location</key><string>file://localhost/C:/Documents%20and%20Settings/MB24244/Desktop/music/07%20Knees.m4a</string>\n"+ 
    "<key>File Folder Count</key><integer>4</integer>\n"+ 
    "afgjdhfshsgsughghanoise\n"+ 
    "<key>Library Folder Count</key><integer>1</integer>\n"+ 
    "<key>Rating</key><integer>100</integer>"; 

Quelqu'un peut-il aider à expliquer ce qui ne va pas avec mon approche et pourquoi les groupes ne fonctionnent pas (qui est ce qui semble être le problème)

Répondre

7

Pourquoi ne pas utiliser un analyseur XML à parse XML?

Bien que regarder l'exemple XML ce n'est pas agréable car il est essentiellement une modélisation map au lieu de modéliser un <song>

En regardant votre regex pourquoi vous cherchez la ligne de fin \n. Il semble que vous apportiez chaque ligne à tour de rôle et je ne crois pas que ceux-ci contiendront le nouveau caractère de ligne.

Cependant cette méthode qui n'utilise pas le scanner fonctionne. Notez que j'ai modifié l'expression rationnelle pour supprimer la fin de la ligne.

Map<String, String> songMap = new HashMap<String, String>(); 

    Pattern pattern = Pattern 
      .compile(".*<key>(.+)</key><(.+)>(.+)</.+>.*"); 

    String[] lines = songString.split("\n"); 

    for (String line : lines) { 
     Matcher matcher = pattern.matcher(line); 
     if (matcher.matches()) { 
      songMap.put(matcher.group(1), matcher.group(3)); 
     } 
    } 

Vous pouvez probablement aussi le faire fonctionner avec le scanner.

+0

Eh bien, j'écris l'application c'est comme un exercice d'entraînement et j'espérais apprendre un peu sur l'analyse que je veux dire Il était facile d'en arriver là. J'essaye d'analyser une bibliothèque de musique d'itunes.xml pour un projet de compagnie. Si je ne peux pas comprendre, je vais passer à quelqu'un d'autre a déjà écrit. –

+0

J'ai fait quelques petites modifications pour obtenir une implémentation fonctionnelle de votre code. – pjp

1

Ensuite, votez pour faire du XML un XML valide (nœud de premier niveau unique), puis utiliser un analyseur XML.

Mais je soupçonnerais le \ n à la fin, je ne sais pas combien la bibliothèque regex de Java aime ça?

0

N'essayez pas d'écrire un analyseur, sauf si vous connaissez déjà les règles de ces fichiers à analyser.

La regex que vous avez écrite ne respecte pas la plupart des règles des fichiers XML.

Si c'est la première fois que vous écrivez une regex, vous devriez probablement essayer d'apprendre quelque chose d'un peu plus facile à analyser. Peut-être même un simple format de fichier que vous créez vous-même.

1
if(scanner.hasNext(pattern)) 
{ 
    String line = scanner.next(pattern); 
    Matcher matcher = pattern.matcher(line); 
    matcher.toMatchResult(); 
    songMap.put(result.group(1), result.group(3)); 
} 

Le matcher vous avez créé avec pattern.matcher (ligne) est un objet flambant neuf qu'il ne sait rien sur le match que vous venez de trouver avec le scanner. Ce que vous voulez, c'est ceci:

MatchResult result = scanner.match(); 

Cette regex a aussi besoin de travail. Si chaque enregistrement apparaît sur sa propre ligne, vous n'avez pas besoin de le masquer avec ".*" à chaque extrémité et vous n'avez pas besoin de faire correspondre le saut de ligne. En outre, je suggère que vous utilisez ".+?" au lieu de ".+" où il apparaît. Pour la raison, read this.

0

+1 pour utiliser. +? En outre, je suggère de ne pas utiliser le motif dans ce cas, car vous semblez avoir un fichier assez facile à analyser.Je: - diviser le fichier ligne par ligne - Méthodes de chaîne simple pour obtenir le contenu (il semble qu'il n'y a que trois différentes balises dans votre XML)

Si le format de fichier serait changer et devenir plus compliqué je voudrais aller avec le vrai XMLParser et juste traverser l'arbre XML pour obtenir ce dont vous avez besoin :)

Questions connexes