我有几天陷入困境,我不知道该怎么做。
目的是将文件上传到Google云端存储,但由于它是一个大文件,我想要一些效率,我使用一个线程来读取它,我预先将文件切成2Mo块。这些块存储在一个小队列中(大约2到5个插槽),并且可以由我的上传器类(发出PUT请求的那个)访问
但是(因为总有一个)块在每台计算机上都不一致。我尝试了很多东西,BufferedInputStream,PushBackInputStream,FileChannel(有或没有MappedByteBuffer)没什么可做的,受影响的计算机在读取过程中某处失败,而最后一部分(小于正常块)总是比预期的要大(所以总数读取的字节数超过了原始计算的文件大小。)
我不知道为什么,但在某些计算机上(数量很大),在阅读过程中文件似乎会增长。 我错过了什么 ?我究竟做错了什么 ?我可以截断剩余的字节吗?但如果它突然小于预期怎么办呢? 我没有想法,所以我要求你:)
哦,小技巧,由于上传过程中的恢复能力,我必须能够回到我的阅读中,所以它减少了我可以使用的课程数量(标记支持,或者在fileChannel的情况下位置)。
如果您对CPU和内存优化有任何建议,那么您也会受到欢迎:)(不是全部,但剩下的只是用q执行BlockingQueue)
这是我读者的过去: http://paste.awesom.eu/Teraglehn/pw09&ln
有趣的部分:
public void run() {
try {
byte[] chunk = new byte[chunkSize];
int read;
int r;
long skipped;
while (!shouldStop && !finishReading && !stopped) {
if(size()>=maxSize){
continue;
}
read = 0;
System.out.println("[available1] "+available);
System.out.println("[available2] "+inputStream.available());
if(pendingFix !=0){
System.out.println(String.format("Fix of %d bytes asked", pendingFix));
clear();
if (pendingFix > 0 ) {
pendingFix = Math.min(pendingFix, (int) available);
skipped = inputStream.skip((long) pendingFix);
if(skipped != pendingFix){
throw new IOException(String.format("Ask fix of %d bytes has not been completely done (%d bytes actually skipped for unknown reason)", pendingFix, skipped));
}
incrementCursor(pendingFix);
}else {
decrementCursor(Math.min(cursor, -pendingFix));
inputStream.reset();
skipped = inputStream.skip(cursor);
if(skipped != cursor){
throw new IOException(String.format("Ask fix of %d bytes has not been completely done (%d bytes actually back skipped for unknown reason)", pendingFix, cursor-skipped));
}
}
pendingFix = 0;
}
while(read < chunkSize){
r = inputStream.read(chunk, read, chunkSize-read);
if(r<0) {
read = (read > 0)? read : r;
break;
}
else {
read +=r;
}
}
if(pendingFix!=0) continue;
if(read != chunkSize){ // Probably end of file
if(read == -1){
finishReading = true;
}else if(available == read){
System.out.println("Partial chunk (end)");
incrementCursor(read);
put(Arrays.copyOfRange(chunk, 0, read));
finishReading = true;
}else {
throw new IOException(String.format("Only %d bytes have been read on %d bytes asked for unknown reason, %d bytes available", read, chunkSize, available));
}
}else {
System.out.println("Full chunk (running)");
put(chunk.clone());
incrementCursor(read);
}
}
}catch(IOException e){
this.interrupt();
errors.add(e);
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
stopped = true;
}
PS:这一切都很有趣,我按会话上传会话,会话是一个包含一个或多个大文件的文件夹,它始终是最后一个失败的文件....
答案 0 :(得分:1)
当所有事情以某种方式发生时,你已经创造了一个混乱的东西,但是如果某些事情没有做到你期望的事情,它就会失败。您使用的available()
很可能是错误的,或者至少是无用的。
您的读取循环也是错误的,因为它填充了chunk
数组,但假设每次读取都完全填充(如果没有,则覆盖前面的字节)。
您的// Probably end of file
评论意味着您遇到了逻辑问题。因此,我建议用简单的英语写出逻辑,然后重写代码。