2010-10-01 15 views
2

Je viens de rejoindre StackOverflow après avoir trouvé beaucoup de bonnes réponses ici dans le passé. Voici ma première question:Java: comment collecter des fragments de données entrants dans des chaînes correctement terminées pour une analyse ultérieure?

EDIT: Je me sens mal ... ma première question à StackOverflow s'est révélée être une "chasse aux oies sauvages". Le problème est dans les données , pas le code lisant les données. Je cherchais une solution au mauvais endroit! Je vais expliquer dans un commentaire ci-dessous.

Veuillez ne pas tenir compte de cette question.

Dans mon application, les données arrivent en fragments (ce sont des données série). Je veux passer les données à une méthode qui l'analysera. Mais je veux seulement transmettre des lignes correctement terminées. Les lignes seront terminées par '\ r' (return char). Parfois, un fragment de données arrive avec plusieurs lignes terminées. Mais parfois un fragment de données arrive qui n'a pas encore de terminateur (le terminateur arrivera plus tard).

Mon but est de pouvoir envoyer uniquement des lignes terminées correctement (lignes complètes) à dataProcessor.logSerialData. (Le code fonctionne sans cette exigence, mais je pourrais écrire beaucoup plus de code si je pouvais répondre à cette exigence.La logique d'analyse - pas montré ici - serait plus facile à maintenir.)

Voici mon code qui fonctionne (mais ne répond pas à ma nouvelle exigence):

case SerialPortEvent.DATA_AVAILABLE: 
      try 
      { 
       int len = -1; 
       while ((len = in.read(readBuffer)) > 0) 
       { 
        if (len > 0) 
        { 
         String s = new String(readBuffer, 0, len); 
         if (dataProcessor != null) 
         { 
          dataProcessor.logSerialData(s); 
         } 
         else 
         { 
          Logger.log("ERROR: packetReceiver is null"); 
         } 
        } 
       } 
      } 
      catch (IOException ex) 
      { 
       Logger.log(ex); 
       return; 
      } 

Voici un exemple de l'une des nombreuses choses que j'essayé cela ne fonctionne pas. Il provoque en quelque sorte des erreurs dans le flux de données.

private static final String REGEX = ".*\\r"; 
private Pattern p = Pattern.compile(REGEX); 

public void serialEvent(SerialPortEvent e) 
{ 
    byte[] readBuffer = new byte[11000];//tried many values for buffer size 

    switch (e.getEventType()) 
    { 
     case SerialPortEvent.DATA_AVAILABLE: 
      try 
      { 
       int len = -1; 
       while ((len = in.read(readBuffer)) > 0) 
       { 
        if (len > 0) 
        { 
         String input = new String(readBuffer, 0, len); 
         Matcher m = p.matcher(input); 
         int count = 0; 
         while (m.find()) 
         { 
          count++; 
          String terminatedLine = m.group(); 
          if (!terminatedLine.isEmpty()) 
          { 
           completedLines.add(terminatedLine); 
          } 
         } 
        } 
       } 
      } 
      catch (IOException ex) 
      { 
       Logger.log(ex); 
       return; 
      } 
      for (String line : completedLines) 
      { 
       dataProcessor.logSerialData(line); 
      } 

Des suggestions? (En fait, aucune idée pourquoi le nouveau code introduit des erreurs dans le flux de données?) Chaque variation du code de travail que j'ai essayé ne fonctionne pas correctement.J'ai essayé les méthodes regex et non-regex et d'autres choses. fonctionne est l'exemple de travail ci-dessus. traitement des données série semble très délicat, je pourrais utiliser un peu d'aide.

+0

Une classe StringReader serait-elle plus appropriée ici? – Starkey

+0

Je mentionnerai que la vitesse semble être un facteur important. Par exemple, une boucle caractère par caractère, même si je peux dire que la logique est parfaite, introduit des erreurs. Je peux spéculer que c'est trop lent et que les données sérielles entrantes sont corrompues.(Cela semble étrange, je sais.) Pour des raisons de vitesse, j'ai essayé une regex compilée. Le problème avec mon code regex est de savoir comment gérer les fragments entrants qui ne correspondent pas à la chaîne regex? Je dois les sauvegarder et leur ajouter les fragments suivants. Je pense que le matcher peut le faire, mais le code que j'ai écrit ci-dessus ne le fait pas correctement. – MountainX

Répondre

0

Aucune des différentes méthodes de lecture par lignes travaillées. La méthode originale n'a fonctionné que parce qu'elle ne recherchait pas de terminaison de ligne. En voyant qu'aucune des méthodes "sûres" n'a fonctionné de manière prévisible, j'ai fait des recherches plus approfondies. Il semble qu'il y ait une certaine incohérence dans les données entrantes en ce qui concerne les terminateurs de ligne. Java voit les terminateurs là où il n'y en a pas et manque les terminateurs qui s'y trouvent. Après avoir passé plusieurs jours là-dessus, je pense que je vais juste revenir à la méthode originale qui fonctionnait sans chercher de terminaison de ligne.

Désolé pour la question bidon.

0

Cela devrait fonctionner au besoin.

private String remains = ""; 
... 

int len = -1; 
while ((len = in.read(readBuffer)) > 0) { 
    if (len > 0) { 
     String input = remains + new String(readBuffer, 0, len); 
     Matcher m = p.matcher(input); 
     int last = 0; 
     while (m.find()) { 
      String terminatedLine = m.group(); 
      last = m.end(0); 
      if (!terminatedLine.isEmpty()) completedLines.add(terminatedLine); 
     } 
     remains = input.substring(last); 
    } 
} 
0

Il est possible d'envelopper le InputStream dans un Reader en BufferedReader et lire des lignes à partir de cela?