使用RamdomAccesFile和FileChannel分块文件时出现问题

时间:2014-07-10 00:45:58

标签: java file-io java-7 nio

我编写了这段代码,将文件分成多个块。该程序适用于大小为12KB且块大小为8KB的文件。但是,当我给出一个2980144字节的输入文件大小时,它会进入旋转状态 - 永远不会出现。

是否与输入文件的大小和要访问的FileChannel问题有关?我想使用这个程序将较大的文件(二进制形式)分成多个块,以便通过网络轻松传输。我将块大小保留为参数,以便我可以根据需要进行配置。

public static void main(String[] args) {

    int chunkSize = 8000;

    long offset = 0;
    while (offset >= 0) {
        offset = splitter.GetNextChunk(offset);
    }
}

public long GetNextChunk(long offset) {

    long bytesRead = 0;
    ByteBuffer tmpBuf = ByteBuffer.allocate(chunkSize);
    RandomAccessFile outFile = null;
    RandomAccessFile inFile = null;
    FileChannel inFC = null;
    FileChannel outFC = null;

    try {
        inFile = new RandomAccessFile(inFileName, "r");
        inFC = inFile.getChannel();
        tmpBuf.clear();

        // Seek to the offset in the file
        inFC.position(offset);

        // Read the specified number of bytes into the buffer.  
        do {
            bytesRead = inFC.read(tmpBuf);
        } while (bytesRead != -1 && tmpBuf.hasRemaining());

        // Write the copied bytes into a new file (chunk).
        String outFileName = outFolder + File.separator + "Chunk" + String.valueOf(chunkCounter++) + ".dat";
        outFile = new RandomAccessFile(outFileName, "rw");
        outFC = outFile.getChannel();

        outFC.position(0);
        tmpBuf.flip();

        while(tmpBuf.hasRemaining()) {
            outFC.write(tmpBuf);
        }

        // Reposition the buffer to 0.
        tmpBuf.rewind();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        try {
            if (inFC != null)
                inFile.close();

            if (outFC != null)
                outFile.close();

            if (inFC != null)
                inFC.close();

            if (outFC != null)
                outFC.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    return bytesRead;
}

2 个答案:

答案 0 :(得分:1)

发现了这个问题。循环有问题。下面是正确的循环。

    while (bytesRead >= 0) {
        bytesRead = splitter.GetNextChunk(offset);

        if (bytesRead == -1)
            break;

        offset += bytesRead;
        System.out.println("Byte offset is: " + offset);
    }

答案 1 :(得分:1)

它并不像你制作它那么难。你的代码大约是它需要的十倍。试试这个:

while (in.read(buffer) > 0 || buffer.position() > 0)
{
    buffer.flip();
    out.write(buffer);
    buffer.compact();
}

如果'out'是SocketChannel,它将以最大速度通过网络发送文件。

你不需要一个monstro缓冲区,但你应该总是使用2的幂。我通常使用8192.