[代码段] NIO随机写文件按照position写文件 文件片段报文写文件

技术实战 技术实战 7731 人阅读 | 0 人回复

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

比如这样一个场景:

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

可以借助于Java中的nio实现

fileChannel.write(byteBuffer, position)

    /**
     * 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>
     *
     * @param  src
     *         The buffer from which bytes are to be transferred
     *
     * @param  position
     *         The file position at which the transfer is to begin;
     *         must be non-negative
     *
     * @return  The number of bytes written, possibly zero
     *
     * @throws  IllegalArgumentException
     *          If the position is negative
     *
     * @throws  NonWritableChannelException
     *          If this channel was not opened for writing
     *
     * @throws  ClosedChannelException
     *          If this channel is closed
     *
     * @throws  AsynchronousCloseException
     *          If another thread closes this channel
     *          while the write operation is in progress
     *
     * @throws  ClosedByInterruptException
     *          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
     *
     * @throws  IOException
     *          If some other I/O error occurs
     */
    public abstract int write(ByteBuffer src, long position) throws IOException;

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

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

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

核心代码

文件通道

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

写文件

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

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

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

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

            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写即可

common_log.png 转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-101-1-1.html

关注下面的标签,发现更多相似文章
    黄小斜学Java

    疯狂的字节X

  • 目前专注于分享Java领域干货,公众号同步更新。原创以及收集整理,把最好的留下。
    包括但不限于JVM、计算机科学、算法、数据库、分布式、Spring全家桶、微服务、高并发、Docker容器、ELK、大数据等相关知识,一起进步,一起成长。
热门推荐
海康摄像头接入 wvp-GB28181-pro平台测试验
[md]### 简介 开箱即用的28181协议视频平台 `https://github.c
[CXX1300] CMake '3.18.1' was not
[md][CXX1300] CMake '3.18.1' was not found in SDK, PATH, or
[若依]微服务springcloud版新建增添加一个
[md]若依框架是一个比较出名的后台管理系统,有多个不同版本。