ByteBuffer与FileChannel学习笔记

ByteBuffer与FileChannel学习笔记

ps:今天看了很多博客学习了ByteBuffer和FileChannel,融合了其他大佬们的精华,整理成笔记。
首先我们来说说这两个类是什么:

  • ByteBuffer类是在Java NIO中常常使用的一个缓冲区类,使用它可以进行高效的IO操作。

  • FileChannel就是连接到文件的管道。使用FileChannel,你可以读取文件数据,以及往文件里面写入数据。Java NIO的FileChannel是使用标准Java IO读取文件的一种替代方案

我们来看一个简单的程序:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ByteBufferTest {
    public void test() throws IOException {
//创建缓冲区
        ByteBuffer buff = ByteBuffer.allocate(128);//分配内存空间
//创建管道
        FileChannel fin = null;
        FileChannel fout = null;
        try {
            fin = new FileInputStream("C:/Users/Administrator.000/Desktop/filein.txt").getChannel();
            fout = new FileOutputStream("C:/Users/Administrator.000/Desktop/fileout.txt").getChannel();
//读取文件放入缓冲区中,没有读完就一直循环
            while (fin.read(buff) != -1) {
//这里比较重要,看底下的讲解吧
                buff.flip();
//将缓冲区的文件写到输出流中
                fout.write(buff);
                buff.clear();
            }
        } catch (FileNotFoundException e) {
        } finally {
            try {
//一定要记得关闭流
                if (fin != null) {
                    fin.close();
                }
                if (fout != null) {
                    fout.close();
                }
            } catch (IOException e) {
                throw e;
            }
        }
    }
//底下是测试
    public static void main(String[] args) {
        ByteBufferTest bt = new ByteBufferTest();
        try {
            bt.test();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ByteBuffer:

ByteBuffer对象内部定义了四个索引,分别是mark,position,limit,capacity,其中

  1. mark用于对当前position的标记
  2. position表示当前可读写的指针,如果是向ByteBuffer对象中写入一个字节,那么就会向position所指向的地址写入这个字节,如果是从ByteBuffer读出一个字节,那么就会读出position所指向的地址读出这个字节,读写完成后,position加1
  3. limit是可以读写的边界,当position到达limit时,就表示将ByteBuffer中的内容读完,或者将ByteBuffer写满了。
  4. capacity是这个ByteBuffer的容量,上面的程序中调用ByteBuffer.allocate(128)就表示创建了一个容量为capacity字节的ByteBuffer对象。
    常见重要方法
    flip方法将limit值置为position值,position置0,这样在调用get*()方法从ByteBuffer中取数据时就可以取到ByteBuffer中的有效数据,JDK中flip方法的代码如下:
    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

clear方法给人的感觉就是将数据清空了,但是实际上却不是的,它并没有清空缓冲区中的数据,而至重置了对象中的三个索引值,如果不清空的话,假设此次该ByteBuffer中的数据是满的,下次读取的数据不足以填满缓冲区,那么就会存在上一次已经处理的的数据, 在JDK中,这个方法的代码如下:

public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}

hasRemaining()方法可以判断缓冲区中是否有可用的数据, 在JDK中,这个方法的代码如下:

public final boolean hasRemaining() {
    return position < limit;
}

FileChannel:

打开一个 FileChannel
在你使用FileChannel前,你必须先打开它。你不能直接打开一个FileChannel。你必须通过一个InputStream、OutputStream或者RandomAccessFile来获得一个FileChannel。以下是如何通过一个RandomAccessFile来获得FileChannel的示例:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

从FileChannel中读数据到Buffer
为了从FileChannel读取数据,你需要调用其read()方法。如下:

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);

首先分配一个Buffer,从FileChannel读取的数据将被读入Buffer。
然后调用FileChannel.read()方法。这个方法将数据从FileChannel读入Buffer。read()方法返回的int代表着有多少数据被读入了Buffer。如果返回-1,代表着已经读到文件结尾。
向FileChannel中写数据
要将数据写入FileChannel,你需要调用带有一个Buffer类型参数的FileChannel.write()方法。如下:

String newData =“让我们写一个数据”
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());

buf.flip();

while (buf.hasRemaining()) {
channel.write(buf);
}

注意在while-循环里面调用的FileChannel.write()方法。我们无法保证每次write()方法向Channel写了多少字节。因此我们重复调用write()直至没有数据可写为止。Closing a FileChannel
当时使用完FileChannel后,你必须关闭它。如下:

channel.close();
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值