2009-08-10 9 views
2

J'ai un gros fichier texte avec plus de 200.000 lignes, et je n'ai besoin de lire que quelques lignes. Par exemple: ligne 10.000 à 20.000.Comment lire des données partielles à partir d'un gros fichier texte en C++

Important: Je ne souhaite pas ouvrir et rechercher le fichier complet pour extraire ces lignes en raison de problèmes de performances.

Est-ce possible?

+0

Je l'ai vu faire dans Fortran, nous avons dû lire un fichier à partir d'un compteur de données (2 millions de lignes). Donc je suis confiant que c'est faisable – dassouki

Répondre

1

Vous devrez chercher dans le fichier pour compter les retours à la ligne, sauf si vous savez que toutes les lignes ont la même longueur (auquel cas vous pouvez rechercher offset = line_number * line_size_in_bytes, où line_number compte pour zéro et line_size_in_bytes inclut tous les caractères de la ligne).

Si les lignes sont de longueur variable/inconnue, alors en les parcourant, vous pouvez indexer le décalage de début de chaque ligne afin que les lectures suivantes puissent rechercher le début d'une ligne donnée.

6

Si les lignes sont de longueur fixe, il est alors possible de rechercher une position d'octet spécifique et de charger uniquement les lignes souhaitées. Si les lignes sont de longueur variable, la seule façon de trouver les lignes que vous recherchez est d'analyser le fichier et de compter le nombre de marqueurs de fin de ligne. Si le fichier change rarement, vous pouvez obtenir des performances suffisantes en effectuant cette analyse une fois puis en conservant un index des positions en octets de chaque ligne pour accélérer les futurs accès (en écrivant peut-être cet index sur le disque afin qu'il ne soit pas nécessaire fait à chaque fois que votre programme est exécuté).

+1

Avertissement: Certains formats de fichiers incluent un début d'index ou parfois près de la fin. Ensuite, vous lisez l'index et l'utilisez pour calculer la position de départ des données dont vous avez besoin. Oui, c'est plus facile et plus commun dans les formats binaires, mais je l'ai vu dans un format texte. – dmckee

+0

+1 pour la réponse @dmckee: Un index au début ne semble pas vraiment problématique? À la fin, vous pouvez probablement chercher à la fin et vous connaissez probablement la taille de l'index, donc il ne semble pas être un gros problème? – neuro

+0

@neuro: le dernier élément d'un index à la fin doit être un décalage de taille fixe pour le début de l'index. Vous cherchez à la fin, sauvegardez d'un montant connu, lisez le décalage d'index, allez à l'index, et continuez à partir de là. Évident, non? :) – dmckee

0

Si ces lignes ont toutes la même longueur, vous pouvez calculer un décalage pour une ligne donnée et lire uniquement ces octets.

Si les lignes varient en longueur, vous devez vraiment lire le fichier entier pour compter le nombre de lignes. Les caractères de fin de ligne sont simplement des octets arbitraires dans le fichier.

0

Si la ligne est de longueur fixe, il vous suffit de calculer le décalage, pas de problème.

Si ce n'est pas le cas (c'est-à-dire un fichier CSV normal), vous devrez parcourir le fichier, soit pour créer un index, soit pour lire simplement les lignes dont vous avez besoin. Pour rendre la lecture du fichier un peu plus rapide, une bonne idée serait d'utiliser des fichiers mappés en mémoire (voir l'implémentation qui fait partie des iostreams Boost: http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html).

0

Comme d'autres notes, si vous n'avez pas les lignes de largeur fixe, il est impossible de faire sans construire l'index. Cependant, si vous contrôlez le format du fichier, vous pouvez obtenir une performance ~ O (log (size)) au lieu de O (size) pour trouver la ligne de départ, si vous parvenez à stocker le numéro de la ligne elle-même chaque ligne, soit d'avoir le contenu du fichier ressembler à quelque chose comme ceci:

1: val1, val2, val3 
2: val4 
3: val5, val6 
4: val7, val8, val9, val10 

avec ce format du fichier, vous pouvez trouver rapidement la ligne nécessaire à la recherche binaire: commencer par la recherche dans le milieu du fichier. Lire jusqu'à la nouvelle ligne suivante. Lisez ensuite la ligne et analysez le nombre. Si le nombre est plus grand que la cible, alors vous devez répéter l'algorithme sur la première moitié du fichier, s'il est plus petit que le numéro de ligne cible, alors vous devez le répéter dans la seconde moitié du fichier. Vous devrez faire attention aux boîtiers d'angle (par exemple: votre "début" de la gamme et la "fin" de la gamme sont sur la même ligne, etc.), mais pour moi cette approche a fonctionné très bien le passé pour l'analyse des fichiers journaux qui contenaient la date (et j'avais besoin de trouver les lignes qui sont entre les horodateurs).

Bien sûr, cela ne bat pas encore les performances de l'index construit explicitement ou les enregistrements de taille fixe.

Questions connexes