2010-11-04 10 views
3

Je dois travailler avec de gros fichiers (plusieurs Go) et j'ai besoin de recherches rapides pour récupérer des lignes spécifiques sur demande.Sauter à une ligne et la lire

L'idée a été de maintenir une cartographie:

some_key -> byte_location 

Lorsque l'emplacement d'octet représente l'endroit où dans le fichier de la ligne commence.

Edit: la question a changé un peu:

D'abord, j'utilisé:

FileInputStream stream = new FileInputStream(file); 
BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); 
FileChannel channel = stream.getChannel(); 

je remarquai que FileChannel.position() ne reviendra pas la position exacte où le lecteur est en train de lire, car il est un « tampon "lecteur. Il lit des morceaux d'une taille donnée (16k ici) donc ce que je reçois du FileChannel est un multiple de 16k, et non la position exacte où le lecteur lit réellement.

PS: le fichier est en UTF-8

+0

Quel est le codage de votre fichier? –

+1

Quelle est la question? Comment sauter à une position donnée dans le flux d'entrée? 'in.skip (pos);' Ou comment trouver la position désirée pour sauter à lire toute la ligne, et non une partie? – khachik

Répondre

2

j'aurais essayé quelque chose comme ceci:

RandomAccessFile raf = new RandomAccessFile(file); 
    ... 
    raf.seek(position); 
    raf.readLine(); 
    ... 

Le problème est que readLine() tourne chaque octet en caractère avec les 8 bits de zéro. C'est bien si votre fichier est ASCII ou Latin-1, mais problématique pour UTF-8. Toutefois, si vous êtes prêt à utiliser RandomAccessFile pour écrire le fichier, vous pouvez utiliser readUTF() et writeUTF() pour lire et écrire des "lignes" codées en tant que chaînes UTF-8 modifiées.

FOLLOWUP

... dammit caractères utf-8 sont vissés

Oui ... voir ci-dessus.

Une autre idée pour faire face à UTF-8 avec RandomAccessFile: méthode

  1. cherchent à la position désirée,
  2. utilisation readFully(byte[]) lire un tas d'octets dans un byte[],
  3. pos Position == localiser si la fin de la ligne dans le tampon est
  4. si elle n'est pas trouvée, lire plus d'octets, concaténer et passer à l'étape 2.
  5. si trouvé , utilisez new String(bytes, 0, pos, UTF-8) pour convertir en une chaîne Java.

Ceci est plus lourd que l'utilisation readLine(), mais il devrait être plus rapide que d'utiliser FileInputStream et skip() lors de la lecture de plusieurs lignes à partir des fichiers dans un ordre aléatoire.

+0

C'est exactement ce dont j'ai besoin, merci! – dagnelies

+0

dammit ... utf-8 caractères sont vissés – dagnelies

3

Toute raison de ne pas créer un FileInputStream, appelez stream.skip(pos) puis créer un InputStreamReader autour de cela, et un BufferedReader autour du InputStreamReader?

+0

le 'InputStreamReader' était mon lien manquant que je cherchais. Merci. – dagnelies

+0

question mise à jour ... – dagnelies

+0

@arnaud: si vous ne savez pas vraiment où vous voulez lire, il est difficile de voir comment vous pouvez contourner cela ... lire sur une ligne spécifique sans lire toutes les données est fondamentalement difficile. Votre fichier restera-t-il fixe pendant longtemps? Si c'est le cas, vous pourriez faire un effort pour lire le tout avec précision et vous rappeler simplement les corrections * exactes *. –