11
votes

Lecture de fichiers texte ligne par ligne, avec compensation exacte / rapports de position

Mes exigences simples: lire un énorme fichier de test de ligne (>> un million) (pour cet exemple suppose qu'il s'agit d'une CSV de certaines sortes) et de tenir une référence au début de cette ligne pour une recherche plus rapide à l'avenir (lire une ligne , à partir de x).

J'ai essayé le moyen naïf et facile d'abord, en utilisant un StreamWriter Code> et accédant à la astresseam.position code>. Malheureusement, cela ne fonctionne pas comme je l'ai dit: p>

donné un fichier contenant le fichier suivant p> xxx pré>

et ce code très simple p>

000 Foo
025 Bar
025 Baz
025 Bla
025 Fasel


1 commentaires

Si vous réfléchissez à la classe System.IO.Stream, le tampon minimum autorisé est de 128 octets ... Je ne sais pas si cela vous aidera, mais sur un fichier plus long lorsque j'ai essayé cela, c'était la position la plus courte que je pouvais obtenir.


5 Réponses :


-1
votes

Cela fonctionnerait-il:

using (var sr = new StreamReader(@"C:\Temp\LineTest.txt")) {
  string line;
  long pos = 0;
  while ((line = sr.ReadLine()) != null) {
    Console.Write("{0:d3} ", pos);
    Console.WriteLine(line);
    pos += line.Length;
  }
}


5 commentaires

Malheureusement non, parce que je dois accepter différents types de nouvelles lignes (pensez que ceci \ n, \ r \ n, \ r) et que le nombre serait asymétrique. Cela pourrait fonctionner si j'insiste pour avoir un séparateur cohérent Newline (il pourrait très bien être mélangé dans la pratique) et si je le sondis d'abord, de connaître le décalage réel. Donc - j'essaie d'éviter de descendre cette route.


@Benjamin: Darn - Je viens de poster une réponse similaire qui s'appuie explicitement sur un séparateur de nouvelle ligne cohérent ...


Ensuite, je pense que vous feriez mieux de le faire manuellement avec StreamReader.Lead ().


@Jon: hehe. Comme je l'ai dit: que pourrait être le chemin, au lieu d'utiliser un flux simple - si ce sont les deux seules options que je dois rouler un dés et vivre avec les conséquences: soit les séparateurs cohérents (mauvais Pour les fichiers qui ont été traités sur plusieurs plate-forme, copiez / collé dans des éditeurs incorrects, etc.), etc.) ou sur les trucs de flux (analyse de la ligne de niveau de niveau basse et en chaîne, encodent beaucoup de code de plaque de chaudière pour un rendement apparemment bas)


Cela n'en aiderait pas beaucoup. Je dois abandonner tout le streamreader . Même Lire () On dirige un bloc sur le flux sous-jacent et déplace le astream.position à 25 pour mon échantillon. Après un caractère .



13
votes

Vous pouvez créer un wrapper textreader , qui suivrait la position actuelle dans la base textreader : xxx

vous pouvez alors utiliser comme suit: xxx


3 commentaires

Semble fonctionner. Cela semble si évident maintenant .. Merci beaucoup.


Cette solution convient aussi longtemps que vous voulez la position de caractère, plutôt que la position d'octet. Si le fichier sous-jacent a une barre d'ordre d'octets (BOM), il compensera, ou s'il utilise des caractères multi-octets, la correspondance 1: 1 entre les caractères et les octets ne contiennent plus.


D'accord, fonctionne uniquement pour les caractères codés par octet unique. Ascii. Si, par exemple, votre fichier sous-jacent est Unicode, chaque caractère sera codé de 2 ou 4 octets. La mise en œuvre ci-dessus fonctionne sur un flux de caractères, pas un flux d'octets, vous obtiendrez donc des décalages de caractères qui ne feront pas la mapper sur les positions d'octets réels, chaque caractère peut être de 2 ou 4 octets. Par exemple, la deuxième position de caractère sera signalée en tant qu'index 1, mais la position des octets sera effectivement index 2 ou 4. S'il y a une bombe (marque d'ordre d'octets), cela ajoutera à nouveau des octets supplémentaires à la véritable position d'octet sous-jacente.



2
votes

Bien que la solution de Thomas Levesque fonctionne bien, voici la mienne. Il utilise la réflexion de sorte qu'il sera plus lent, mais il est indépendant de l'encodage. De plus, j'ai également ajouté la recherche d'extension. XXX


0 commentaires

4
votes

Après avoir cherché, tester et faire quelque chose de fou, mon code résoudra (je suis actuellement en train d'utiliser ce code dans mon produit). XXX


0 commentaires

2
votes

C'est un problème vraiment difficile. Après une énumération très longue et épuisante de différentes solutions sur Internet (y compris des solutions de ce fil, merci!) Je devais créer mon propre vélo.

J'avais suivi les exigences:

  • performances - la lecture doit être très rapide, la lecture d'un caractère à l'époque ou à l'aide de la réflexion ne sont pas acceptables, une tampon est donc requise
  • Streaming - Le fichier peut être énorme, il n'est donc pas acceptable de la lire à la mémoire entièrement
  • à la queue - Layerie de fichier doit être disponible
  • Long Lines - Les lignes peuvent être très longues, une tampon peut donc être limitée
  • Stable - une erreur d'octet unique était immédiatement visible pendant l'utilisation. Malheureusement pour moi, plusieurs implémentations que j'ai trouvées étaient avec des problèmes de stabilité XXX


2 commentaires

J'ai un fichier journal, qui, lorsque vous avez lu avec OffseReader, le fait entrer dans une boucle infinie ...


Pourriez-vous partager ce fichier en quelque sorte?