2009-07-28 10 views
2

Je veux utiliser un FileStream et chercher depuis le début du fichier tout en avançant dans le fichier .01% de la taille du fichier à la fois.Le moyen le plus efficace pour parcourir un fichier et lire des lignes?

Donc, je veux chercher une position dans le fichier, lire la ligne entière, si elle correspond à mes critères, j'ai terminé. Sinon, je cherche un autre .01.

C# est OK mais VB.NET est préféré.

J'utilisé pour faire quelque chose comme ça dans VB6 ...

  FileOpen(1, CurrentFullPath, OpenMode.Input, OpenAccess.Read, OpenShare.Shared) 
     Dim FileLength As Long = LOF(1) 

     For x As Single = 0.99 To 0 Step -0.01 
      Seek(1, CInt(FileLength * x)) 
      Dim S As String = LineInput(1) 
      S = LineInput(1) 
      filePosition = Seek(1) 
      If filePosition < 50000 Then 
       filePosition = 1 
       Exit For 
      End If 
      V = Split(S, ",") 
      Dim MessageTime As Date = CDate(V(3) & " " & Mid$(V(4), 1, 8)) 
      Dim Diff As Integer = DateDiff(DateInterval.Minute, MessageTime, CDate(RequestedStartTime)) 
      If Diff >= 2 Then 
       Exit For 
      End If 
     Next 

Mais je ne veux pas utiliser FileOpen, je veux utiliser un FileStream.

Toute aide est grandement appréciée!

+0

votre question mentionne vouloir lire seulement 1% du fichier à un temps, mais il dit aussi que vous vouliez le lire ligne par ligne, alors j'ai répondu dans le même sens. –

Répondre

3

Ceci est une conversion plus ou moins directe de votre code, où nous utilisons FileStream.Position pour spécifier l'emplacement dans le fichier à lire:

 
Using streamReader As System.IO.StreamReader = System.IO.File.OpenText(CurrentFullPath) 
    For x As Single = 0.99 To 0 Step -0.01 
    streamReader.BaseStream.Position = CLng(streamReader.BaseStream.Length * x) 
    Dim S As String = streamReader.ReadLine() 
    '... etc. 
    Next 
End Using 
+0

-1 pour aucune utilisation/fin Utilisation. Aussi, avez-vous testé ce code? Comment StreamReader pense-t-il que la position du flux change en dessous? Vous devriez également tester pour voir ce qu'il fait si la position change juste avant le retour à la ligne, et quand elle change pour être à l'intérieur d'une paire CR + LF. –

+0

Vous avez raison, ce n'est pas exactement l'implémentation idéale, mais je l'ai écrit de cette façon afin que Doug puisse facilement voir les similitudes/différences entre son code original et la nouvelle approche FileStream. Et oui, j'ai testé le code, même si mon test était quelque peu superficiel. Le StreamReader ne semble pas déranger que la position est modifiée, car il lit juste à partir de la position actuelle du flux. – bernhof

+0

Le conseil pour vérifier si la position est actuellement entre et la paire CR/LF est bonne. Est-ce que le code original gère cette situation? – bernhof

1

ce combat quelque chose comme ça (C# version):

using (var file = System.IO.File.OpenText(filename)) 
{ 
    while (!file.EndOfStream) 
    { 
      string line = file.ReadLine(); 
      //do your logic here 
      //Logical test - if true, then break 
    } 
} 

EDIT: version VB ici (! Avertissement - d'un C# dev)

Using file as FileStream = File.OpenText(filename) 
    while Not file.EndOfStream 
     Dim line as string = file.ReadLine() 
    ''//Test to break 
    ''//exit while if condition met 
    End While 
End Using 
+0

Merci Josh mais le fichier est trop gros pour le parcourir ligne par ligne. Je dois être capable de chercher un poste dans le fichier. – Doug

0

Je préfère normalement vb.net, mais C# 's blocs itérateur sont lentement me gagner:

public static IEnumerable<string> SkimFile(string FileName) 
{ 
    long delta = new FileInfo(FileName).Length/100; 
    long position = 0; 

    using (StreamReader sr = new StreamReader(FileName)) 
    { 
     while (position < 100) 
     { 
      sr.BaseStream.Seek(position * delta, SeekOrigin.Begin); 
      yield return sr.ReadLine(); 
      position++; 
     } 
    } 
} 

Mettez-le dans un projet de bibliothèque de classes et de l'utiliser de vb comme thi s:

Dim isMatch as Boolean = False 
For Each s As String in SkimFile("FileName.txt") 
    If (RequestedDate - CDate(s.SubString(3,11))).Minutes > 2 Then 
     isMatch = True 
     Exit For 
    End If 
Next s 

(j'ai pris quelques libertés pour rendre l'exemple plus facile avec des critères vous (pris les valeurs de largeur fixe plutôt que délimité))

+0

Joel, j'aime ça mais j'aurais dû préciser que j'avais besoin d'utiliser .NET 2.0. Est-ce que votre code 2.0? – Doug

+0

Non, vous avez besoin de 3.5 pour la fonction lamdba et l'extension .Any(). Mais la partie C# est tout 2.0. Donnez 5 minutes et je mettrai à jour le vb pour le rendre compatible avec la version 2.0. –

+0

Aussi, je devrais vous avertir: ce code a été tapé directement dans la fenêtre de réponse et est complètement non testé. –

0

Il y a un example on MSDN.

Modifier en réponse à un commentaire:

Je dois admettre que je suis un peu confus, comme tu avais l'air lancinant sur l'aide d'un tampon FileStream, mais que vous voulez lire un fichier d'une ligne à la fois? Vous pouvez le faire tout simplement en utilisant un StreamReader. Je ne sais pas VB, mais en C# ce serait quelque chose comme ceci:

using (StreamReader sr = File.OpenText(pathToFile)) 
{ 
    string line = String.Empty; 
    while ((line = sr.ReadLine()) != null) 
    { 
     // process line 
    } 
} 

Voir http://msdn.microsoft.com/en-us/library/system.io.file.aspx.

+0

Merci Dan, mais je voulais lire une ligne et pas de char par char. Je pense que c'est ce que fait l'exemple MSDN. Je ne pouvais pas le faire fonctionner pour moi. – Doug

Questions connexes