Lire un fichier ligne par ligne dans l'ordre inverse
J'ai une application java ee où je utiliser une servlet pour imprimer un fichier journal créé avec log4j. Lors de la lecture des fichiers journaux vous sont généralement à la recherche pour le dernier journal de la ligne et, par conséquent, la servlet serait beaucoup plus utile si l'imprimer le fichier journal dans l'ordre inverse. Mon code est:
response.setContentType("text");
PrintWriter out = response.getWriter();
try {
FileReader logReader = new FileReader("logfile.log");
try {
BufferedReader buffer = new BufferedReader(logReader);
for (String line = buffer.readLine(); line != null; line = buffer.readLine()) {
out.println(line);
}
} finally {
logReader.close();
}
} finally {
out.close();
}
Les implémentations j'ai trouvé dans l'internet impliquent l'utilisation d'un StringBuffer et le chargement de tous les fichiers avant l'impression, n'est-il pas un code de chemin de lumière de la recherche à la fin du fichier et de lire le contenu jusqu'au début du fichier?
- Essayez le saut() méthode avec un max de type int. Je vais vous dire la distance qu'il a sauté. Puis de soustraire une certaine quantité de cette valeur et passer à l'il. Puis lire dans le montant restant, et d'analyser la mémoire tampon.
- double possible de Java: Vite lu la dernière ligne d'un fichier texte? En particulier, chercher à @Jon Skeet réponse qui renvoie à une question similaire pour C#.
- Voir aussi: stackoverflow.com/questions/4121678/...
skip()
retourne dans quelle mesure il ignorée parce qu'elle ne sera pas forcément sauter aussi loin que vous le demandez. Il pourrait effectivement essayer de sauter aussi loin que vous l'avez demandé, cependant, et ne parviennent pas.- Tout simplement l'impression du journal les lignes dans l'ordre inverse n'est pas une bonne idée. Ce qui se passe, par exemple, si vous avez un multi-ligne d'entrée de journal ... comme une exception?
Vous devez vous connecter pour publier un commentaire.
[MODIFIER]
Par demande, je suis en ajoutant cette réponse avec le sentiment d'une plus tard, commentaire: Si vous avez besoin de ce comportement souvent, un "plus approprié" solution est probablement de déplacer vos journaux à partir de fichiers texte des tables de base de données avec DBAppender (partie de log4j 2). Ensuite, il vous suffit de requête pour les dernières inscriptions.
[/EDIT]
Je serais probablement approche un peu différemment que les réponses répertoriées.
(1) Créer une sous-classe de
Writer
qui écrit les octets codés de chaque personnage dans l'ordre inverse:(2) Créer une sous-classe de log4j
WriterAppender
dontcreateWriter
méthode serait substituée pour créer une instance deReverseOutputStreamWriter
.(3) Créer une sous-classe de log4j
Layout
dontformat
méthode renvoie la chaîne du journal en sens inverse l'ordre des caractères:(4) de Modifier mon fichier de configuration des logs pour envoyer des messages de log les deux la "normale" fichier journal et un "inverse" fichier journal. Le "reverse" fichier journal contient les journaux des messages comme "normal" fichier journal, mais chaque message doit être écrit à l'envers. (À noter que l'encodage de la "reverse" fichier journal ne serait pas nécessairement conforme à l'UTF-8, ou même n'importe quel codage de caractères.)
(5) Créer une sous-classe de
InputStream
qui encapsule une instance deRandomAccessFile
afin de lire les octets d'un fichier dans l'ordre inverse:Maintenant, si je veux lire les entrées de la "normale" fichier journal dans l'ordre inverse, j'ai juste besoin de créer une instance de
ReverseFileInputStream
, en lui donnant le "révérer" fichier journal.DBAppender
(partie de log4j 2). Ensuite, il vous suffit de requête pour les dernières inscriptions.C'est une vieille question. Je voulais aussi faire la même chose et après quelques recherches, trouvé il y a une classe dans apache commons-io de réaliser ceci:
org.apache.commons.io.input.ReversedLinesFileReader
Je pense un bon choix pour ce serait en utilisant RandomFileAccess classe. Il y a un exemple de code pour la lecture à l'aide de cette classe sur cette page. La lecture des octets de cette façon est facile, cependant la lecture des chaînes peuvent être un peu plus difficile.
Une alternative plus simple, parce que vous dites que vous êtes en train de créer un servlet pour ce faire, est d'utiliser un
LinkedList
pour accueillir la dernière N lignes (où N pourrait être une servlet paramètre). Lorsque la taille de la liste dépasse N, vous appelezremoveFirst()
.À partir d'une perspective de l'expérience utilisateur, c'est probablement la meilleure solution. Comme vous le notez, la plus récente des lignes sont les plus importants. Ne pas être submergé par l'information est également très important.
Si vous êtes pressés et veulent la solution la plus simple, sans trop se préoccuper de la performance, je voudrais essayer d'utiliser un processus externe pour faire le sale boulot (étant donné que vous êtes l'exécution de votre application à l'Onu*serveur x, comme toute bonne personne aurait à faire XD)
Bonne question. Je ne suis pas au courant de tout les implémentations de cette. Il n'est pas trivial à faire correctement non plus, donc attention à ce que vous choisissez. Il devrait traiter avec le jeu de caractères d'encodage et de détection des différentes saut de ligne méthodes. Voici la mise en œuvre j'ai jusqu'à présent qui fonctionne avec de l'ASCII et UTF-8 fichiers, y compris un cas de test pour l'UTF-8. Il ne fonctionne pas avec l'encodage UTF-16LE ou UTF-16BE des fichiers codés.
vous pouvez utiliser RandomAccessFile implémente cette fonction,tels que:
utilisation:
La solution la plus simple est de lire le fichier en marche avant, à l'aide d'un
ArrayList<Long>
pour tenir le décalage d'octet de chaque enregistrement de journal. Vous aurez besoin d'utiliser quelque chose comme Jakarta Commons CountingInputStream pour récupérer la position de chaque enregistrement, et aura besoin de soin d'organiser vos tampons pour s'assurer qu'il renvoie les valeurs appropriées:Et vous ne serez probablement pas en mesure d'utiliser un
BufferedReader
, parce qu'il va tenter de lecture de l'avant et de se débarrasser de la comte (mais la lecture d'un caractère à la fois ne sera pas un problème de performance, parce que vous êtes à la mise en mémoire tampon plus bas dans la pile).Pour écrire le fichier, vous parcourez la liste en arrière et utiliser un
RandomAccessFile
. Il y a un peu d'un truc: pour décoder correctement les octets (en supposant un encodage multi-octet), vous aurez besoin de lire les octets correspondant à une entrée, puis d'appliquer un décodage à elle. Toutefois, la liste va vous donner le début et la fin de la position des octets.Un avantage important de cette approche, par rapport à tout simplement l'impression que les lignes dans l'ordre inverse, c'est que vous n'aurez pas de dégâts multi-ligne, journaux de messages (tels que des exceptions).
De sortie:
[Vaquar khan travaille dans la Citi, Il est bon bon programmeur programmeur confiance en moi
jetons[vaquar, khan, est, de travail, dans la Citi, Il, est, bon, bon, programmeur, programmeur, de confiance, de m']
uniquWordList[la confiance, vaquar, programmeur, est, bien, dans, khan, moi, mon travail, Citi, Il]
uniquWordList[programmeur, de travail, vaquar, la confiance, la bonne, dans, khan, Citi, est, moi, Il]
Si vous souhaitez Trier de A à Z puis écrire un plus comparater
Concis solution à l'aide de Java 7 Autoclosables et Java 8 Flux :
Gros inconvénient: ne fonctionne que lorsque les lignes sont strictement dans l'ordre naturel, comme les fichiers journaux préfixé avec des horodatages mais sans exceptions