JAVA NIO

本文深入探讨了Java NIO包中Buffer类的使用,包括缓冲区的属性、操作方法以及如何通过Channel通道将数据源和数据汇与Buffer连接起来。详细解释了ByteBuffer和MappedByteBuffer的创建方式、用途及与文件操作的关系。同时,文章还介绍了缓冲区视图、文件加锁、字符编码转换等高级应用,并通过示例代码演示了实际操作过程。

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

jdk1.4 开始引入了新IO类,NIO包的目的是为了提高IO的效率。

缓冲区Buffer:

缓冲区的优点我就不多介绍了。

拥有3个属性:

(1)容量:一个缓冲区最多容量。

(2)界限:一个缓冲区可读写的范围。

(3)位置:接下来要读写的位置。

界限是用来控制当前读写的范围,如果容量为100,界限为10,则位置只能在0-10之间,即只能读写0-10之间的数据

提供了三个方法改变属性:

(1)clear():把界限移到容量处,把位置设为0.

(2)flip():把界限移到位置处,把位置移到0.

(3)rewind():界限不变,位置设为0.

ByteBuffer:字节缓冲区

创建:ByteBuffer bf = ByteBuffer.allocate(capacity);

MappedByteBuffer:ByteBuffer的子类

能够把文件的部分映射到缓冲区中。
方法:

get();

put();

bb.isRemaining();判断是否还有数据可读

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class TransferDemo{
	public static void main(String args[])throws Exception{
		FileChannel in = new FileInputStream("test.txt").getChannel();
		FileChannel out = new FileOutputStream("out.txt").getChannel();
		ByteBuffer bf = ByteBuffer.allocate(1024);
		while(in.read(bf)!=-1){
			bf.flip();
			out.write(bf);
			bf.clear();
		}
		out.close();
		in.close();
	}
}


疑问:光有Buffer,但是怎么和数据源和数据汇进行连接呢?

Channel通道:把数据源或数据汇和Buffer连接起来。

FileChannel是一个实现好的类,是文件和缓冲区的通道,在FileInputStream、FileOutputStream、RandomAccessFile中的getChannel();获得。

(1)read(ByteBuffer bf);      读取文件数据到ByteBuffer中

(2)write(ByteBuffer bf);    把ByteBuffer写入文件

把String包装到ByteBuffer中:ByteBuffer.wrap(str.getBytes());

利用Charset能够对ByteBuffer进行编码转换。

Charset cs = Charset.forName("UTF-8");

CharBuffer cs.decode(ByteBuffer);把ByteBuffer解码为Unicode编码并返回。

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class FileChannelDemo01{
	public static void main(String args[])throws Exception{
		FileChannel fc = new FileOutputStream("text.txt").getChannel();
		fc.write(ByteBuffer.wrap("你好".getBytes()));
		fc.close();

		fc = new RandomAccessFile("text.txt","rw").getChannel();
		fc.position(fc.size());
		fc.write(ByteBuffer.wrap("朋友".getBytes()));
		fc.close();

		fc = new FileInputStream("text.txt").getChannel();
		ByteBuffer buf = ByteBuffer.allocate(1024);
		fc.read(buf);
		buf.flip();
		Charset cs = Charset.defaultCharset();
		System.out.println(cs.decode(buf));
		
		fc.close();
	}
}


Charset类:字符编码转换类

Charset cs = Charset.defaultCharset();

Charset cs = Charset.forName("UTF-8");

获得字符集

UTF-16BE是Unicode码。

ByteBuffer encode(String);把String按照指定的字符集编码,并返回。

CharBuffer decode(ByteBuffer)按照指定的字符集转换成Unicode码。

import java.io.*;
import java.nio.*;
import java.nio.channels.*;

public class CharsetConvert{
	public static void main(String args[])throws Exception{
		ByteBuffer bb = ByteBuffer.wrap("你好".getBytes("UTF-8"));
		CharBuffer cb = bb.asCharBuffer();
		System.out.println(cb);
		bb = ByteBuffer.wrap("你好".getBytes("UTF-16BE"));
		cb = bb.asCharBuffer();
		System.out.println(cb);
		
	}
}


