问题描述:
在客户端有一个大文件,要使用多线程将其上传到服务器端主要有以下问题。
一、怎样将这个文件拆分,以便每个线程传递其一部分,当然在客户端将其拆分好,再上传肯定是可以的。我的意思是可不可以先获得文件的输入流FileInputStream(new File(文件名)),然后在流里面控制要传递哪部分data。二、当这些被切割的文件传到服务器后,怎样在服务器端将其还原为原来的文件呢?
如果不能对服务器端编程,就不可能还原文件?
在客户端有一个大文件,要使用多线程将其上传到服务器端主要有以下问题。
一、怎样将这个文件拆分,以便每个线程传递其一部分,当然在客户端将其拆分好,再上传肯定是可以的。我的意思是可不可以先获得文件的输入流FileInputStream(new File(文件名)),然后在流里面控制要传递哪部分data。二、当这些被切割的文件传到服务器后,怎样在服务器端将其还原为原来的文件呢?
如果不能对服务器端编程,就不可能还原文件?
每个线程从固定的点开始读文件(读固定长度.)假设:文件有200个字节.
4个线程 分别从 0 50 100 150开始读,每个线程读50个字节,这样速度就能快很多.等上传完后再合并文件.我只知道一个合并文件的方法:
COPY:[源盘][路径]〈源文件名1〉〈源文件名2〉…[目标盘][路径]〈目标文件名〉;
思路的确是这样的,可是问题就在于怎样获得这个流的分割。我尝试了几种方案结果都不行。
一、用InputStream的skip(int len)方法过滤,因为只能跳转掉len长度后传输后面的字节,当有3个线程或更多时,肯定是不行的。二、结合FileChannel的position()方法,去定位流中当前要传输的位置,然后通过read(buf,0,length)取得要传输的那段流,比如ssnec说的传输50k到100k的位置,就可以fileIS.position(50K);
byte[] buf=new buf[50K];
fileIS.read(buf,0,50K);
来完成。但是当文件很大的时候呢,假如文件是2G,那么每个线程负责传500M。
还是这样的,byte[] buf=new buf[50M]; GOD!!这么大的数组,JVM马上就out of memory了。
ok,既然这样不行那就把buf设小一点,然后做一个判断,如下
file.position(startPos);
byte[] buf = new byte[2048];
int len=2048;
while (in.read(buf,0,len)!= -1 && startPos < endPos){
ftp.put(buf, fileName,true);
startPos=startPos+len;
}
似乎是可以了,但是这样频繁的put()操作也同样有问题,你会发现BindException的错误。
原因是短时间内new socket操作很多,而socket.close( )操作并不能立即释放绑定的端口,导致系统资源耗尽。所以最后还是决定放弃在流里面分割的想法,其实用多个线程传多个文件,和将一个大文件用多个线程传,效果也是一样的嘛。