web-dev-qa-db-fra.com

Java BufferedReader vers le haut d'un fichier texte?

J'ai actuellement 2 BufferedReaders initialisés sur le même fichier texte. Quand j'ai fini de lire le fichier texte avec le premier BufferedReader, j'utilise le second pour faire passer un autre dans le fichier par le haut. Plusieurs passages dans le même fichier sont nécessaires.

Je connais reset(), mais elle doit être précédée d'un appel à mark() et mark() doit connaître la taille du fichier, ce que je ne pense pas avoir devrait avoir à s'embêter.

Des idées? Paquets? Libs? Code?

Merci TJ

26
T to the J

Quel est l'inconvénient de simplement créer un nouveau BufferedReader à lire par le haut? Je m'attends à ce que le système d'exploitation mette en cache le fichier s'il est assez petit.

Si vous êtes préoccupé par les performances, avez-vous prouvé qu'il s'agit d'un goulot d'étranglement? Je ferais simplement la chose la plus simple et ne m'inquiéterais pas jusqu'à ce que vous ayez une raison précise de le faire. Je veux dire, vous pouvez simplement lire le tout en mémoire et ensuite faire les deux passes sur le résultat, mais encore une fois cela va être plus compliqué que de simplement relire depuis le début avec un nouveau lecteur.

25
Jon Skeet

Les lecteurs tamponnés sont destinés à lire un fichier séquentiellement. Ce que vous recherchez est le Java.io.RandomAccessFile , puis vous pouvez utiliser seek() pour vous amener où vous voulez dans le fichier.

Le lecteur à accès aléatoire est implémenté comme suit:

try{
     String fileName = "c:/myraffile.txt";
     File file = new File(fileName);
     RandomAccessFile raf = new RandomAccessFile(file, "rw");
     raf.readChar();
     raf.seek(0);
} catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
} catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
}

Le "rw" est un caractère de mode qui est détaillé ici .

La raison pour laquelle les lecteurs à accès séquentiel sont configurés comme ceci est pour qu'ils puissent implémenter leurs tampons et que les choses ne puissent pas être modifiées sous leurs pieds. Par exemple, le lecteur de fichiers attribué au lecteur tamponné ne doit être utilisé que par ce lecteur tamponné. S'il y avait un autre emplacement qui pourrait l'affecter, vous pourriez avoir un fonctionnement incohérent car un lecteur a avancé sa position dans le lecteur de fichiers tandis que l'autre voulait qu'il reste le même maintenant vous utilisez l'autre lecteur et il est dans un emplacement indéterminé.

29
Ryan P

La meilleure façon de procéder est de changer votre algorithme, de manière à ce que vous n'aurez PAS besoin de la deuxième passe. J'ai utilisé cette approche plusieurs fois, lorsque j'ai dû gérer des fichiers énormes (mais pas terribles, c'est-à-dire quelques Go) qui ne correspondaient pas à la mémoire disponible.

Cela peut être difficile, mais le gain de performances vaut généralement l'effort

3
Davide

À propos de la marque/réinitialisation:

La méthode mark dans BufferedReader prend un paramètre readAheadLimit qui limite la distance que vous pouvez lire après une marque avant que la réinitialisation ne devienne impossible. La réinitialisation ne signifie pas en fait une recherche de système de fichiers (0), elle cherche juste à l'intérieur du tampon. Pour citer le Javadoc:

readAheadLimit - Limite le nombre de caractères pouvant être lus tout en préservant la marque. Après avoir lu ce nombre de caractères, la tentative de réinitialisation du flux peut échouer. Une valeur limite supérieure à la taille du tampon d'entrée provoquera l'allocation d'un nouveau tampon dont la taille n'est pas inférieure à la limite. Par conséquent, des valeurs importantes doivent être utilisées avec précaution.

1
Zarkonnen