2009-08-05 5 views
0

J'ai un programme qui suit un fichier en croissance. J'essaie d'éviter de saisir une ligne partielle du fichier (par exemple lire avant que la ligne soit complètement écrite par l'autre processus). Je sais que cela se passe dans mon code, donc j'essaie de l'attraper spécifiquement.std :: getline et eol vs eof

Existe-t-il une façon saine de faire cela?

Voici ce que je suis en train:

if (getline (stream, logbuffer)) 
{ 
    if (stream.eof()) 
    { 
     cout << "Partial line found!" << endl; 
     return false; 
    } 
    return true; 
} 
return false; 

Cependant, je ne peux pas reproduire facilement le problème, donc je ne suis pas sûr que je détecter avec ce code. std :: getline supprime les retours à la ligne, donc je ne peux pas vérifier le buffer pour un retour chariot. Mon message de journal (ci-dessus) ne se déclenche JAMAIS.

Existe-t-il un autre moyen de vérifier ce que je veux détecter? Est-il possible de savoir si la dernière ligne que j'ai lue a frappé EOF sans trouver de caractère EOL?

Merci.

+1

Pourquoi ne pas modifier l'autre processus pour vider uniquement son tampon de sortie dans le fichier sur les nouvelles lignes? –

+0

Je ne possède pas l'autre processus, ni aucun contrôle sur son comportement. Le plaisir de l'intégration. – Joe

+0

En effet. Déposer une plainte auprès de l'autre ministère? –

Répondre

3

Ce ne sera jamais vrai:

if (getline (stream, logbuffer)) 
{ 
    if (stream.eof()) 
    { 
     /// will never get here 

Si getline() travaillé, le courant ne peut pas être dans un état de EOF. Les tests d'état eof() et associés ne fonctionnent que sur les résultats d'une opération de lecture précédente, tels que getline() - ils ne prédisent pas ce que la lecture suivante fera. Pour autant que je sache, il n'y a aucun moyen de faire ce que vous voulez. Cependant, si l'autre processus écrit une ligne à la fois, les problèmes que vous dites que vous rencontrez devraient être très rares (non-existant dans mon expérience), dépendant dans une certaine mesure du système d'exploitation que vous utilisez. Je soupçonne que le problème est ailleurs, probablement dans votre code. Résoudre un fichier est une chose très courante, et il n'est normalement pas nécessaire de recourir à un code spécial pour le faire.

Cependant, si vous trouvez que vous avez besoin de lire les lignes partielles, l'algorithme de base est la suivante:

forever do 
    wait for file change 
    read all possible input using read or readsome (not getline) 
    chop input into lines and possible partial line 
    process as required 
end 
+1

Pas vrai. Si la dernière ligne du fichier ne se termine pas par newline, getline réussira (failbit n'est pas défini) mais le flux passe toujours à l'état EOF (parce que getline a essayé de lire plus de caractères). Même si eofbit est défini, getline renvoie tout ce qui a été lu de la dernière ligne dans logbuffer. – Tronic

0

Même si l'autre programme ne se fait pas l'écriture du fichier, dans le fichier qui est où le la ligne se termine, il n'y a donc aucun moyen de faire la différence autrement que d'attendre de voir si l'autre programme écrit quelque chose de nouveau. Si vous voulez juste savoir si la ligne se termine par une nouvelle ligne ou non, vous pouvez écrire votre propre fonction getline qui se lit jusqu'à ce qu'elle frappe un retour à la ligne mais ne la dépouille pas.

+0

Je suppose que ce que je voudrais savoir, c'est si la dernière ligne lue se terminait par une nouvelle ligne ou non. – Joe

0

Je dois prendre un problème avec la déclaration que vous avez fait ici:

Cependant, je ne peux pas reproduire facilement le problème, donc je ne suis pas sûr que je détecter avec ce code.

Il semble que d'après ce que vous avez dit, il serait extrêmement facile de reproduire votre problème, si c'est ce que vous avez dit. Vous pouvez facilement créer un fichier texte dans un éditeur de texte - assurez-vous que le dernier se termine par un EOF au lieu de passer à une nouvelle ligne. Puis pointez votre programme sur ce fichier et voir quels résultats.

+0

Hm. Bon point. – Joe

+0

Cela ne reproduit pas vraiment le problème. Il reproduit l'explication de l'OP, qui pourrait bien être erronée. –

1

Un objet istream tel qu'un std::cin a un get function qui s'arrête de lire lorsqu'il arrive à un retour à la ligne sans l'extraire du flux. Vous pouvez alors peek() ou get() pour voir s'il s'agit bien d'une nouvelle ligne. Le hic, c'est que vous devez connaître la longueur maximale d'une ligne provenant de l'autre application. Exemple de code (non testé) suit ci-dessous:

char buf[81]; // assumes an 80-char line length + null char 
memset(buf, 0, 81); 

if (cin.get(buf, 81)) 
{ 
    if (cin.peek() == EOF) // You ran out of data before hitting end of line 
    { 
     cout << "Partial line found!\n"; 
    } 
} 
+0

Mon commentaire est plutôt en retard, mais je crois que c'est la bonne réponse. Utiliser 'std :: istream :: peek()' pour vérifier 'EOF' vous indiquera si' std :: getline() 'est retourné parce qu'il a trouvé un retour à la ligne ou parce qu'il a atteint la fin du fichier. Je viens de parler de ce problème dans [mon dernier article de blog] (https://v1ntage.io/2018/01/10/episode-007-handling-eof-with-stdgetline/). – v1bri

Questions connexes