文章参考摘抄自:https://ifeve.com/java-nio-all/
一、java NIO特性:
Channels and Buffers
Channel主要的实现:
- FileChannel 从文件中读写数据
- DatagramChannel 通过UDP读写网络中的数据
- SocketChannel 通过TCP读写网络中的数据
- ServerSocketChannel 监听新进来的TCP连接,对每一个新进来的连接都会创建一个SocketChannel。
Buffer实现:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
MappedByteBuffer,用于表示内存映射文件
标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Non-blocking IO
可以采用多线程从通道读取数据并处理。
Selectors
可以监听多个通道的事件,如连接打开,同时单线程也可监听多个数据通道。要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
还有Pipe和FileLock
基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。
二、文件读写案例:
a、通过使用一个InputStream、OutputStream或RandomAccessFile来获取一个FileChannel实例
b、从FileChannel中读取数据至Buffer中;返回的int值表示了有多少字节被读到了Buffer中。如果返回-1,表示到了文件末尾。
c、用完FileChannel后必须将其关闭。
public static void chanelTest() {
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile("D:\\笔记\\dblink.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip();
while(buf.hasRemaining()){
System.out.print((char) buf.get());
//
channel.write(buf); //文件写入
}
buf.clear();
bytesRead = inChannel.read(buf);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
aFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
三、特殊用法
FileChannel的position方法
在FileChannel的某个特定位置进行数据的读/写操作。也可以通过调用position(long pos)方法设置FileChannel的当前位置。
|
FileChannel的size方法
返回该实例所关联文件的大小。
long
fileSize = channel.size();
FileChannel的truncate方法
截取文件 指定长度并删除其余部分。channel.truncate(
1024
);
FileChannel的force方法
将通道里尚未写入磁盘的数据强制写到磁盘上。
transferFrom()
FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中;position表示从position处开始向目标文件写入数据,count表示最多传输的字节数,如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。在SoketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。因此,SocketChannel可能不会将请求的所有数据(count个字节)全部传输到FileChannel中。
如:
RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
transferTo()
将数据从FileChannel传输到其他的channel中。
RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);
附中文乱码处理:
文件读取到后,写入时做编码处理:
-
Charset charset = Charset.forName("GBK");
-
CharsetDecoder charDecoder = charset.newDecoder();