MappedByteBuffer:映射缓冲区

ByteBuffer的子类,用于因为文件太大不能放入内存的文件,能够映射文件的部分区域。

MappedByteBuffer b = channel.map(FileChannel.MapMode.READ_WRITE,pos,capacity);    pos表示文件开始映射位置,capacity表示要映射的容量。

import java.nio.*;
import java.io.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class MappedByteBufferDemo01{
	public static void main(String args[])throws Exception{
		int capacity = 0x8000000;
		MappedByteBuffer mb = new RandomAccessFile("test.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE,0,capacity);
		mb.put("你好".getBytes("GBK"));
		mb.flip();
		System.out.println(Charset.forName("GBK").decode(mb)); 
	}
}

 

缓冲区视图:

ByteBuffer提供了一些方法可以得到其他的视图,比如asCharBuffer()获得CharBuffer。

(1)CharBuffer cb = bb.asCharBuffer();

(2)IntBuffer ib = bb.asIntBuffer();

ByteBuffer提供了

getInt()用于读取整数缓冲区视图put进去的整数。

getChar()用于读取字符缓冲区视图put进去的字符。

 

import java.nio.*;
public class BufferViewDemo{
	public static void main(String args[])throws Exception{
		ByteBuffer bb = ByteBuffer.allocate(100);
		CharBuffer cb = bb.asCharBuffer();
		cb.put("你好");
		bb.rewind();
		/*while(bb.hasRemaining()){
			System.out.println(bb.getChar()); 
		}*/
		IntBuffer ib = bb.asIntBuffer();
		int[] arr = {1,2,3};
		ib.put(arr);
		System.out.println(ib.get(2));
		ib.flip();
		while(ib.hasRemaining()){
			int i = ib.get();
			System.out.println(i); 
		}

	}
}

文件加锁:

得到锁并加锁:FileLock lock = channel.tryLock();

释放锁:lock.release();

 

 

 

03-15
### Java NIO 教程与文档 Java NIO 是一种基于缓冲区和通道的 I/O 处理方式,相较于传统的 Java IO 更高效且适合处理大规模数据传输。以下是关于 Java NIO 的一些核心概念及其学习资源。 #### 1. **核心组件** Java NIO 主要由以下几个部分组成: - **Buffer**: 数据容器,用于存储不同类型的原始数据[^4]。 - **Channel**: 类似于流的概念,但支持双向读操作。 - **Selector**: 支持多路复用机制,允许单线程管理多个 Channel。 这些组件共同构成了高效的非阻塞 I/O 模型,适用于网络编程和文件操作场景。 #### 2. **官方文档** Oracle 官方文档提供了详尽的 Java NIONIO.2 API 描述以及使用示例。可以通过访问 Oracle 官网并搜索 "Java SE documentation" 来获取最新的官方文档[^3]。 #### 3. **教程推荐** Baeldung 网站上的教程涵盖了 Java NIO 的基本原理及高级应用案例。例如,“Five ways to maximize Java NIO and NIO.2” 提供了五个重要的功能介绍,包括变更通知器(Change Notifiers),这使得监听事件变得更加简单。 #### 4. **实际应用场景** 通过结合实例代码可以更好地理解如何利用 Java NIO 实现高性能的数据传输。例如,在文件入方面有多种实现方法,既可以直接采用标准库中的 `Files` 工具类,也可以借助更底层的 Buffer 和 Channel 结构完成复杂任务[^1]。 ```java import java.nio.file.*; import java.io.IOException; public class FileWriteExample { public static void main(String[] args) throws IOException { Path path = Paths.get("example.txt"); String content = "This is a test."; // 使用 Files.write 方法快速入字符串到文件 Files.write(path, content.getBytes()); } } ``` 上述代码展示了如何利用 `Files.write()` 函数向指定路径下的文件入一段文本内容。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值