2010-08-10 8 views
4

Je souhaite ajouter deux fichiers texte ensemble.Pourquoi StreamReader.ReadLine() renvoie une valeur pour un fichier d'une ligne sans saut de ligne?

J'ai un fichier avec un retour chariot à la fin. Observez le fichier A qui est de 28 octets.

c'est une ligne dans le fichier \ n

alors j'ai un autre fichier qui est la même chose sans la nouvelle ligne. Observe le fichier B qui est de 26 octets.

c'est une ligne dans le fichier

Je veux ajouter le même fichier lui-même (fichier A à A, et le fichier B to B) et de comparer le nombre d'octets.

Cependant, lors de l'utilisation StreamReader.ReadLine() dans le dossier A, je reçois une valeur retournée, mais MSDN dit:

Une ligne est définie comme une séquence de caractères suivi d'un saut de ligne ("\ n"), un retour chariot ("\ r") ou un retour chariot immédiatement suivi d'un saut de ligne ("\ r \ n"). La chaîne renvoyée ne contient pas le retour chariot final ou le saut de ligne. La valeur renvoyée est null si la fin du flux d'entrée est atteinte.

Cependant, il n'y a pas de CRLF dans le fichier.

Comment puis-je ajouter ces fichiers en toute sécurité sans ajouter de saut de ligne supplémentaire à la fin? Par exemple, StreamWriter.WriteLine() mettra un saut de ligne supplémentaire sur le fichier A lorsque je ne le souhaite pas. Quelle serait une approche idéale?

+2

Si vous voulez juste ajouter le fichier entier, pourquoi êtes-vous vous-même avec de telles constructions concernant ont inventées en tant que «lignes» en premier lieu? Utilisez 'ReadToEnd' pour obtenir le tout, ou lisez le fichier un bloc à la fois. Il n'y a aucune raison de traiter un couple de caractères spécialement quand vous allez tout simplement les écrire mot pour mot de toute façon. –

+1

J'étais préoccupé par l'utilisation de la mémoire pour les fichiers plus volumineux. Mais le traitement du fichier en morceaux est logique. –

Répondre

2

StreamReader et StreamWriter (qui dérivent de TextReader et TextWriter) ne sont pas adaptés aux situations nécessitant une forme exacte de données binaires. Ce sont des abstractions de haut niveau d'un fichier composé d'octets, pas de texte ou de lignes. En fait, non seulement vous pourriez vous retrouver avec un nombre différent de nouvelles lignes, mais en fonction de l'environnement, vous pourriez écrire un terminateur de ligne autre que le CR/LF attendu.

Vous devriez plutôt simplement copier d'un flux à un autre. C'est assez facile en fait.

var bytes = File.ReadAllBytes(pathIn); 
var stream = File.Open(pathOut, FileMode.Append); 
stream.Write(bytes, 0, bytes.Length); 
stream.Close(); 

Si la taille du fichier est potentiellement important, vous devez ouvrir l'entrée et le fichier de sortie en même temps et d'utiliser un tampon de taille fixe pour copier un bloc à la fois.

using (var streamIn = File.Open(pathIn, FileMode.Read)) 
using (var streamOut = File.Open(pathOut, FileMode.Append)) { 

    var bytes = new byte[BLOCK_SIZE]; 

    int count; 
    while ((count=streamIn.Read(bytes, 0, bytes.Length)) > 0) { 
     streamOut.Write(bytes, 0, count); 
    } 

} 

est également intéressant de noter que le code ci-dessus pourrait être remplacé par Stream.CopyTo qui est nouveau dans .NET 4.

0

Eh bien, cela dépend vraiment des raisons de votre implémentation (Pourquoi lisez-vous par ligne et en l'écrivant ligne par ligne?) Vous pouvez simplement utiliser StreamWriter.Write(string) et sortir tout le texte que vous avez stocké, les méthodes WriteLine() sont nommées en tant que tels, car ils ajoutent une nouvelle ligne.

TextWriter.WriteLine méthode (String)
écrit une chaîne de caractères suivie par une terminaison de ligne dans le flux de texte.

2

Vous pouvez utiliser StreamWriter.Write à la place de WriteLine pour éviter le crlf supplémentaire. En ce qui concerne les documents ReadLine, je crois que le problème est une explication mal formulée. Vous ne voudriez certainement pas supprimer les derniers octets d'un fichier simplement parce qu'il n'y a pas d'indicateur de fin de ligne formel.

3

Vous obtenez seulement null si vous appelez ReadLineà la fin du flux. Sinon, vous obtiendrez toutes les données jusqu'à soit un CRLFou la fin du flux.Si vous essayez de faire une duplication octet par octet (et comparaison), il est préférable de lire les caractères (en utilisant StreamReader/StreamWriter comme vous utilisez maintenant) ou octets (en utilisant simplement le Stream classe) en utilisant les fonctions normales Read et Write plutôt que ReadLine et WriteLine.

Vous pouvez également lire tout le contenu du fichier en utilisant ReadToEnd puis l'écrire en appelant Write (pas WriteLine), mais ce n'est pas pratique si le fichier est volumineux.

string data; 

using(StreamReader reader = new StreamReader(path)) 
{ 
    data = reader.ReadToEnd(); 
} 

using(StreamWriter writer = new StreamWriter(path, true)) 
{ 
    writer.Write(data); 
} 
Questions connexes