不完整的文件复制Java NIO

时间:2016-04-27 11:21:29

标签: java asynchronous nio filechannel

我在阅读文件时遇到问题。我对NIO也很陌生。我要发送到服务器的文件的实际大小几乎 900MB ,只收到 3MB

服务器的阅读旁边代码:

private void read(SelectionKey key) throws IOException{
    SocketChannel socket = (SocketChannel)key.channel();
    RandomAccessFile aFile = null;
    ByteBuffer buffer = ByteBuffer.allocate(300000000);
    try{
        aFile = new RandomAccessFile("D:/test2/test.rar","rw");

        FileChannel inChannel = aFile.getChannel();

        while(socket.read(buffer) > 0){
            buffer.flip();
            inChannel.write(buffer);
            buffer.compact();
        }
        System.out.println("End of file reached..");
    }catch(Exception e){
        e.printStackTrace();
    }
}

这是我的客户端写方法的代码:

private void write(SelectionKey key) throws IOException {
    SocketChannel socket = (SocketChannel) key.channel();
    RandomAccessFile aFile = null;
    try {
        File f = new File("D:/test.rar");
        aFile = new RandomAccessFile(f, "r");
        ByteBuffer buffer = ByteBuffer.allocate(300000000);

        FileChannel inChannel = aFile.getChannel();
        while (inChannel.read(buffer) > 0) {
            buffer.flip();
            socket.write(buffer);
            buffer.compact();
        }
        aFile.close();
        inChannel.close();

        key.interestOps(SelectionKey.OP_READ);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

1 个答案:

答案 0 :(得分:3)

  1. 每次套接字通道可读时,您都会打开一个新文件。到达的每个TCP段,您都会重新创建目标文件,因此丢弃以前收到的任何内容。

    对此的简单修复是打开文件以便在每个OP_READ上追加,但它仍然会非常低效。您应该在知道目标文件后立即打开目标文件,并在读取发件人的流末尾时关闭目标文件,或者如果您没有在结束时发出信号,则将其关闭。流。您尚未披露您的申请协议,因此我无法更具体。

  2. 当没有可用于无阻塞的数据时,
  3. read()返回零。您将其视为文件的结尾。它不是。
  4. 在频道之间的规范方法如下:

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

    但是,如果目标是非阻塞套接字通道,则会变得相当复杂:您必须操纵是否为OP_WRITE选择,具体取决于最后write()是否返回零。你会发现这里有很多帖子解释过,很多都是我。

  5. 我从未见过客户端非阻塞I / O的任何令人信服的理由,除非它连接到多个服务器(例如网络爬虫)。我会在客户端使用阻塞模式或java.net.Socket,这将消除上面提到的写入复杂性。

  6. 注意,您不需要关闭从中获取的RandomAccessFileFileChannel。要么会这样做。