Analyse/mise en forme des données à partir du port série - C#
J'ai développé un petit programme qui écoute sur un port série. Mon programme est de recevoir des données. Le problème est, il n'est pas afficher dans le format souhaité (une chaîne). Les données de mon programme est de la réception est disponible en deux chaînes de caractères, par exemple:
ID:34242 State:NY
Postal:12345 StreetType:Ave
Son affichée par morceaux et une partie des données est transmis suivant les lignes en tant que tel:
ID:34242
State:N
Y Zip:12
345 Street
Type:Ave
J'ai utilisé le SerialDataReceive Gestionnaire d'Événement pour recevoir mes données et il ressemble à ceci:
private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort spL = (SerialPort) sender;
int bufSize = 20;
Byte[] dataBuffer = new Byte[bufSize];
Console.WriteLine("Data Received at"+DateTime.Now);
Console.WriteLine(spL.Read(dataBuffer, 0, bufSize));
string s = System.Text.ASCIIEncoding.ASCII.GetString(dataBuffer);
Console.WriteLine(s);
}
Comme vous pouvez le voir, j'ai récupérer les octets dans le tampon, de créer un tableau d'octets pour stocker les données et utiliser le codage ASCII pour traduire les octets en une chaîne de caractères. J'ai essayé d'utiliser ReadLine() mais je n'est pas le cas affiché avec cette fonction. Personne ne sait de toute autre manière à analyser et mettre en forme les données dans une chaîne de caractères?
OriginalL'auteur Rick | 2012-02-29
Vous devez vous connecter pour publier un commentaire.
Le problème est, comme vous l'aurez deviné, que l'événement DataReceived est soulevée dès que les données ont été reçues sur le port série. Il peut ne pas être d'un dossier complet; le SerialPort objet n'a aucune idée de ce que vous considérez être "assez" données importantes, ou réalisable.
La solution habituelle est de maintenir un autre tampon de réception de données, contenant les données que vous avez reconnu comme incomplet. Lorsque les données sur le port et votre événement se déclenche, il faut d'abord prendre ce qui est dans la mémoire tampon et ajouter à ce que vous avez déjà reçues. Ensuite, vous devez commencer au début de ce mémoire tampon de données et d'inspecter les données reçues, à la recherche de modèles connus de la atomique en "morceaux" de données qui ont un sens pour vous; par exemple, disons que la première chose que vous allez recevoir est
"ID: 12"
. Vous prenez cela, le mettre dans la mémoire tampon, puis analyser la mémoire tampon de la recherche d'un modèle défini par une expression régulière"ID: \d*? "
. Parce que l'espace de fin n'est pas présent dans votre tampon, votre modèle ne parvient pas à trouver quoi que ce soit de sens, et donc, vous savez maintenant que vous n'avez pas reçu l'intégralité d'un message.Puis, sur la prochaine levée de l'DataReceived cas, vous tirez
"453 Sta"
de la série de la mémoire tampon. Vous l'ajouter à ce que vous avez déjà et obtenir"ID:12453 Sta"
, et lorsque vous appliquez les regex, vous obtenez le match "ID: 12345 ". Vous passez de cette dans une méthode de traitement supplémentaire (affichage de la console, peut-être), et retirez la même chaîne à partir de l'avant de la mémoire tampon, de laisser les "Sta". La numérisation à nouveau vous ne trouvez pas autre chose d'intéressant, de sorte que vous laissez ce que vous avez, et le cycle se répète de données aws continue à venir. Évidemment, vous allez tester modèles plus que juste l'ID de modèle; vous pouvez rechercher un ensemble de la "chaîne" vous vous attendez à recevoir, comme"ID: \d*? State: \w{2} "
. Vous pouvez même conserver les données dans la mémoire tampon jusqu'à ce que vous avez à la fois des chaînes pour un enregistrement:"ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*? "
.De toute façon, vous aurez besoin de déterminer si les données reçues sont soit fiable "de longueur fixe" (ce qui signifie que chaque chaîne d'un type particulier aura toujours le même nombre d'octets ou de caractères), ou de manière fiable "délimité" (ce qui signifie qu'il sera de certains personnages ou combinaison de caractères qui sépare toujours des éléments importants de données). Si aucune de ces situations s'applique, il peut être très difficile d'analyser les données dans un seul champ de blocs.
Voici un exemple basé sur ce que vous avez déjà:
OriginalL'auteur KeithS
Voir astuce #1
http://blogs.msdn.com/b/bclteam/archive/2006/10/10/top-5-serialport-tips-_5b00_kim-hamilton_5d00_.aspx
Fondamentalement, vous n'êtes pas assuré d'obtenir le nombre d'octets. Vous obtiendrez ce qui est disponible pour la lecture, jusqu'à count octets - pas plus que de les compter, mais peut-être moins.
Dans votre exemple de code, la méthode de Lecture retourne le nombre d'octets lus de sorte que vous pouvez regarder et agir en conséquence. Si vous vous attendez à 20 et bénéficiez de 10, vous pouvez garder la lecture et la création de vos données jusqu'à ce que finalement vous avez 20 octets. Si vos données n'est pas une longueur fixe, alors vous aurez à garder en regardant ce que vous avez reçu jusqu'à présent de décider si vous avez un bloc de données.
Notez que la méthode de Lecture prend un offset. C'est utile pour ce problème.
Hé les gars, j'ai été en mesure de venir avec la solution. J'ai reconstruire ma SerialDataReceive Gestionnaire d'Événement dans une façon qui me permet de recueillir toutes mes octets (37) lire tous ces octets et de les convertir en chaîne de caractères. Je suis en train de voir les données dans mon programme exactement comme ses envoyés à partir du port. Merci à vous tous pour vous réponses rapides. Ils m'ont beaucoup aidé.
OriginalL'auteur hatchet
En supposant que il n'y a pas de caractère de fin, quelque chose comme cela peut fonctionner. La partie la plus délicate est de savoir quand imprimer une nouvelle ligne.
Vous pouvez essayer d'insérer un retour à la ligne avant chaque
ID:
(par exemple, remplacer"ID:"
avec"\r\n\ID:"
). Ce sera encore parfois échouer lorsque vous recevezStreetType:AveI
d'abord et ensuite"D:23566 St"
suivant. Pour résoudre ce problème, vous pouvez simplement regarder pour toutI
aprèsStreetType:
, mais ce n'est pas aussi facile que ça, soit-si vous voyez345 Stre
,etTy
,pe:RdI
. Aussi, siI
est un caractère valide (tType:DRI
,VE ID:23525
)?Je pense que le code suivant doit gérer correctement ces cas. Notez que je suis passé de
Console.WriteLine
àConsole.Write
et ajouter manuellement la nouvelle ligne en cas de besoin:Maintenant, le seul problème restant est que si le dernier enregistrement n'a vraiment fin en
I
ouID
, il ne sera jamais imprimé. Un périodique délai d'attente pour rincer la chaîne précédente pourrait résoudre ce problème, mais il introduit (beaucoup) plus de problèmes de son propre.OriginalL'auteur Justin