2017-05-11 4 views
0

J'ai trouvé un problème étrange avec FileStream.SetLength (0). Lors de l'écriture d'abord quelque chose à un flux, puis en appelant SetLength (0), le contenu de l'écriture précédente obtient encore écrit dans le fichier:Après StreamWriter.WriteLine(), FileStream.SetLength (0) ne vide pas le fichier

var fileName = "test.txt"; 
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None)) 
{ 
    using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true)) 
    { 
     streamWriter.WriteLine("123"); 
     fileStream.SetLength(0); 
     streamWriter.WriteLine("abc"); 
    } 
} 
    var fileContent = File.ReadAllText(fileName); 

ContenuFichier devient « 123 \ r \ nabc \ r \ n »

De toute évidence, 123 n'a pas été supprimé, même s'il a été écrit avant d'appeler SetLength (0).

L'utilisation de Seek() ou le réglage de la Position à 0 n'a pas aidé.

Dans mon application, j'écris dans un fichier que je garde ouvert. De temps en temps, il peut arriver que je doive vider complètement le fichier et écrire un contenu différent. Pour des raisons de performances, je ne souhaite pas fermer streamWriter.

Note à tous les gars qui aiment marquer des questions à tort comme des doublons

J'ai fait l'expérience très frustrant sur Stackoverflow qu'une question se est marqué à tort comme double. J'ai passé une journée à écrire la question, il décide en un instant que c'est un doublon, même si ce n'est pas le cas. Cela arrive généralement quand ce type ne comprend pas vraiment la question et ne prend pas la peine de trouver la bonne réponse. Il sent juste qu'un problème similaire a été résolu auparavant sur SO. Mais les détails comptent. Oui, il y a des questions sur la troncature d'un fichier en utilisant SetLength (0), mais elles sont différentes en un point crucial: Dans ces exemples, SetLength (0) n'est pas précédé d'un Write(). Mais c'est essentiel, sans cela il n'y a pas de problème.

Veuillez, s'il vous plaît, être très prudent et attentif lorsque vous empêchez les autres de répondre en marquant une question comme doublon.

+0

StreamWriter ne sait pas que vous êtes en train de jouer avec son flux sous-jacent. Il a un tampon lui-même, vous devrez le vider(). –

+0

Seul moyen de vraiment effacer est de fermer et d'ouvrir à nouveau comme nouveau flux. – jdweng

+0

@jdweng: Ma solution utilisant Flush() semble fonctionner, même si je ne réalise peut-être pas que cela crée un problème. Pouvez-vous décrire ce que cela pourrait être? –

Répondre

1

Lors de l'inspection FileStream.SetLength() on referencesource.microsoft.com, j'ai remarqué ce drôle de morceau de code:

 // Handle buffering updates. 
     if (_writePos > 0) { 
      FlushWrite(false); 
     } 

Il vérifie dans les SetLength() si le tampon FileStream interne a encore une partie du contenu d'écriture et l'écrit d'abord au dossier, avant d'exécuter le reste de SetLength().

Un comportement très étrange. Je pouvais résoudre ce problème en vidant la mémoire tampon interne avant d'appeler SetLength() en utilisant un flush() d'abord:

var fileName = "test.txt"; 
    using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None)) { 
    using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true)) { 
     streamWriter.WriteLine("123"); 
     streamWriter.Flush(); 
     fileStream.SetLength(0); 
     streamWriter.WriteLine("abc"); 
    } 
    } 
    var fileContent = File.ReadAllText(fileName); 

ContenuFichier est maintenant: « abc \ r \ n »

Je serais intéressé d'entendre si d'autres pensent que c'est un bug dans FileStream?