NIO整理

本文通过具体示例介绍了Java NIO中的Buffer与Channel的基本使用方法,包括如何利用Buffer进行数据的存取、翻转及清除等操作,同时展示了如何通过Channel实现文件间的高效数据传输,并解析了读取文件数据过程中可能出现的编码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


buffer的例子

@Test
	public void test()
	{
		CharBuffer buffer = CharBuffer.allocate(8);
		System.out.println("capacity:"+buffer.capacity());//输出8
		System.out.println("limit:"+buffer.limit());//输出8
		System.out.println("position:"+buffer.position());//输出0
		buffer.put('a');
		buffer.put('b');
		buffer.put('c');
		System.out.println("=====加入三个元素后======");
		System.out.println("capacity:"+buffer.capacity());//输出8
		System.out.println("limit:"+buffer.limit());//输出8
		System.out.println("position:"+buffer.position());//输出3
		//在进行读操作前调用 flip()方法 limit移动到position位置 把 position指针移动到0位置
		buffer.flip();
		System.out.println("=====调用flip方法后======");
		System.out.println("position:"+buffer.position());//输出0
		System.out.println("limit:"+buffer.limit());//输出3  
		//buffer.get()获取当前position指针的值  position+1
		System.out.println("=====调用buffer.get()方法======");
		System.out.println("输出:"+buffer.get());//输出a  
		System.out.println("输出:"+buffer.get());//输出b 
		System.out.println("当前position:"+buffer.position());//输出2
		//buffer.clear() clear方法不是清空数据而是把position指针置0 limit置capacity 为下一次输入数据做准备
		System.out.println("=====调用buffer.clear()方法======");
		System.out.println("limit:"+buffer.limit());//输出8
		System.out.println("position:"+buffer.position());//输出0
		//get(index)按索引取值验证clear()是否删除数据
		System.out.println("按索引取数据:"+buffer.get(2));//输出c 表明没有删除数据
	}
	

输出

capacity:8
limit:8
position:0
=====加入三个元素后======
capacity:8
limit:8
position:3
=====调用flip方法后======
position:0
limit:3
=====调用buffer.get()方法======
输出:a
输出:b
当前position:2
=====调用buffer.clear()方法======
limit:3
position:2
按索引取数据:c

Channel的例子

从test.txt文件中读取内容输出到a.txt并将内容输出到控制台

@Test
	public void test2()
	{
		File f = new File("src//NIO//test.txt");
	
		try (
				
				FileChannel inChannel = new FileInputStream(f).getChannel();
				FileChannel outChannel = new FileOutputStream("src//NIO//a.txt").getChannel();	
		    )
		
			{
				//将FileChannel中的数据全部映射成ByteBuffer
				MappedByteBuffer buffer=inChannel.map(FileChannel.MapMode.READ_ONLY,0,f.length());
			
				//在"src//NIO//a.txt"中写入数据
				outChannel.write(buffer);//写入完成此时position==limit==capacity==f.length
				System.out.println("文件长度:"+f.length());
				System.out.println("capacity:"+buffer.capacity());
				System.out.println("limit:"+buffer.limit());
				System.out.println("position:"+buffer.position());
				//调用clear()不删除数据  置position=0
				buffer.clear();
				Charset charset = Charset.forName("GBK");//创建解码器
				//创建解码器哦
				CharsetDecoder decoder = charset.newDecoder();
				//使用解码器将ByteBuffer转换成CharBuffer 
				CharBuffer charBuffer = decoder.decode(buffer);
				System.out.println("====输出测试文件内容=====");
				System.out.println(charBuffer);
			} 
			catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			catch (IOException e1) 
			{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			}
	}

测试文件内容为 :测试123asc

控制台输出:

文件长度:10
capacity:10
limit:10
position:10
====输出测试文件内容=====
测试123asc

从文件中读取数据

文件内容:测试123asc是的v是的是的分v三大城市的胜多负少的v大幅上厕所反射是是

//从文件中读取数据
	@Test
	public void test4()
	{
		File f = new File("src//NIO//test.txt");
		try {
			FileChannel inChannel = new FileInputStream(f).getChannel();
			ByteBuffer buffer = ByteBuffer.allocate(50);
			while(inChannel.read(buffer)!=-1)
			{
				//读入完毕将limit置为position 将position置为0准备读出数据
				buffer.flip();
				Charset charset = Charset.forName("GBK");//创建解码器
				//创建解码器哦
				CharsetDecoder decoder = charset.newDecoder();
				//使用解码器将ByteBuffer转换成CharBuffer 
				CharBuffer charbuffer = decoder.decode(buffer);
				
				System.out.println(charbuffer);
				//读出完毕将position置0 limit值为capacity准备再次读入数据
				buffer.clear();
			}
		
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

控制台输出:


报错:当输入字节序列对于给定 charset 来说是不合法的,或者输入字符序列不是合法的 16 位 Unicode 序列时,抛出此经过检查的异常。说白了,会出现java.nio.charset.MalformedInputException异常,原因是“半个中文问题”。

首先我们删掉文件中的所有英文字符 GBK编码为2个字节我们将buffer容量改为2 

控制台输出

测
试
是
的
是
的
是
的
分
三
大
城
市
的
胜
多
负
少
的
大
幅
上
厕
所
反
射
是
是
似
懂
非
懂
是
闪
电
风
暴
的
分
水
电
费
水
电
费
是
多
少
的
曾
多
次
到
市
场
上
的
出
生
地

符合预期每次读2个字节也就是一个字符

接着把容量改为16也就是一次输出8个字符

ByteBuffer buffer = ByteBuffer.allocate(16);

控制台输出

测试是的是的是的
分三大城市的胜多
负少的大幅上厕所
反射是是似懂非懂
是闪电风暴的分水
电费水电费是多少
的曾多次到市场上
的出生地

符合预期

参考资料:点击打开链接 疯狂Java讲义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值