java 多线程文件复制

目标是用多线程实现文件读取和写入,但是,实际却发现,java的io并不允许多线程同时写入,读取可以,本来想要 写个比操作系统快的复制功能,代码只实现了基本版本,还有缺陷,以后会继续完善,如果大家有更快速写入文件的方法,一定要留言哦

在目前没有多线程写入的前提下,读取后写入队列然后再起一个线程写文件会比现在的代码要快,但是也不是我想要的并发写入,大家有没有更好的解决方案。nio中的FileChannel.transferTo,经过测试,写入也是阻塞其他线程的

 

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.math.BigInteger;
 4 import java.security.MessageDigest;
 5 
 6 public class Digest {
 7     public static String getFileMD5(File file) {
 8         if (!file.isFile()) {
 9             return null;
10         }
11         MessageDigest digest = null;
12         FileInputStream in = null;
13         byte buffer[] = new byte[8192];
14         int len;
15         try {
16             digest = MessageDigest.getInstance("MD5");
17             in = new FileInputStream(file);
18             while ((len = in.read(buffer)) != -1) {
19                 digest.update(buffer, 0, len);
20             }
21             BigInteger bigInt = new BigInteger(1, digest.digest());
22             return bigInt.toString(16);
23         } catch (Exception e) {
24             e.printStackTrace();
25             return null;
26         } finally {
27             try {
28                 in.close();
29             } catch (Exception e) {
30                 e.printStackTrace();
31             }
32         }
33     }
34 
35     public static String getFileSha1(File file) {
36         if (!file.isFile()) {
37             return null;
38         }
39         MessageDigest digest = null;
40         FileInputStream in = null;
41         byte buffer[] = new byte[8192];
42         int len;
43         try {
44             digest = MessageDigest.getInstance("SHA-1");
45             in = new FileInputStream(file);
46             while ((len = in.read(buffer)) != -1) {
47                 digest.update(buffer, 0, len);
48             }
49             BigInteger bigInt = new BigInteger(1, digest.digest());
50             return bigInt.toString(16);
51         } catch (Exception e) {
52             e.printStackTrace();
53             return null;
54         } finally {
55             try {
56                 in.close();
57             } catch (Exception e) {
58                 e.printStackTrace();
59             }
60         }
61     }
62 }
Digest

 

  1 import java.io.File;
  2 import java.io.FileInputStream;
  3 import java.io.FileNotFoundException;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.RandomAccessFile;
  7 import java.text.DecimalFormat;
  8 
  9 public class CopyFile {
 10 
 11     private String fileName = "";
 12     private int buffSize = 1024;
 13     private long fileSize = 0;
 14     private int threadNum = 2;
 15     private String newName = "";
 16     private String newPath = "";
 17     private String copyIn = "";
 18     private boolean showProgress = true;
 19     private boolean end = false;
 20     long stime = 0;
 21     long etime = 0;
 22     private long copySize = 0;
 23     private File srcfile = null;
 24     File newFile = null;
 25     File filecopyIn = null;
 26 
 27     public CopyFile(String filePath) {
 28         this.fileName = filePath;
 29     }
 30 
 31     public CopyFile(String filePath, int threadNum) {
 32         this.fileName = filePath;
 33         this.threadNum = threadNum;
 34     }
 35 
 36     public CopyFile(String filePath, int threadNum, int buffSize) {
 37         this.fileName = filePath;
 38         this.buffSize = buffSize;
 39         this.threadNum = threadNum;
 40     }
 41 
 42     public void to() throws IOException {
 43         if (newPath == null || "".equals(newPath)) {
 44             newPath = new File(fileName).getParent();
 45             to(newPath);
 46         }
 47     }
 48 
 49     public void to(String newPath) throws IOException {
 50         if (!new File(newPath).isDirectory()) {
 51             throw new IOException("目标必须为目录");
 52         }
 53         srcfile = new File(fileName);
 54         stime = System.currentTimeMillis();
 55         this.newName = newFileName(newPath, fileName);
 56         copyIn = newName + ".copyIN";
 57         newFile = new File(newName);
 58         if (newFile.exists()) {
 59             newFile.delete();
 60         }
 61         filecopyIn = new File(copyIn);
 62         if (filecopyIn.exists()) {
 63             filecopyIn.delete();
 64         }
 65 
 66         InputStream in = new FileInputStream(srcfile);
 67         fileSize = in.available();
 68         for (int i = 0; i < threadNum; i++) {
 69             long s = fileSize / threadNum * i;
 70             long e = fileSize / threadNum * (i + 1)
 71                     + (i == threadNum - 1 ? fileSize % threadNum : 0);
 72             new copyThread(s, e);
 73         }
 74         if (showProgress)
 75             new Progress().start();
 76 
 77     }
 78 
 79     private String newFileName(String newPath2, String fileName2) {
 80         String tmp = srcfile.getName();
 81         int suffixIndex = tmp.lastIndexOf(".");
 82         if (suffixIndex > -1) {
 83             tmp = tmp.substring(0, suffixIndex) + " copy"
 84                     + tmp.substring(suffixIndex, tmp.length());
 85         } else {
 86             tmp += " copy";
 87         }
 88         if (!newPath2.endsWith(File.separatorChar + ""))
 89             newPath2 += File.separatorChar;
 90         return newPath2 + tmp;
 91     }
 92 
 93     public long end() {
 94         long newFileLength = 0;
 95         if (filecopyIn.renameTo(newFile)) {
 96             newFileLength = newFile.length();
 97         } else {
 98             System.out.println("重命名失败");
 99             newFileLength = filecopyIn.length();
100         }
101         long time = System.currentTimeMillis();
102         etime = time;
103         long haoshi = (etime - stime);
104         System.out.println("用时=" + haoshi + "毫秒");
105         System.out.println("源文件:" + fileSize + "   复制的文件:" + newFileLength
106                 + "   丢失:" + (fileSize - newFileLength));
107         System.out
108                 .println("文件:"
109                         + Digest.getFileMD5(srcfile).equals(
110                                 Digest.getFileMD5(newFile)));
111         end = true;
112         return haoshi;
113     }
114 
115     class Progress extends Thread {
116         public void run() {
117             DecimalFormat df = new DecimalFormat("0");
118             while (!end) {
119                 long progress = Integer.parseInt(df.format((float) copySize
120                         / fileSize * 100));
121                 System.out.println(progress + "%");
122                 if (progress == 100)
123                     end();
124                 try {
125                     sleep(1000);
126                 } catch (InterruptedException e) {
127                     e.printStackTrace();
128                 }
129             }
130         }
131     }
132 
133     class copyThread extends Thread {
134         private RandomAccessFile in = null;
135         private RandomAccessFile out = null;
136         private long startOff = 0, endOff = 0;
137         private byte[] buff;
138 
139         public copyThread(long startOff, long endOff) {
140             try {
141                 this.startOff = startOff;
142                 this.endOff = endOff;
143                 in = new RandomAccessFile(fileName, "r");
144                 in.seek(startOff);
145                 out = new RandomAccessFile(copyIn, "rwd");
146                 out.seek(startOff);
147                 start();
148             } catch (FileNotFoundException e) {
149                 e.printStackTrace();
150             } catch (IOException e) {
151                 e.printStackTrace();
152             }
153         }
154 
155         public void run() {
156             try {
157                 System.out.println("start=" + startOff + "  end=" + endOff);
158                 buff = new byte[buffSize];
159                 long currentThreadTotal = endOff - startOff;
160                 long yu = currentThreadTotal % buffSize;
161                 int off = buffSize;
162                 long forCount = currentThreadTotal / buffSize
163                         + (yu > 0 ? 1 : 0);
164                 for (long i = 0; i < forCount; i++) {
165                     off = (int) (i == forCount - 1 && yu > 0 ? yu : buffSize);
166                     int rd = in.read(buff, 0, off);
167                     if (rd != -1)
168                         out.write(buff, 0, rd);
169                     if (showProgress) {
170                         synchronized (this) {
171                             copySize += rd;
172                         }
173                     }
174                     yield();
175                 }
176 
177                 in.close();
178                 out.close();
179                 // end();
180             } catch (Exception e) {
181                 e.printStackTrace();
182             }
183         }
184     }
185 
186     public static void main(String[] args) {
187         String y = "e:/baidu download/贫民窟的百万富翁.rmvb";
188         String n = "e:/baidu download/";
189         CopyFile cf = new CopyFile(y, 3, 1024 * 1024 * 10);
190         try {
191             cf.to();
192         } catch (IOException e) {
193             e.printStackTrace();
194         }
195 
196     }
197 }

 

 

posted @ 2013-12-24 17:23  代码三郎  阅读(677)  评论(0编辑  收藏  举报