java中的大文件读取不一致

时间:2015-03-31 08:15:46

标签: java applet

我有几天陷入困境,我不知道该怎么做。

目的是将文件上传到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:这一切都很有趣,我按会话上传会话,会话是一个包含一个或多个大文件的文件夹,它始终是最后一个失败的文件....

1 个答案:

答案 0 :(得分:1)

当所有事情以某种方式发生时,你已经创造了一个混乱的东西,但是如果某些事情没有做到你期望的事情,它就会失败。您使用的available()很可能是错误的,或者至少是无用的。

您的读取循环也是错误的,因为它填充了chunk数组,但假设每次读取都完全填充(如果没有,则覆盖前面的字节)。

您的// Probably end of file评论意味着您遇到了逻辑问题。因此,我建议用简单的英语写出逻辑,然后重写代码。