程序员潇然 发表于 2022-7-30 12:03:27

NIO随机写文件按照position写文件 文件片段报文写文件

有的时候我们可能是通过网络接收到的报文,报文的内容其实是文件片段,一个文件的报文可能非常多,而且可能不是有序的。

比如这样一个场景:

文件按照字节切分为片段,通过网络传送,报文自身保存了总包数以及子包号,如何快速有效的合成文件呢?

可以借助于Java中的nio实现

### `fileChannel.write(byteBuffer, position)`

```java
    /**
   * Writes a sequence of bytes to this channel from the given buffer,
   * starting at the given file position.
   *
   * <p> This method works in the same manner as the {@link
   * #write(ByteBuffer)} method, except that bytes are written starting at
   * the given file position rather than at the channel's current position.
   * This method does not modify this channel's position.If the given
   * position is greater than the file's current size then the file will be
   * grown to accommodate the new bytes; the values of any bytes between the
   * previous end-of-file and the newly-written bytes are unspecified.</p>
   *
   * @paramsrc
   *         The buffer from which bytes are to be transferred
   *
   * @paramposition
   *         The file position at which the transfer is to begin;
   *         must be non-negative
   *
   * @returnThe number of bytes written, possibly zero
   *
   * @throwsIllegalArgumentException
   *          If the position is negative
   *
   * @throwsNonWritableChannelException
   *          If this channel was not opened for writing
   *
   * @throwsClosedChannelException
   *          If this channel is closed
   *
   * @throwsAsynchronousCloseException
   *          If another thread closes this channel
   *          while the write operation is in progress
   *
   * @throwsClosedByInterruptException
   *          If another thread interrupts the current thread
   *          while the write operation is in progress, thereby
   *          closing the channel and setting the current thread's
   *          interrupt status
   *
   * @throwsIOException
   *          If some other I/O error occurs
   */
    public abstract int write(ByteBuffer src, long position) throws IOException;
```

这个方法可以通过指定保存的位置,进行文件字节的写入。

通常来说数据的发送代码的设计,除非是最后一包,否则前面应该都是相同大小的

这样通过子包号就可以计算每一个包应该的位置,类似于分页

核心代码

#### 文件通道

```java
      File file = new File("d:/test.exe");
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      FileChannel fileChannel = fileOutputStream.getChannel();
```

#### 写文件

通常是循环接收文件的过程中进行处理

sendContents 表示读取到的字节   position 表示位置,packNo 表示子包号

定长的时候,只有最后一包可能大小不同,所以除了最后一包,处理时可以使用下面的逻辑

最后一包处理完前面的最后处理即可,细节可以根据业务情况自己确定

```java
            byte[] sendContents = something.getBytes;
            long position = (packNo - 1) * sendContents.length;
            // 将字符串放入缓存区
            ByteBuffer byteBuffer = ByteBuffer.wrap(sendContents);
            fileChannel.write(byteBuffer, position);

```

补充:

写文件时候的position 序号是从0 开始的,不要搞错了

子包号也需要关注下是0开始还是1 开始,上面的样例代码是从1 开始的

不需要关注文件大小的问题,会根据position 有一些调整,只需要按照position写即可

!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-101-1-1.html `
页: [1]
查看完整版本: NIO随机写文件按照position写文件 文件片段报文写文件