2009-08-11 5 views
4

Voici comment je le fais:C#: FileStream.Read() ne lit pas le fichier jusqu'à la fin, mais retourne 0

static void Main(string[] args) 
{ 
    string FileName = "c:\\error.txt"; 
    long FilePosition = 137647; 

    FileStream fr = new FileStream(FileName, FileMode.Open); 
    byte[] b = new byte[1024]; 
    string data = string.Empty; 
    fr.Seek(FilePosition, SeekOrigin.Begin); 
    UTF8Encoding encoding = new UTF8Encoding(); 

    while (fr.Read(b, 0, b.Length) > 0) 
    { 
     data += encoding.GetString(b); 
    } 
    fr.Close(); 
    string[] str = data.Split(new string[] { "\r\n" }, StringSplitOptions.None); 
    foreach (string s in str) 
    { 
     Console.WriteLine(s); 
    } 
    Console.ReadKey(); 
} 

Le tableau str se termine par ces lignes:

***** Histoire pour T5-2847880-18 main (TOURNOI: S-976-46079) *****
main Début: 11 Aug Mar 18:14

mais il y a plus lignes dans le fichier.

J'ai uploadé error.txt à SendSpace: http://www.sendspace.com/file/5vgjtn Et voici la sortie complète de la console: the_same_site/fichier/k05x3a

S'il vous plaît aider! Je suis vraiment désemparé ici. Merci d'avance!

Répondre

15

Votre code a quelques erreurs subtiles et des problèmes dans:

  • Vous assumez que le tampon entier a été rempli en appelant GetString(b)
  • Vous supposez que chaque tampon se termine à la fin d'un caractère . Utilisez un TextReader (par exemple StreamReader) pour lire les données de texte, en évitant ce type de problème.
  • Vous ne fermez pas le fichier en cas d'exception (utilisez une directive using)
  • Vous utilisez concaténation de chaîne dans une boucle: préférez StringBuilder

Comme d'autres l'ont souligné, File.ReadAllLines éviterait beaucoup de ce travail. Il y a aussi File.ReadAllText, et TextReader.ReadToEnd pour les non-fichiers.

Enfin, utilisez simplement Encoding.UTF8 au lieu de créer une nouvelle instance à moins que vous ayez vraiment besoin de modifier certaines options.

+0

Merci beaucoup pour la réponse si détaillée! File.ReadAllLines ne me convient pas car le fichier peut devenir très volumineux et nécessiter beaucoup de traitement pour trouver la ligne dont j'ai besoin. Créer un StreamReader à partir d'un FileStream est exactement ce que j'ai cherché. Encore merci! –

4

Pas techniquement une réponse à votre question, mais vous pouvez remplacer tout cela avec:

string[] str = File.ReadAllLines("c:\\error.txt"); 

Edit (comme promis):
Plutôt que de manquer un morceau, il me semble que vous allez avoir un duplicata de la dernière partie. Vous ne lisez pas 1024 octets complets à partir du fichier, mais vous convertissez tous les 1024 octets en une chaîne et l'ajout.

Votre boucle devrait être comme ceci:

int bytesRead; 
while ((bytesRead = fr.Read(b, 0, b.Length)) > 0) 
{ 
    data += encoding.GetString(b, 0, bytesRead); 
} 

Autre que cela: ce que Jon a dit :)

+0

Ha! Les grands esprits se ressemblent ;-) –

2

Pourquoi faites-vous pas votre vie plus facile et faire cela?

string[] str = System.IO.File.ReadAllLines("c:\\error.txt"); 
0

Vous trouverez peut-être beaucoup plus facile d'utiliser simplement File.ReadLines(). Ignorez les lignes qui ne vous intéressent pas, au lieu d'utiliser la position.

int counter = 0; 
foreach (string s in File.ReadAllLines(FileName)) 
{ 
    ++counter; 
    if (counter > 50?) 
    { 
     Console.WriteLine(s); 
    } 
} 

Vous pouvez également utiliser le StreamReader, qui vous permet d'enrouler le flux après avoir défini sa position, puis utilisez la méthode ReadLine().

+0

Supposément, il a stocké cette position octet la fois précédente, il a lu le fichier, et maintenant il veut juste lire la partie qui est nouveau. L'utilisation de la position du fichier serait préférable dans ce cas. Bien sûr, vous devez être sûr que le fichier ne sera pas écrasé entre-temps (un journal étant cyclé par exemple). – Thorarin

Questions connexes