10
votes

Fichier texte inverse massive en Java

Quelle serait la meilleure approche pour inverser un fichier texte chargé de manière asynchrone sur un servlet qui inverse ce fichier de manière évolutive et efficace?

  • Le fichier texte peut être massif (gigaoctets long)
  • peut assumer un environnement de serveur / en cluster de Mulitple pour le faire de manière distribuée.
  • Les bibliothèques open source sont encouragées à considérer

    Je pensais utiliser Java Nio pour traiter le fichier comme une matrice sur disque (afin que je n'ai pas à traiter le fichier sous forme de tampon à chaîne en mémoire). En outre, je pense à utiliser MapReduce pour casser le fichier et à le traiter dans des machines distinctes.


5 commentaires

Le fichier doit-il être stocké dans l'ordre inverse? Est-il possible de l'écrire dans l'ordre correct et de l'inverser quand il est lu?


Cela ressemble à une de ces questions de défi technique destinées à découvrir comment les employés candidats ont abordé les problèmes et gérer la concurrence.


Le fichier doit être stocké dans l'ordre inverse. C'était une question d'entrevue pour une startup. Comment allez-vous gérer la partie concurrence de la question?


La concurrence serait inutile si vous avez utilisé ma solution - en fait, il nie complètement le problème, cela ne prendrait plus et ne serait plus plus difficile que de stocker le fichier "normalement"


Si vous voulez de l'efficacité, pourquoi téléchargez-vous le fichier du tout. Votre bande passante est susceptible d'être le facteur limitant. Le moyen le plus rapide d'inverser le fichier est de le faire localement.


4 Réponses :


4
votes

Si elle vous est téléchargée et que vous pouvez obtenir la longueur au début, vous pouvez simplement créer un fichier de taille complète vide à l'avant et écrivez-le à partir du dos et de votre chemin à l'avant en utilisant recherche

Vous voudrez probablement définir une taille de bloc (comme 1k?) et inverser cela beaucoup en mémoire avant de l'écrire dans le fichier.


0 commentaires

2
votes

C'est une tâche assez difficile. Si vous pouvez vous assurer que http longueur de contenu < / code> et Type de contenu Les en-têtes sont présents dans la demande de téléchargement (ou dans le corps de MultiPart lorsqu'il s'agit d'une demande multipart / formulaire ), ce serait un travail facile avec l'aide de < Un href = "http://java.sun.com/javase/6/docs/api/java/io/randomAccessfile.html" rel = "nofollow noreferrer"> aléatoireAccessfile . La longueur du contenu est obligatoire pour que le randomAccessfile sache combien de temps le fichier sera et écrire le caractère à la position souhaitée. Le codage de caractères (qui est généralement présent en tant qu'attribut de l'en-tête de type de contenu) est obligatoire de savoir combien d'octets un caractère prendra en compte (car randomAccessfile est basé sur un octet et par exemple l'encodage UTF-8 est variable-octet-longueur).

Voici un exemple de coup d'envoi (laissant une exception évidente manipulant de côté): xxx

si ces en-têtes ne sont pas présents (en particulier Contenu -Length est important), vous aurez alors besoin de le stocker sur le disque d'abord jusqu'à la fin du flux, puis de relire et d'inverser la même manière avec l'aide de RandomAccessFile . < / p>

mise à jour : cela serait réellement plus difficile qu'il ne ressemble. Le codage du caractère de l'entrée est-il toujours garanti pour être le même? Si oui, ce que l'on serait? En outre, que voudriez-vous faire avec des personnages de substitution et des lignes de substitution? L'exemple ci-dessus ne prend pas cela en compte correctement. Mais cela donne au moins l'idée de base.


10 commentaires

Merci Balusc pour votre réponse. Je suppose que l'encodage Unicode / UTF-8. Je ne pense pas que nous devons faire quelque chose de spécial avec de nouvelles lignes.


Vous pouvez convertir un seul caractère en chaîne à l'aide de caractères.Tostring (((char))


Lorsque vous obtenez la matrice d'octet pour calculer sa longueur, vous devez le garder autour et écrire cela pour sortir. Vous écrivez actuellement le point de code (appelant efficacement la sortie.write (int b)), pas les octets codés.


De plus, si le codage de transfert est défini sur "chund", vous n'aurez pas de longueur de contenu.


@Kathy: 1) Ce n'est pas plus efficace. Par un autre sujet, j'ai appris que charbufuffer # wrap () est meilleur. 2) Non, je l'ai lancé à Char. 3) Cela dépend du côté du client. J'ai déjà indiqué que la longueur du contenu est obligatoire.


@Ballusc je ne vois pas une méthode d'écriture (char c) en aléatoireAccessfile. Et si vous ne spécifiez pas l'encodage, vous écrivez, le point de code n'est pas la valeur codée.


@Balusc w3.org/protocols/rfc2616/rfc2616-sec14. HTML # SEC14.13 dit que la longueur de contenu est facultative. Où voyez-vous que cela est nécessaire?


Je suppose que cela pourrait être obligatoire sur le téléchargement par opposition au téléchargement


@Kathy: Euh, veuillez utiliser le lien Modifier pour modifier les commentaires :) 1) Oui, je vois, merci de la corriger. 2) Obligatoire du côté du serveur, car vous devez autrement stocker le fichier entier en premier. Voir aussi le texte que j'ai écrit après le code. 3) Ouais ... Cela sent trop de nitpicking. Je vais le laisser comme ça :)


@Ballusc qui sent trop comme le nitpicking?



0
votes

Enregistrez-le dans des morceaux gérables sur le disque car ils entrent, puis lisez les morceaux vers l'arrière lorsque vous avez besoin et présentez le contenu à l'envers.

1 MB serait une taille raisonnable, compte tenu du montant disponible pour une application Java normale ces jours-ci?


0 commentaires

0
votes

Dans le fichier paradigme de la carte, peut être divisé en petites partitions et chaque partition peut être stockée dans un objet de collecte, qui peut être inversé facilement et en phase de réduction de chaque sortie inversée peut à nouveau fusionnée ensemble. Par E.G dans le code Spark-Scala devrait être quelque chose comme ça. xxx


0 commentaires