Question

Pour mes structures de données de projet, l'objectif est de lire dans un fichier fourni contenant plus de 10000 chansons avec l'artiste, le titre et les paroles clairement marqués, et chaque chanson est séparée par une ligne avec un seul guillemet. J'ai écrit ce code pour analyser le fichier texte, et il fonctionne, avec une durée d'un peu moins de 3 secondes à
lire les 422k lignes de texte
créer un objet chanson
Ajouter a déclaré Song à un ArrayList

Le code d'analyse syntaxique je l'ai écrit est:

if (songSource.canRead()) {  //checks to see if file is valid to read
    readIn= new Scanner(songSource);
    while (readIn.hasNextLine()) {
 do {
     readToken= readIn.nextLine();

             if (readToken.startsWith("ARTIST=\"")) {
  artist= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("TITLE=\"")) {
  title= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("LYRICS=\"")) {
  lyrics= readToken.split("\"")[1];
      } else {
  lyrics+= "\n"+readToken;
      }//end individual song if block
 } while (!readToken.startsWith("\"")); //end inner while loop

    songList.add(new Song(artist, title, lyrics));

    }//end while not EOF 
} //end if file can be read 

Je parlais avec mon professeur Intro algorithmes sur le code pour ce projet, et il a déclaré que je devrais essayer d'être plus défensif dans mon code pour permettre des incohérences dans les données fournies par d'autres personnes. Au départ, j'utilisais si / blocs d'autre entre l'artiste, les champs Titre et Paroles, et sur sa suggestion que je changé en séquentiel si les déclarations. Bien que je puisse voir son point, en utilisant cet exemple de code, comment puis-je être plus sur la défensive permettant des incohérences d'entrée?

Était-ce utile?

La solution

Vous présumez que l'entrée est parfait. Si vous regardez la façon dont votre application est actuellement installée, sur la base d'une lecture rapide de votre algorithme données ressemblerait à ceci

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"

Mais considérez le cas

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"

Sur la base de votre algorithme, vous avez maintenant 2 chansons caractérisé comme

songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
             Song("Peter", "HELLO WORLD", "Sing Song All night long") }

Avec l'algorithme actuel, l'artiste et le titre sont exposés et affichera dans la 2ème chanson, même si elles ne sont pas définis. Vous devez réinitialiser vos trois variables.

dans votre autre vous abandonnes juste la ligne complète en paroles. Que faire si vous aviez déjà sorti Lyrics, vous surchargez maintenant. Cas de test

 ARTIST="John"
 LYRICS="Sing Song All night long"
 TILET="HELLO WORLD"
 "

Pensez à envoyer ce dossier à un état d'erreur. Ainsi, lorsque la lecture du lot est terminé, un rapport d'erreur peut être généré et fixe.

vous considérez seulement aussi EOF après un artiste a été lu. Et si le EOF se produit, vous allez obtenir une exception là. Au cours de l'artiste lu et le fichier ne se termine pas ». Dans votre do / while ajouter un autre vérifier hasNextLine ()

Autres conseils

Je remplacerais par exemple:.

artist= readToken.split("\"")[1];

avec

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

D'autres modifications comprennent:

  1. réinitialiser les variables locales (afin de ne pas accidentellement le mauvais artiste pour une chanson, si aucun artiste est fourni pour une chanson après la première)
  2. décider quoi faire si certaines données sont manquantes - voulez-vous encore ajouter la chanson à la liste des chansons

Dans le monde réel, il y a des garanties données en ce qui concerne l'intégrité des données. Dans le cas de faire face à l'entrée d'utilisateur (que ce soit à partir de stdin ou un fichier) il existe un projet paradigme défini pour notifier à l'utilisateur d'un problème qui nécessite une attention.

Par exemple, lorsqu'un code compilation du compilateur ou un shell l'exécution d'un script rencontre une incohérence qu'il pourrait arrêter et imprimer la ligne contenant l'incompatibilité avec une deuxième ligne en dessous qui utilise le symbole « ^ » pour indiquer l'emplacement du problème .

Alors, voici quelques questions de base à se poser:
1. chaque ligne garanti pour contenir tous les domaines
2. Est-ce l'ordre des champs garantis?

Si ce sont les conditions du contrat d'entrée et sont violés, vous devez ignorer / signaler la ligne. Si elles ne sont pas les conditions de l'entrée, vous devez manipuler .. que vous ne disposez pas actuellement.

Je vois deux choses qui manquent ici Jason.

Je pense que le if / else était bien et il ne changera pas la logique. Cependant, vous devez limiter la portée de vos variables autant que possible. En déclarant l'artiste, le titre, etc. à l'intérieur de la boucle while, ils seront initialisées à zéro (ou autre) si une entrée est manquante l'artiste alors il ne sera pas la valeur de la dernière entrée.

En outre, ce qui se passe si le titre, artiste, etc. a une citation en elle? Comment est-ce manipulé? Que diriez-vous Lyrics qui semblent avoir plusieurs lignes droite?

Qu'est-ce qui se passe s'il y a un champ inconnu - peut-être une faute d'orthographe? Il sera ajouté à la fin de paroles qui ne semble pas juste. Une seule fois le champ PAROLES a été trouvé si vous ajoutez à cela. Si des paroles est nulle alors il commencera par « null ».

Voici quelques questions qui pourraient être abordées:

  • Votre code suppose qu'il n'y a pas d'espace avant (par exemple) "ARTISTE", aucun autour du signe "=" et ainsi de suite.

  • Votre code suppose que les mots-clés sont en majuscules. Quelqu'un pourrait utiliser des minuscules ou majuscules et minuscules.

  • Votre code suppose qu'une ligne qui ne commence pas par keyword=\" est une continuation des paroles de la chanson. Mais si l'utilisateur est entré ARTOST="Sting"? Ou si l'utilisateur a essayé d'utiliser deux lignes pour un nom d'artiste?

Enfin, je ne suis pas convaincu que le remplacement de « autre si » par « si » dans ce cas a influeraient sur la robustesse du code.

Traiter avec des exceptions (je suppose Scanner pourrait jeter InputMismatchException pour un caractère non valide).

Il ressemble à la boucle do { } while (...) de l'infini peut si le fichier est mal formé, et la fin du fichier est atteinte.

empêche Rien artist ou title d'être vide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top