私はクライアントマシンからネットワークフォルダ(UNCパス)にファイルをコピーするために使用されるファイルコピーアプリケーションに取り組んでいます。クライアントとネットワークフォルダは10Gbps接続で接続されています。従来のストリーム/バッファ機構では最大250Mbpsしか使用できませんでした。だから私はNIOメソッドを使い始めたのです。 Files.copy()
とtransferFrom()
の両方の方法で最大6Gbpsの帯域幅を使用できますが、これで十分です。しかし問題は、これらの両方の方法が進歩をもたらさないということです。アプリケーションにファイルの進行状況を表示する必要があります。進捗状況を監視する最速のJavaファイルコピー方法は何ですか?
次に、アップロードの進捗状況を追跡するためのReadableByteChannel
インターフェイスが見つかりました。しかし、これを実装した後、アップロード速度は100Mbpsに落ちました。私が正しく実装していないかどうかはわかりません。
OSレベルのコピー(Ctrl + CとCtrl + V)は、6Gbpsの帯域幅使用で動作します。どのように進捗監視とJavaメソッドで同じを達成するために?
public class AppTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
File source = new File(args[0]);
File dest = new File(args[1] + File.separator + source.getName());
long startTime = System.currentTimeMillis();
try {
if (args[2].equalsIgnoreCase("s")) {
copyUsingStream(source, dest, args.length > 3 ? Integer.parseInt(args[3]) : 32 * 1024);
} else if (args[2].equalsIgnoreCase("fp")) {
copyUsingFileChannelWithProgress(source, dest);
} else if (args[2].equalsIgnoreCase("f")){
copyUsingFileChannels(source, dest);
} else if (args[2].equalsIgnoreCase("j")) {
copyUsingFilescopy(source, dest);
} else {
System.out.println("Unknown copy option.");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Completed in " + (System.currentTimeMillis() - startTime));
}
private static void copyUsingStream(File source, File dest, int buf_size) throws IOException {
System.out.println("Copying using feeder code...");
System.out.println("Buffer Size : " + buf_size);
FileInputStream sourceFileIS = new FileInputStream(source);
FileOutputStream srvrFileOutStrm = new FileOutputStream(dest);
byte[] buf = new byte[buf_size];
int dataReadLen;
while ((dataReadLen = sourceFileIS.read(buf)) > 0) {
srvrFileOutStrm.write(buf, 0, dataReadLen);
}
srvrFileOutStrm.close();
sourceFileIS.close();
}
private static void copyUsingFileChannels(File source, File dest)
throws IOException {
System.out.println("Copying using filechannel...");
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} finally {
inputChannel.close();
outputChannel.close();
}
}
private static void copyUsingFilescopy(File source, File dest) throws IOException{
Files.copy(source.toPath(), dest.toPath());
}
interface ProgressCallBack {
public void callback(CallbackByteChannel rbc, double progress);
}
static class CallbackByteChannel implements ReadableByteChannel {
ProgressCallBack delegate;
long size;
ReadableByteChannel rbc;
long sizeRead;
CallbackByteChannel(ReadableByteChannel rbc, long sizeRead, long expectedSize, ProgressCallBack delegate) {
this.delegate = delegate;
this.sizeRead = sizeRead;
this.size = expectedSize;
this.rbc = rbc;
}
@Override
public void close() throws IOException {
rbc.close();
}
public long getReadSoFar() {
return sizeRead;
}
@Override
public boolean isOpen() {
return rbc.isOpen();
}
@Override
public int read(ByteBuffer bb) throws IOException {
int n;
double progress;
if ((n = rbc.read(bb)) > 0) {
sizeRead += n;
progress = size > 0 ? (double) sizeRead/(double) size * 100.0 : -1.0;
delegate.callback(this, progress);
}
return n;
}
}
private static void copyUsingFileChannelWithProgress(File sourceFile, File destFile) throws IOException {
ProgressCallBack progressCallBack = new ProgressCallBack() {
@Override
public void callback(CallbackByteChannel rbc, double progress) {
// publish((int)progress);
}
};
FileOutputStream fos = null;
FileChannel sourceChannel = null;
sourceChannel = new FileInputStream(sourceFile).getChannel();
ReadableByteChannel rbc = new CallbackByteChannel(sourceChannel, 0, sourceFile.length(), progressCallBack);
fos = new FileOutputStream(destFile);
fos.getChannel().transferFrom(rbc, 0, sourceFile.length());
if (sourceChannel.isOpen()) {
sourceChannel.close();
}
fos.close();
}
}
ありがとうございました! –