Java NIO、NIO.2学习笔记(四)
o.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class ReadFile
{
public static void main(String[] args) throws IOException
{
try(
// 创建文件输入流
FileInputStream fis = new FileInputStream("ReadFile.java");
// 创建一个FileChannel
FileChannel fcin = fis.getChannel())
{
// 定义一个ByteBuffer对象,用于重复取水
ByteBuffer bbuff = ByteBuffer.allocate(64);
// 将FileChannel中数据放入ByteBuffer中
while( fcin.read(bbuff) != -1 )
{
// 锁定Buffer的空白区
bbuff.flip();
// 创建Charset对象
Charset charset = Charset.forName("GBK");
// 创建解码器(CharsetDecoder)对象
CharsetDecoder decoder = charset.newDecoder();
// 将ByteBuffer的内容转码
CharBuffer cbuff = decoder.decode(bbuff);
System.out.print(cbuff);
// 将Buffer初始化,为下一次读取数据做准备
bbuff.clear();
}
}
}
}
复制代码
可以看到,代码每次读取数据后调用flip()方法将没有数据的区域"封印"起来,避免程序从Buffer中读取null值
0x3: Charset
复制代码
import java.nio.*;
import java.nio.charset.*;
public class CharsetTransform
{
public static void main(String[] args) throws Exception
{
// 创建简体中文对应的Charset
Charset cn = Charset.forName("GBK");
// 获取cn对象对应的编码器和解码器
CharsetEncoder cnEncoder = cn.newEncoder();
CharsetDecoder cnDecoder = cn.newDecoder();
// 创建一个CharBuffer对象
CharBuffer cbuff = CharBuffer.allocate(8);
cbuff.put('孙');
cbuff.put('悟');
cbuff.put('空');
cbuff.flip();
// 将CharBuffer中的字符序列转换成字节序列
ByteBuffer bbuff = cnEncoder.encode(cbuff);
// 循环访问ByteBuffer中的每个字节
for (int i = 0; i < bbuff.capacity() ; i++)
{
System.out.print(bbuff.get(i) + " ");
}
// 将ByteBuffer的数据解码成字符序列
System.out.println("\n" + cnDecoder.decode(bbuff));
}
}
复制代码
实际上,Charset类也提供了如下3个方法,无须创建相应的解码、编码器就可以直接进行编码转换,是否创建编码、解码器的差别我觉得和在进行和正则有关的编程的时候是否创建正则表达式的编译后对象是一个原理,复用性、性能的原因
1. CharBuffer decode(ByteBuffer bb)
将ByteBuffer中的字节序列转换成字符序列的快捷方法
2. ByteBuffer encode(CharBuffer cb)
将ByteBuffer中的字节序列转换成字符序列的快捷方法
3. ByteBuffer encode(String str)
将CharBuffer中的字符序列转换成字节序列的快捷方法
0x4: FileLock
文件锁在操作系统中是很平常的事情,如果多个程序需要并发修改同一个文件时,程序之间需要通过锁机制来进行并发控制。从JDK 1.4的NIO开始,java开始提供文件锁的支持。在NIO中,FileChannel调用lock()、tryLock()方法返回的FileLock可以支持文件锁功能,这两种锁的特性如下
复制代码
1. lock()
FileLock lock(long position, long size, boolean shared)
1) position、size表明对文件的一部分进行加锁,这是一种细粒度的锁机制
2) 参数shared
2.1) true: 表明是一个"共享锁",它将允许多个进行来"读取(注意: 只是读取)",但阻止其他进程获得对该文件的排它锁
2.2) false(默认值): 表明是一个"排它锁",它将锁住对该文件的读写
程序可以通过FileLock的isShared来判断它获得的锁是否为共享锁
当调用lock()试图锁定某个文件时,如果无法获得文件锁,该方法将一直阻塞
2. tryLock()
tryLock()是"尝试"锁定文件,它将立即返回而不是阻塞,如果获得了文件锁,该方法返回文件锁,否则返回null
复制代码
code:
复制代码
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class FileLockTest
{
public static void main(String[] args) throws Exception
{
try(
// 使用FileOutputStream获取FileChannel
FileChannel channel = new FileOutputStream("a.txt").getCha