我在某個問題上停留了一段時間,我不知道該怎麼做。java中的大文件讀取不一致問題
目的是將文件上傳到Google Cloud Storage,但由於它是一個大文件,而且我想要一些效率,所以我使用一個線程來讀取它,並且我以2Mo的塊爲單位預先分割該文件。這些塊存儲在一個小隊列中(大約2到5個插槽),並且可以由我的上傳者類(進行PUT請求的人)訪問。
但是(因爲總是有一個)塊在每臺計算機上都不一致。我嘗試了很多事情,BufferedInputStream,PushBackInputStream,FileChannel(有或沒有MappedByteBuffer)都沒有什麼可做,受到影響的計算機在閱讀期間失敗,最後一部分(比正常塊小)比預期的要大(所以總數讀取的字節數超過原始計算的文件大小)。
我不知道爲什麼,但在某些計算機上(顯着數量),看起來文件在閱讀期間增長。 我錯過了什麼嗎?我究竟做錯了什麼 ?我可以截斷剩餘的字節嗎?但如果突然小於預期,該怎麼辦? 我出來的想法,所以我請求你的:)
哦,一點點技巧,由於在上傳過程中恢復能力,我必須能夠回到我的閱讀,所以這是減少我的班級數量使用(標記支持,或fileChannel情況下的位置)。
如果您對CPU和內存優化任何意見,歡迎您太:)(這裏沒有這一切,但其餘它只是BlockingQueue的實現與Q)
這裏是我的讀者的過去: 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:有一些樂趣,這一切,我通過會議上傳會話,會話與一個或多個大型文件的文件夾,它總是ŧ他最後一個失敗的文件....
這一切都太複雜了。你需要知道的基本事情是read()沒有義務填充緩衝區。 – EJP 2015-03-31 09:10:40
我知道,這就是爲什麼有一段時間。但爲什麼它閱讀更多的應該保持閱讀文件?這就是問題所在 ! PS:爲什麼只有一些電腦?我甚至嘗試在受影響的PC上的IDE中運行讀卡器,使用相同的文件上傳,並且它完美地工作... – 2015-03-31 09:17:46