Nio-FileChannel与粘包问题

来源:互联网 发布:生成淘宝无线链接地址 编辑:程序博客网 时间:2024/05/29 16:27

昨天我们说了Nio中的套接字通道SocketChannel,及相关的缓冲区类ByteBuffer。
今天我们来说一下文件的通道类FileChannel。


粘包问题

在缓冲区类ByteBuffer中存入数据的时候,由于都是直接写入的。前一个数据包的尾,紧挨着后一个数据的头,没法做到区分。
如果是传输文件,那么只要保证连贯性和完整性即可。不需要分包。
如果是结构性数据的话,就需要分包了,那么怎么办呢?

  1. 用标识符来做分割,存在的隐患是分隔符可能是正文内容
  2. 双方规定好发送的大小,局限性是不灵活,应用范围比较狭窄。
  3. 采用协议头的思想来做。(推荐,类似HTTP请求头)

FileChannel

用于读取、写入、映射和操作文件的通道。
文件通道在其文件中有一个当前 position,可对其进行查询和修改。该文件本身包含一个可读写的长度可变的字节序列,并且可以查询该文件的当前大小。
写入的字节超出文件的当前大小时,则增加文件的大小;截取 该文件时,则减小文件的大小。文件可能还有某个相关联的元数据,如访问权限、内容类型和最后的修改时间;此类未定义访问元数据的方法。

1-. FileChannel需要通过FileOutputStream或FileInputStream来获取。

需要注意的是:
通过FileOutputStream得到文件通道只能执行写操作,如果在该通道上执行读操作,抛出NonReadableChannelException。
同理通过FileInputStream得到文件通道只能执行读操作。

FileOutputStream out = new FileOutputStream(new File("1.txt"));//获取文件通道FileChannel fc = out.getChannel();

2-. FileChannel也有一个position的属性,来标识当前指针的位置。
position(newPosition):设置position的值
position():获取当前position的值

//例子:在该文件的第四个字节处写入"1234"字符串。FileOutputStream out = new FileOutputStream(new File("1.txt"));FileChannel fc = out.getChannel();fc.position(4);ByteBuffer buf = ByteBuffer.wrap("1234".getBytes());fc.write(buf);//关闭通道和输出流fc.close();out.close();

FileChannel在执行read()/write()方法时,position会自动增加。

3-. RandomAccessFile 类。通过该类获得的FileChannel,既可以读也可以写。但是要注意,读和写不可以是同一个ByteBuffer

/* * r:表示只读的 * rw:即可以读,也可以写 * position的默认值为0*/RandomAccessFile raf = new RandomAccessFile(new File("1.txt"), "rw");FileChannel fc = raf.getChannel();ByteBuffer rdbuf = ByteBuffer.allocate(8);fc.position(4);//读入fc.read(rdbuf);System.out.println(new String(rdbuf.array()));      System.out.println(fc.position());fc.write(buf);ByteBuffer wtbuf = ByteBuffer.wrap("abcd".getBytes());//写入fc.write(wtbuf);fc.close();raf.close();
原创粉丝点击