目录
一、通道概览
1.概念示意图
2.Channel接口继承关系
二、文件通道使用
1.文件通道类图
2.文件通道示例 三、文件通道开启源码
1.通道开启示例
2.RandomAccessFile创建源码
3.文件打开源码
4.开启通道源码
四、ByteBuffer写入通道源码 五、强制刷盘源码
六、通道重置位点源码
七、读取数据到ByteBuffer源码
1.JDK源码跟踪
2.Native源码跟踪
八、通道关闭源码
1.JDK源码追踪
2.Native方法源码跟踪
九、文件截取源码
十、参考资料
十一、系列文章
代码语言:javascript复制
一、通道概览
1.概念示意图
系统I/O即字节的传输,Channel即传输的通道,文件或网络Socket服务即传输的目的地。
2.Channel接口继承关系
实现Channle的接口
小结:由图可以看出直接继承Channel接口的接口由5个分别为:AsynchronousChannel、NetworkChannel、ReadableByteChannel、WritableByteChannel、InterruptibleChannel。其他接口和类都从这5个接口派生。两个字节操作接口ReadableByteChannel、WritableByteChannel,即:通道只能在字节缓冲区上操作。
二、文件通道使用
1.文件通道类图
2.文件通道示例
以示例方式串下文件通道的基本操作,示例内容为:将字符串写入文件,再读出来打印。
代码语言:javascript复制File file =new File("/Users/yongliang/mytest/channletst.tmp");
RandomAccessFile randomAccessFile =new RandomAccessFile(file,"rw");
FileChannel fileChannel = randomAccessFile.getChannel();// @1
ByteBuffer buffer = ByteBuffer.allocate(20);
String str ="It's a good day!";
buffer.put(str.getBytes("UTF-8"));
buffer.flip();
while(buffer.hasRemaining()) {
fileChannel.write(buffer);// @2
}
fileChannel.force(false);// @3
System.out.println("FileChannel current position=" fileChannel.position());
fileChannel.position(0);// @4
ByteBuffer buffer2 = ByteBuffer.allocate(16);
int data = fileChannel.read(buffer2);// @5
System.out.println("length=" data);
System.out.println("content=" new String(buffer2.array()));
fileChannel.close();// @6
@1 开启文件通道
@2 将ByteBuffer数据写入FileChannel
@3 强制刷盘
@4 FileChannel重置到开始位置
@5 从FileChannel中读取数据到ByteBuffer
@6 关闭FileChannel
小结:梳理了FileChannle的继承关系以及通过一个示例说明FileChannle的基本操作。
三、文件通道开启源码
1.通道开启示例
代码语言:javascript复制RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
FileChannel fileChannel = randomAccessFile.getChannel();
2.RandomAccessFile创建源码
代码位置:java.io.RandomAccessFile
代码语言:javascript复制public RandomAccessFile(File file, String mode)
throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
int imode = -1;
if (mode.equals("r"))
imode = O_RDONLY;
else if (mode.startsWith("rw")) {
imode = O_RDWR;
rw = true;
if (mode.length() > 2) {
if (mode.equals("rws"))
imode |= O_SYNC;
else if (mode.equals("rwd"))
imode |= O_DSYNC;
else
imode = -1;
}
} // @1
// ...
fd = new FileDescriptor(); // @2
fd.attach(this);
path = name;
open(name, imode); // @3
}
@1 r只读模式;rw读写模式;rws模式保证数据同步写入磁盘;rwd模式保证数据和元数据同步写入磁盘。
@2 初始化文件描述符,此时初始值为-1
@3 open调用本地方法打开文件
小结:RandomAccessFile通过Native的open方法打开一个文件。
3.文件打开源码
调用链条
代码语言:javascript复制1.open(name,imode);
2.open0(Stringname,intmode)
3.Java_java_io_RandomAccessFile_open0
4.fileOpen
5.handleOpen
代码位置:jdk/src/solaris/native/java/io/io_util_md.c
代码语言:javascript复制Java_java_io_RandomAccessFile_open0(JNIEnv*env,
jobjectthis, jstring path, jint mode)
{
intflags = 0;
if(mode & java_io_RandomAccessFile_O_RDONLY)
flags =O_RDONLY;
elseif (mode & java_io_RandomAccessFile_O_RDWR) {
flags =O_RDWR | O_CREAT;
if(mode & java_io_RandomAccessFile_O_SYNC)
flags|= O_SYNC;
elseif (mode & java_io_RandomAccessFile_O_DSYNC)
flags|= O_DSYNC;
}
fileOpen(env,this, path, raf_fd, flags);
}
代码位置:jdk/src/solaris/native/java/io/io_util_md.c
代码语言:javascript复制fileOpen(JNIEnv *env, jobjectthis, jstring path, jfieldID fid,int flags)
{
WITH_PLATFORM_STRING(env, path, ps) {
FD fd;
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
/* Remove trailing slashes, since the kernel won't */
char *p = (char *)ps strlen(ps) -1;
while ((p > ps) && (*p =='/'))
*p-- ='