记录一下多线程文件复制工具类、以后有需要可以拿来用。
存在一些问题:
A.怎么根据文件大小确定最佳的线程数 B.文件读取 buffer 大小多少才适合???
/**
*
*/
package com.demo.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.junit.Test;
/**
* @author rico
* 多线程文件复制工具类
*/
public class MultiThreadFileCopy {
public static void main(String[] args) {
//junit 断点好像调试不了线程/??/、?
new MultiThreadFileCopy().testCopyFile();
}
@Test
public void testCopyFile() {
//怎么根据文件大小确定最佳的线程数
int blocks = 3;
//源文件和目标文件
String filePath = "F:/demo.log";
String outFilePath = "F:/demo-copy-multi.log";
try {
File file = new File(filePath);
long fileSize = file.length();
long blockSize = fileSize / blocks; //每个线程操作的文件大小
long lastBlockSize = fileSize % blockSize; //文件大小不能整除线程数,文件剩余的数据会被添加到最后一个线程中操作
System.out.println("###fileSize: " + fileSize);
System.out.println("###blockSize: " + blockSize);
System.out.println("###lastBlockSize: " + lastBlockSize);
for(int i=0; i<blocks; i++) {
if(i == blocks-1) {
blockSize += lastBlockSize;
}
Runnable r = new CopyThread(filePath, outFilePath, i, blockSize, fileSize);
new Thread(r).start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
public class CopyThread implements Runnable {
String filePath;
String outFilePath;
int block;
long blockSize;
long fileSize;
public CopyThread(String filePath, String outFilePath, int block, long blockSize, long fileSize) {
this.filePath = filePath;
this.outFilePath = outFilePath;
this.block = block;
this.blockSize = blockSize;
this.fileSize = fileSize;
}
@Override
public void run() {
FileInputStream fis = null;
RandomAccessFile raf = null;
try {
System.out.println("####block: " + block *blockSize);
fis = new FileInputStream(new File(filePath));
raf = new RandomAccessFile(new File(outFilePath), "rw");
fis.skip(block * blockSize);
raf.seek(block * blockSize);
//buffer 大小多少才适合???
byte[] bytes = new byte[1024 * 100];
int len = fis.read(bytes);
long totalBlockSize = len;
while(len > -1) {
if(totalBlockSize < blockSize) {
raf.write(bytes, 0, len);
len = fis.read(bytes);
} else if(totalBlockSize == blockSize) {
raf.write(bytes, 0, len);
len = -1;
} else {
if(totalBlockSize-len < blockSize) {
int leftBlockSize = (int) (len - (totalBlockSize-blockSize));
raf.write(bytes, 0, leftBlockSize);
len = -1;
}
}
System.out.println("####totalBlockSize: " + totalBlockSize);
System.out.println("####len: " + len);
totalBlockSize += len;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fis != null)
fis.close();
if(raf != null)
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}