java多线程复制文件

来源:互联网 发布:淘宝上怎么找到凤楼 编辑:程序博客网 时间:2024/06/04 18:00
package com.test;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;public class FileCoper {private static final String _ORIGIN_FILE_MODE = "r";  private static final String _TARGET_FILE_MODE = "rw"; private static long time1 = 0l; private String originFileName;  private String targetFileName;  private RandomAccessFile originFile;  private RandomAccessFile targetFile;  private int threadCount;  private static int totalThreadCount = 0;  private static int executedCount = 0; public FileCoper() {  this.threadCount = 1;  totalThreadCount = this.threadCount; } public FileCoper(String originFile, String targetFile) {  try {   this.originFileName = originFile;   this.targetFileName = targetFile;   this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE);   this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE);   this.threadCount = 1;   totalThreadCount = this.threadCount;  } catch (FileNotFoundException e) {   e.printStackTrace();  } } public FileCoper(String originFile, String targetFile, int threadCount) {  try {   this.originFileName = originFile;   this.targetFileName = targetFile;   this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE);   this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE);   this.threadCount = 1;   totalThreadCount = this.threadCount;  } catch (FileNotFoundException e) {   e.printStackTrace();  } }  public void init(String originFile, String targetFile) throws Exception {  this.originFileName = originFile;  this.targetFileName = targetFile;  this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE);  this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE);  this.threadCount = 1;  totalThreadCount = this.threadCount; }  public void init(String originFile, String targetFile, int threadCount) throws Exception {  this.originFileName = originFile;  this.targetFileName = targetFile;  this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE);  this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE);  this.threadCount = threadCount;  totalThreadCount = this.threadCount; }  public void init(RandomAccessFile originFile, RandomAccessFile targetFile) throws Exception {  this.originFile = originFile;  this.targetFile = targetFile;  this.threadCount = 1;  totalThreadCount = this.threadCount; }  public void init(RandomAccessFile originFile, RandomAccessFile targetFile, int threadCount) throws Exception {  this.originFile = originFile;  this.targetFile = targetFile;  this.threadCount = threadCount;  totalThreadCount = this.threadCount; }  public static synchronized void finish() {  FileCoper.executedCount ++;    System.out.println("总线程【" + FileCoper.totalThreadCount + "】,已经完成【" + FileCoper.executedCount + "】个线程的复制!!!");  if (FileCoper.totalThreadCount == FileCoper.executedCount){  long time2 = System.currentTimeMillis();  System.out.println("花费时长:"+(time2-time1));   System.out.println("所有【" + FileCoper.totalThreadCount + "】线程复制完成!!!");  } }  public void start() throws Exception {  if (this.originFile.length() == 0)   return;  if (this.threadCount == 0)   this.threadCount = 1;  // 设置目标文件大小  this.targetFile.setLength(this.originFile.length());  this.targetFile.seek(0);  this.originFile.seek(0);      time1 = System.currentTimeMillis();  System.out.println(this.originFile.length());  // 把文件分块,每一块有一对值:当前块在文件中的起始位置和结束位置  long[][] splits = new long[this.threadCount][2];  long originFileLength = this.originFile.length();  int startPos = 0;  for (int i = 0; i < this.threadCount; i++) {   splits[i][0] = 0;   splits[i][1] = 0;   if (i == 0) {    splits[i][0] = 0;    splits[i][1] = originFileLength / this.threadCount;   } else if (i == this.threadCount - 1) {    // 注意:此处不能加1,如果加1,线程多文件就会出现乱码    // splits[i][0] = startPos + 1;    splits[i][0] = startPos;    splits[i][1] = originFileLength;   } else {    // 注意:此处不能加1,如果加1,线程多文件就会出现乱码    // splits[i][0] = startPos + 1;    splits[i][0] = startPos;    splits[i][1] = startPos + originFileLength / this.threadCount;   }   startPos += originFileLength / this.threadCount;   // System.out.println(splits[i][0] + " " + splits[i][1]);   Coper fc = new Coper("thread-" + i);   fc.init(this.originFile, this.targetFile, splits[i][0], splits[i][1]);   fc.setOriginFileName(this.originFileName);   fc.setTargetFileName(this.targetFileName);   fc.start();  } }  public void startNew() throws Exception {  if (this.originFile.length() == 0)   return;  // 设置目标文件大小  this.targetFile.setLength(this.originFile.length());  this.targetFile.seek(0);  this.originFile.seek(0);  long startPosition;  long endPosition;  long block = this.originFile.length() / 1029;  if (block <= 1)   this.threadCount = 1;  for (int i = 0; i < this.threadCount; i++) {   // 定义每次转移的长度   startPosition = i * 1029 * (block / this.threadCount);   endPosition = (i + 1) * 1029 * (block / this.threadCount);   if (i == (this.threadCount - 1))    endPosition = this.originFile.length();   Coper fc = new Coper("thread-" + i);   fc.init(this.originFile, this.targetFile, startPosition, endPosition);   fc.setOriginFileName(this.originFileName);   fc.setTargetFileName(this.targetFileName);   fc.start();  } } private class Coper extends Thread {    private String originFileName;    private String targetFileName;    private RandomAccessFile originFile;    private RandomAccessFile targetFile;    private String threadId;    private long startPosition;    private long endPosition;    private long blockCapacity;    public void setOriginFileName(String originFileName) {   this.originFileName = originFileName;  }    public void setTargetFileName(String targetFileName) {   this.targetFileName = targetFileName;  }  public Coper(String threadId) {   this.threadId = threadId;  }    public void init(RandomAccessFile originFile, RandomAccessFile targetFile, long startPosition, long endPosition) throws Exception {   this.originFile = originFile;   this.targetFile = targetFile;   this.startPosition = startPosition;   this.endPosition = endPosition;   this.blockCapacity = this.endPosition - this.startPosition;  }  public void run() {   // System.out.println(this.threadId + " 启动,开始复制文件【" +   // this.originFileName + "】中的文件块【" + this.startPosition + "," +   // this.endPosition + "】到目标文件【" + this.targetFileName + "】中...");   synchronized (this.originFile) {    try {     // 记录当前拷贝的字节数     int copyCount = 0;     // 数据拷贝的启示偏移量     long offSet = this.startPosition;     byte[] b = new byte[16 * 1024 * 1024];     // 动态设置一次读取的字节数缓冲     long blockSize = 0;     while (copyCount < this.blockCapacity) {      this.originFile.seek(offSet);      if (this.blockCapacity - copyCount > 16 * 1024 * 1024)       blockSize = 16 * 1024 * 1024;      else       blockSize = this.blockCapacity - copyCount;      if (blockSize > this.blockCapacity - copyCount)       blockSize = this.blockCapacity - copyCount;      int count = this.originFile.read(b, 0, (int) blockSize);      synchronized (this.targetFile) {       try {        if (copyCount == 0)         this.targetFile.seek(offSet);        else         this.targetFile.seek(offSet + 1);        this.targetFile.write(b, 0, count);       } catch (IOException e) {        e.printStackTrace();       }      }      // 增加拷贝的字节数      copyCount += count;      // 拷贝其实【偏移量下移      offSet += count;     }    } catch (IOException e) {     e.printStackTrace();    }   }   // System.out.println(this.threadId + " 复制文件【" + this.originFileName   // + "】中的文件块【" + this.startPosition + "," + this.endPosition +   // "】到目标文件【" + this.targetFileName + "】完成!");   // 通知主线程,当前线程完成复制工作   FileCoper.finish();  } } public static void main(String[] args) throws Exception {  FileCoper fc = new FileCoper();  fc.init("e:/InitialData_zhihuan.sql", "e:/InitialData_zhihuan2.sql", 30);  //fc.init("d:/ValueAdd_11.txt", "d:/ValueAdd_111.txt", 100);  // fc.init("D:\tools\music\做你的爱人.mp3", "d:/做你的爱人_5.mp3", 10);  //fc.init("E:\电影\最黑暗侵袭.rmvb", "d:/最黑暗侵袭_1.rmvb", 100);   /* // 读入键盘输入  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  // 文件来源  String originFile;  // 文件目标  String targetFile;  System.out.println("【源文件、目标文件、线程数】");  System.out.print("要复制的源文件:");  originFile = br.readLine();  System.out.print("文件复制到目标文件:");  targetFile = br.readLine();  System.out.print("切分线程数:");  int threadCount = Integer.parseInt(br.readLine());  fc.init(originFile, targetFile, threadCount);*/  // fc.startNew();  long time1 = System.currentTimeMillis();  fc.start();  long time2 = System.currentTimeMillis();  System.out.println(time2-time1); }}