Nio-FileChannel与粘包问题

昨天我们说了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();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值