Java NIO、NIO.2学习笔记(三)
此时Buffer中的数据被檫除了吗?没有)
我们可以类比思考:
Buffer的这种数据读取机制是一种典型的"基于数据结构的数据操作方式",和操作系统的栈内存操作方式从原理上是一致的
复制代码
code:
复制代码
import java.nio.*;
public class BufferTest
{
public static void main(String[] args)
{
// 创建Buffer
CharBuffer buff = CharBuffer.allocate(8); //①
System.out.println("capacity: " + buff.capacity());
System.out.println("limit: " + buff.limit());
System.out.println("position: " + buff.position());
// 放入元素
buff.put('a');
buff.put('b');
buff.put('c'); //②
System.out.println("加入三个元素后,position = " + buff.position());
// 调用flip()方法
buff.flip(); //③
System.out.println("执行flip()后,limit = " + buff.limit());
System.out.println("position = " + buff.position());
// 取出第一个元素
System.out.println("第一个元素(position=0):" + buff.get()); // ④
System.out.println("取出一个元素后,position = " + buff.position());
// 调用clear方法
buff.clear(); //⑤
System.out.println("执行clear()后,limit = " + buff.limit());
System.out.println("执行clear()后,position = " + buff.position());
System.out.println("执行clear()后,缓冲区内容并没有被清除:" + "第三个元素为:" + buff.get(2)); // ⑥
System.out.println("执行绝对读取后,position = " + buff.position());
}
}
复制代码
0x2: Channel
Channel中最常用的方法是:
复制代码
1. map()
用于将Channel对应的部分、或全部数据映射成Buffer
MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)
1) FileChannel.MapMode: 执行映射时的模式
1.1) PRIVATE: private (copy-on-write,写时复制) mapping
1.2) READ_ONLY: Mode for a read-only mapping
1.3) READ_WRITE: Mode for a read/write mapping
2) position、long size决定哪些数据被映射成Buffer
2. read()
用于从Buffer中读取数据
3. write()
用于向Buffer中写入数据
复制代码
code:
复制代码
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class FileChannelTest
{
public static void main(String[] args)
{
File f = new File("FileChannelTest.java");
try(
// 创建FileInputStream,以该文件输入流创建FileChannel
FileChannel inChannel = new FileInputStream(f).getChannel();
// 以文件输出流创建FileBuffer,用以控制输出
FileChannel outChannel = new FileOutputStream("out.txt").getChannel())
{
// 将FileChannel里的全部数据映射成ByteBuffer
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY , 0 , f.length()); // ①
// 使用GBK的字符集来创建解码器
Charset charset = Charset.forName("GBK");
// 直接将buffer里的数据全部输出
outChannel.write(buffer); // ②
// 再次调用buffer的clear()方法,复原limit、position的位置
buffer.clear();
// 创建解码器(CharsetDecoder)对象
CharsetDecoder decoder = charset.newDecoder();
// 使用解码器将ByteBuffer转换成CharBuffer
CharBuffer charBuffer = decoder.decode(buffer);
// CharBuffer的toString方法可以获取对应的字符串
System.out.println(charBuffer);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
复制代码
有时候,如果遇到Channel对应的文件太大,无法一次性全部Map到内存中、或者使用map()方法一次将所有的文件内容映射到内存中会引起性能下降,也可以使用Channel的Buffer的"分批逐段读取"的方法
复制代码
import java.i