FileChannel.transferTo pour les gros fichiers dans windows
À l'aide de Java NIO utiliser pouvez copier des fichiers plus vite. J'ai trouvé deux genre de méthode, principalement sur internet pour faire ce travail.
public static void copyFile(File sourceFile, File destinationFile) throws IOException {
if (!destinationFile.exists()) {
destinationFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destinationFile).getChannel();
destination.transferFrom(source, 0, source.size());
} finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
}
Dans 20 très utile Java des extraits de code pour les Développeurs Java j'ai trouvé un commentaire différent et astuce:
public static void fileCopy(File in, File out) throws IOException {
FileChannel inChannel = new FileInputStream(in).getChannel();
FileChannel outChannel = new FileOutputStream(out).getChannel();
try {
//inChannel.transferTo(0, inChannel.size(), outChannel); //original -- apparently has trouble copying large files on Windows
//magic number for Windows, (64Mb - 32Kb)
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = inChannel.size();
long position = 0;
while (position < size) {
position += inChannel.transferTo(position, maxCount, outChannel);
}
} finally {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
}
}
Mais je n'ai pas trouver ou à comprendre quel est le sens de
"nombre magique pour Windows, (64 mo - 32 ko)"
Il est dit que inChannel.transferTo(0, inChannel.size(), outChannel)
a un problème dans windows, est 32768 (= (64 * 1024 * 1024) - (32 * 1024)) octet est optimale pour cette méthode.
OriginalL'auteur Tapas Bose | 2011-09-11
Vous devez vous connecter pour publier un commentaire.
Windows a une dure limite sur la taille de transfert maximale, et si vous la dépassez, vous obtenez une exception d'exécution. Si vous avez besoin de tune. La deuxième version que vous donnez est supérieure parce qu'elle n'est pas que le fichier a été transféré complètement avec un
transferTo()
d'appel, qui s'accorde avec la Javadoc.Réglage de la taille de transfert de plus que d'environ 1 MO est assez inutile de toute façon.
MODIFIER Votre deuxième version a une faille. Vous devriez décrémenter
size
par le montant transféré à chaque fois. Il devrait être plus comme:Pourquoi devrait
maxCount
être décrémenté?Autant que je sache,
maxCount
doit être décrémenté que si elle est donnée la valeur de la taille du fichier dans le tout début:maxCount = filesize
, puis décrémente à chaque boucle.Ce que je comprends,
size
devrait pas être décrémenté.size
est le nombre total d'octets à lire, c'est à direinChannel.size()
. Vous voulez continuer à liremaxCount
octets dans une boucle, tout en incrémentantposition
jusqu'àposition
atteint la fin de la chaîne, c'est à direwhile (position < size)
. Pouvez-vous expliquer pourquoi vous voulez décrémentersize
? Si vous le faites, puis à chaque itération, vous êtes l'incrémentationposition
, c'est à dire faire avancer le début de la plage d'octets que vous lisez, et de décrémentationsize
signifie que vous apportez à la fin de la plage d'octets de plus en plus proche.Lire le code à nouveau.
size
n'est pas le nombre d'octets gauche transférer.size
est la fin de l'entrée. La valeur deposition
besoin pour continuer à avancer jusqu'à la position max, valeur, qui estsize
. Donc,size
est la valeur maximale queposition
peut avoir, parce que vous êtes à la fin du fichier. C'est la EOF position. Sa valeur reste la même tout au long de. Je ne sais pas si j'ai été assez clair. Ce que vous dites, c'est "avancer vers votre but, et continuez à déplacer votre poteau de but plus proche". Que serait le double-compte de vos progrès.OriginalL'auteur user207421
J'ai lu que c'est pour la compatibilité avec le système d'exploitation Windows 2000.
Source: http://www.rgagnon.com/javadetails/java-0064.html
Citation: win2000, la transferTo() ne permet pas de transférer des fichiers > de 2^31-1 octets. elle lève une exception de "java.io.IOException: ressources système Insuffisantes pour terminer le service demandé est levée." La solution consiste à copier dans une boucle de 64 mo à chaque fois jusqu'à ce qu'il n'y a plus de données.
Eh bien, j'ai testé le transferTo avec et sans la boucle sur ma plate-forme Windows 8 et n'a connu qu'une différence de temps (en effet, la boucle a été plus rapide, mais je ne peux pas la mettre en œuvre dans le cadre de mes projets, sans savoir pourquoi il était plus rapide). Cependant, les résultats des tests étaient que tous les deux terminé avec succès avec des fichiers de plus de 2 go en taille. Je ne peux pas trouver une source pour votre "Windows a une dure limite sur la taille de transfert maximale de commentaire. Pourriez-vous nous en fournir une?
Votre lien dit exactement cela. À deux reprises.
OriginalL'auteur Danny Rancher
Il semble y avoir des preuves anecdotiques que les tentatives de transfert de plus de 64 mo à l'heure sur certaines versions de Windows résultats dans un lent copie. D'où la case: cela semble être le résultat d'un détail de la sous-jacentes du code natif qui implémente l'
transferTo
fonctionnement sur Windows.Ah, les éléments de preuve. Jetez un oeil à bugs.sun.com/view_bug.do?bug_id=6822107: avis de l'64 MO nombre de cité. Je suppose que c'est le plus propre de la source pour la valeur magique.
Je les ai lus il y a des années. Il n'y a rien au sujet de "certaines versions de Windows" ou "des résultats dans une lente copie" dans ce un bug, ou de l'une de bugs liés. Le nombre réel dans l'évaluation est de 1,5 GO.
OriginalL'auteur Femi