java多線程復制文件

jopen 11年前發布 | 27K 次閱讀 Java開發 Java

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);
 }

}</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!