La façon la plus rapide de mettre à lire un gros fichier
Lors d'une mémoire tampon de MAX_BUFFER_SIZE, et un fichier qui dépasse de loin, comment peut-on:
- Lire le fichier en blocs de MAX_BUFFER_SIZE?
- Faire aussi vite que possible
J'ai essayé d'utiliser NIO
RandomAccessFile aFile = new RandomAccessFile(fileName, "r");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(CAPARICY);
int bytesRead = inChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
buffer.get();
}
buffer.clear();
bytesRead = inChannel.read(buffer);
aFile.close();
Et régulière IO
InputStream in = new FileInputStream(fileName);
long length = fileName.length();
if (length > Integer.MAX_VALUE) {
throw new IOException("File is too large!");
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file " + fileName);
}
in.close();
S'avère que régulière IO est environ 100 fois plus vite en faisant la même chose que NIO. Ai-je raté quelque chose? Est-ce prévu? Est-il un moyen plus rapide pour lire le fichier dans le tampon morceaux?
En fin de compte, je travaille avec un gros fichier, je n'ai pas de mémoire pour les lire tous à la fois. Au lieu de cela, j'aimerais lire de façon incrémentielle dans les blocs qui pourrait ensuite être utilisé pour le traitement.
NIO n'est pas nécessairement plus rapide, c'est juste différent. Si
NIO w/o ByteBuffers est inutile (ou au moins transferTo sur Linux, sur Windows, il est émulé, donc inutile)
NIO est (strictement) plus rapidement lorsqu'il est utilisé correctement, il n'exige pas de tampon de copie par rapport à la régulière les IO. Ce n'est pas très facile à utiliser pour les novices, si.
Je tiens seulement à souligner que vos deux impls sont en train de faire des choses différentes. Votre NIO code de l'exemple est la lecture des octets dans votre ByteBuffer, alors vous êtes la lecture de , un par un, à partir de la sauvegarde de byte[] dans le ByteBuffer et ne rien faire avec eux dans la boucle. Dans les IO du code de la lecture des octets dans le byte[] et à ne pas faire d'autres travaux. Votre NIO code est fait 2x le lit plus la des milliards d'appels à get() pour saisir des valeurs de chaque octet.
java.io
est plus rapide pour vous, puis de les ignorer NIO.NIO w/o ByteBuffers est inutile (ou au moins transferTo sur Linux, sur Windows, il est émulé, donc inutile)
NIO est (strictement) plus rapidement lorsqu'il est utilisé correctement, il n'exige pas de tampon de copie par rapport à la régulière les IO. Ce n'est pas très facile à utiliser pour les novices, si.
Je tiens seulement à souligner que vos deux impls sont en train de faire des choses différentes. Votre NIO code de l'exemple est la lecture des octets dans votre ByteBuffer, alors vous êtes la lecture de , un par un, à partir de la sauvegarde de byte[] dans le ByteBuffer et ne rien faire avec eux dans la boucle. Dans les IO du code de la lecture des octets dans le byte[] et à ne pas faire d'autres travaux. Votre NIO code est fait 2x le lit plus la des milliards d'appels à get() pour saisir des valeurs de chaque octet.
OriginalL'auteur JAM | 2012-01-28
Vous devez vous connecter pour publier un commentaire.
En supposant que vous avez besoin de lire tout le fichier en mémoire à la fois (que vous êtes en train de faire), ni la lecture de morceaux plus petits, ni NIO vont vous aider ici.
En fait, vous seriez probablement mieux de lecture de plus gros morceaux - qui votre IO code est automatiquement fait pour vous.
Votre NIO code est actuellement plus lent, parce que vous êtes seulement à la lecture d'un octet à la fois (à l'aide de
buffer.get();
).Si vous voulez traiter en morceaux - par exemple, le transfert entre les flux - ici est un standard moyen de le faire sans NIO:
Il utilise une taille de mémoire tampon de 1 KO, mais il peut transférer une quantité illimitée de données.
(Si vous étendez votre réponse avec des détails de ce que vous êtes réellement à la recherche de faire au niveau fonctionnel, je pourrais l'améliorer encore pour une meilleure réponse.)
Non, à moins que de travailler avec d'autres API qui ont déjà fait usage de NIO pour les fonctions - par exemple, si vous travaillez avec de nombreux fichiers concurrents, et d'avoir à éviter d'importants multi-threading.
Enfin, pouvez-vous recommander la façon dont on peut lire
n
octets à l'aide de nio? Je me demandaisSemblable à mon non-NIO exemple dans ma réponse, dans votre NIO exemple, à
inChannel.read(buffer);
- il suffit d'utiliser un tampon d'une taille appropriée. Vous ne cherchez pas à lire le fichier en entier, seulement un morceau. Juste être conscient que c'est un appel non bloquant, de sorte que vous pouvez obtenir de moins que le nombre d'octets que vous avez demandé.Je comprends. Merci monsieur
OriginalL'auteur ziesemer
Si vous voulez faire de votre premier exemple, le plus rapide
Si vous voulez être encore plus rapide.
Cela peut prendre de 10 à 20 micro-secondes pour des fichiers jusqu'à 2 GO en taille.
Vrai, la fermeture du fichier de canal se ferme le fichier à accès aléatoire
Comment puis-je lire une ligne complète avec
MappedByteBuffer
, au lieu de lire char par char? voir howtodoinjava.com/2013/05/01/...juste regardé le code source et a constaté que la fermeture du fichier de canal ne ferme pas le fichier à accès aléatoire, mais dans l'autre sens, alors assurez-vous de fermer la RandomAccessFile 🙂
OriginalL'auteur Peter Lawrey