package com.dhcc.thread;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class TestIo {
String mubiao;
String dizhi;
int startIndex;
int endIndex;
int threadNnum;
public TestIo(String mubiao, String dizhi, int threadNnum) {
super();
this.mubiao = mubiao;
this.dizhi = dizhi;
this.threadNnum = threadNnum;
}
public void copy() throws IOException {
for (int id = 0; id < threadNnum; id++) {
new Thread(new Doww(mubiao, dizhi, id, threadNnum)).start();
}
}
public static void main(String[] args) {
TestIo t = new TestIo("E://aaaa//85、搜狐邮箱.wmv", "E://aaaa//bbbb.wmv", 3);
try {
t.copy();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Doww extends Thread {
String mubiao;
String dizhi;
int startIndex;
int endIndex;
int id;
int count;
int threadNnum;
public Doww(String mubiao, String dizhi, int id, int threadNnum) {
this.mubiao = mubiao;
this.dizhi = dizhi;
this.id = id;
this.threadNnum = threadNnum;
}
@Override
public void run() {
RandomAccessFile fis = null;
RandomAccessFile raf = null;
try {
fis = new RandomAccessFile(new File(mubiao), "r");
raf = new RandomAccessFile(new File(dizhi), "rw");
int total = (int) fis.length();
int count = total / threadNnum;
startIndex = id * count;
endIndex = (id + 1) * count - 1;
fis.seek(startIndex);
raf.seek(startIndex);
byte[] bytes = new byte[250];
int len = 0;
while (startIndex <= endIndex) {
len = fis.read(bytes);
raf.write(bytes, 0, len);
startIndex += len;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
上次分片下载有bug,bug是下载的线程只是一部分,使用三个线程,结果只有三分之一下载好。
原因是每一个线程,都会产生一个新的io流,每个io流read个write都是从头开始读写,因此读写的文件只能是一部分。相当于每个线程都是从头开始下载文件的。
解决办法,
fis.seek(startIndex);
raf.seek(startIndex);
使用RandomAccessFile的seek,这个方法可以保存文件读写的位置。我控制startIndex每次位置不一样,第一个线程从0开始读写,第二个从count开始读写,第三个 2*count 读写。
这样每次控制读的位置和写的位置我都能控制。尽管每次产生的都是不同的RandomAccessFile对象,但是我控制每次读写位置不一样。
不然如果使用FileInputStream 每次都是不同的对象,每次读都是从头开始读,这样复制下来的是一样的,每个线程读写同样的东西。