- 浏览: 979863 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
Reference定义(PhantomReference,Cleaner):http://donald-draper.iteye.com/blog/2371661
FileChanne定义:http://donald-draper.iteye.com/blog/2374149
文件读写方式简单综述:http://donald-draper.iteye.com/blog/2374237
文件读写方式简单综述后续(文件,流构造):http://donald-draper.iteye.com/blog/2374294
文件通道创建方式综述:http://donald-draper.iteye.com/blog/2374537
引言:
获取区文件的通道一共有四种,第一种从FileOutputStream获取写模式文件通道,第二种从FileInputStream获取读模式文件通道,第三种从RandomAccessFile获取读写模式文件通道,第四种调用FileChannelImpl#open方法,这个过程首先从参数文件Path(WindowsPath)获取文件系统的提供者,实际为WindowsFileSystemProvider,委托给WindowsFileSystemProvider创建文件通道,WindowsFileSystemProvider根据WindowsPath和,文件属性WindowsSecurityDescriptor(FileAttribute[]),和打开选项集,将实际创建通道任务交给WindowsChannelFactory,WindowsChannelFactory首先将打开选项装换为内部的通道配置标志Flags(读写模式(read,writer),同步方式(sync,dsync),append等),然后根据Flags,和Path信息等信息创建文件,创建文件实际由WindowsNativeDispatcher完成。WindowsNativeDispatcher首先从线程本地缓存获取NativeBuffer,将Path信息放在NativeBuffer中,然后创建文件,创建后,将NativeBuffer释放,即放入线程本地缓存,以便重用。具体选择哪种方式,根据需要选择。
从今天开始,文件通道的具体实现FileChanneImpl
来看构造
从上面可以看出文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器
FileDispatcherImpl。
从上面可以看出文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成完成,这一点和SocketChannel通道思路相似。
transferTo方法有3点要关注
1
2.
再来看将通道数据映射到内存和释放映射内存空间
3.
从上面可以看出文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
再看文件通道传输方法transferFrom
这个方法我们需要关注2点
1.
再来看
//IOUtil
//FileDispatcherImpl
2.其他可读通道
从上面可以看出文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer
写入当前通道。
再来看force操作:
//FileDispatcherImpl
再来看truncate方法
//FileDispatcherImpl
再来看其他函数
//FileDispatcherImpl
总结:
文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器,FileDispatcherImpl。
文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成,这一点和SocketChannel通道读写思路基本相同。
文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer
写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer写入当前通道。
文件通道解析二(文件锁,关闭通道):http://donald-draper.iteye.com/blog/2374736
附:
//FileDispatcher
FileChanne定义:http://donald-draper.iteye.com/blog/2374149
文件读写方式简单综述:http://donald-draper.iteye.com/blog/2374237
文件读写方式简单综述后续(文件,流构造):http://donald-draper.iteye.com/blog/2374294
文件通道创建方式综述:http://donald-draper.iteye.com/blog/2374537
引言:
获取区文件的通道一共有四种,第一种从FileOutputStream获取写模式文件通道,第二种从FileInputStream获取读模式文件通道,第三种从RandomAccessFile获取读写模式文件通道,第四种调用FileChannelImpl#open方法,这个过程首先从参数文件Path(WindowsPath)获取文件系统的提供者,实际为WindowsFileSystemProvider,委托给WindowsFileSystemProvider创建文件通道,WindowsFileSystemProvider根据WindowsPath和,文件属性WindowsSecurityDescriptor(FileAttribute[]),和打开选项集,将实际创建通道任务交给WindowsChannelFactory,WindowsChannelFactory首先将打开选项装换为内部的通道配置标志Flags(读写模式(read,writer),同步方式(sync,dsync),append等),然后根据Flags,和Path信息等信息创建文件,创建文件实际由WindowsNativeDispatcher完成。WindowsNativeDispatcher首先从线程本地缓存获取NativeBuffer,将Path信息放在NativeBuffer中,然后创建文件,创建后,将NativeBuffer释放,即放入线程本地缓存,以便重用。具体选择哪种方式,根据需要选择。
从今天开始,文件通道的具体实现FileChanneImpl
public class FileChannelImpl extends FileChannel { private static final long allocationGranularity = initIDs(); private final FileDispatcher nd;//文件分发器 private final FileDescriptor fd;//文件描述 private final boolean writable;//通道是否可写 private final boolean readable;//通道是否可读 private final boolean append;//通道写是否为追加模式 private final Object parent;//创建通道的对象 //下面这些属性,暂时不能确定是具体什么意思,只能先从字面上去理解, //这里我们先放在这里,后面用到在讲 private final NativeThreadSet threads = new NativeThreadSet(2); private final Object positionLock = new Object();//文件读写是位置锁 private static volatile boolean transferSupported = true;//是否支持通道传输 private static volatile boolean pipeSupported = true;//是否支持管道 private static volatile boolean fileSupported = true;//是否支持文件 private static final long MAPPED_TRANSFER_SIZE = 8388608L;/ private static final int TRANSFER_SIZE = 8192; private static final int MAP_RO = 0; private static final int MAP_RW = 1; private static final int MAP_PV = 2; private volatile FileLockTable fileLockTable;//存放文件锁的Table private static boolean isSharedFileLockTable;//文件锁table是否为共享 private static volatile boolean propertyChecked; static final boolean $assertionsDisabled = !sun/nio/ch/FileChannelImpl.desiredAssertionStatus(); static { //加载nio,net资源库 Util.load(); } private static native long initIDs(); }
来看构造
public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, Object obj) { return new FileChannelImpl(filedescriptor, flag, flag1, false, obj); } public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj) { return new FileChannelImpl(filedescriptor, flag, flag1, flag2, obj); } //创建FileChannelImpl private FileChannelImpl(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj) { fd = filedescriptor; readable = flag; writable = flag1; append = flag2; parent = obj; nd = new FileDispatcherImpl(flag2); }
从上面可以看出文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器
FileDispatcherImpl。
public int write(ByteBuffer bytebuffer) throws IOException { ensureOpen();//确保通道打开 if(!writable)//如果通道不可写,则抛出不可写异常 throw new NonWritableChannelException(); Object obj = positionLock;//获取position锁 JVM INSTR monitorenter ;//进入同步 int i; int j; i = 0; j = -1; int k; begin(); ... j = threads.add(); //看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲 //只不过nd为FileDispatcherImpl do i = IOUtil.write(fd, bytebuffer, -1L, nd, positionLock); while(i == -3 && isOpen()); ... } public long write(ByteBuffer abytebuffer[], int i, int j) throws IOException { if(i < 0 || j < 0 || i > abytebuffer.length - j) throw new IndexOutOfBoundsException(); ensureOpen(); if(!writable) throw new NonWritableChannelException(); Object obj = positionLock; JVM INSTR monitorenter ; ... //看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲 //只不过nd为FileDispatcherImpl do l = IOUtil.write(fd, abytebuffer, i, j, nd); while(l == -3L && isOpen()); ... } public int read(ByteBuffer bytebuffer) throws IOException { ensureOpen(); if(!readable) throw new NonReadableChannelException(); Object obj = positionLock; JVM INSTR monitorenter ; int i; int j; i = 0; j = -1; int k; ... //看到这里是不是很熟悉,在socketChannel和DatagramChannel都有讲过,这里不再讲 //只不过nd为FileDispatcherImpl do i = IOUtil.read(fd, bytebuffer, -1L, nd, positionLock); while(i == -3 && isOpen()); ... } public long read(ByteBuffer abytebuffer[], int i, int j) throws IOException { if(i < 0 || j < 0 || i > abytebuffer.length - j) throw new IndexOutOfBoundsException(); ensureOpen(); if(!readable) throw new NonReadableChannelException(); Object obj = positionLock; JVM INSTR monitorenter ; ... do l = IOUtil.read(fd, abytebuffer, i, j, nd); while(l == -3L && isOpen()); ... }
从上面可以看出文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成完成,这一点和SocketChannel通道思路相似。
public long transferTo(long l, long l1, WritableByteChannel writablebytechannel) throws IOException { ensureOpen();//确保当前通道打开 if(!writablebytechannel.isOpen())//如果目的通道,不可写则抛出ClosedChannelException throw new ClosedChannelException(); if(!readable)//如果当前通道不可读,则抛出NonReadableChannelException throw new NonReadableChannelException(); //如果目的通道为FileChannelImpl,且不可写,则抛出NonWritableChannelException if((writablebytechannel instanceof FileChannelImpl) && !((FileChannelImpl)writablebytechannel).writable) throw new NonWritableChannelException(); if(l < 0L || l1 < 0L)//检查position和count参数 throw new IllegalArgumentException(); //获取当前文件通道size long l2 = size(); if(l > l2)//如果position大于当前文件size,返回0 return 0L; int i = (int)Math.min(l1, 2147483647L);//获取需要读取字节数,为count参数和2^31-1当中的最小的一个 if(l2 - l < (long)i) i = (int)(l2 - l);//需要读取的字节数 long l3; if((l3 = transferToDirectly(l, i, writablebytechannel)) >= 0L) return l3; if((l3 = transferToTrustedChannel(l, i, writablebytechannel)) >= 0L) return l3; else return transferToArbitraryChannel(l, i, writablebytechannel); }
transferTo方法有3点要关注
1
if((l3 = transferToDirectly(l, i, writablebytechannel)) >= 0L) return l3;
private long transferToDirectly(long l, int i, WritableByteChannel writablebytechannel) throws IOException { int j; int k; long l1; int i1; if(!transferSupported)//不支持通道传输, return -4L; FileDescriptor filedescriptor = null; //这一段的目的就是获取目的通道文件描述符 if(writablebytechannel instanceof FileChannelImpl) { if(!fileSupported)//如果通道为文件通道,但不支持文件 return -6L; filedescriptor = ((FileChannelImpl)writablebytechannel).fd; } else if(writablebytechannel instanceof SelChImpl) { //如果目的通道为SinkChannelImpl,且不支持管道 if((writablebytechannel instanceof SinkChannelImpl) && !pipeSupported) return -6L; filedescriptor = ((SelChImpl)writablebytechannel).getFD(); } if(filedescriptor == null) return -4L; j = IOUtil.fdVal(fd);//获取当前文件通道文件描述符的值 k = IOUtil.fdVal(filedescriptor);//获取目的通道文件描述符的值 if(j == k)//当前通道与目的通道相同 return -4L; ... do l1 = transferTo0(j, l, i, k); while(l1 == -3L && isOpen()); ... } private native long transferTo0(int i, long l, long l1, int j);
2.
if((l3 = transferToTrustedChannel(l, i, writablebytechannel)) >= 0L) return l3;
private long transferToTrustedChannel(long l, long l1, WritableByteChannel writablebytechannel) throws IOException { boolean flag; long l2; //判断目的通道是否为可选择通道,及socketChannel或DatagramChannel,Pipe(sink,source) flag = writablebytechannel instanceof SelChImpl; //如果目的通道不是文件通道也不是可选择通道,则返回 if(!(writablebytechannel instanceof FileChannelImpl) && !flag) return -4L; l2 = l1; _L2: long l3; if(l2 <= 0L) break; /* Loop/switch isn't completed */ l3 = Math.min(l2, 8388608L);//获取读取的size,为count和2^23中间小的一个 //将当前文件通达映射到内存中 MappedByteBuffer mappedbytebuffer = map(java.nio.channels.FileChannel.MapMode.READ_ONLY, l, l3); int i; //直接调用目的通道的write方法将映射文件内存写到通道中。 i = writablebytechannel.write(mappedbytebuffer); if(!$assertionsDisabled && i < 0) throw new AssertionError(); l2 -= i; if(flag) { //如果目的通道非文件通道,则释放文件通道映射内存空间 unmap(mappedbytebuffer); break; /* Loop/switch isn't completed */ } ... }
再来看将通道数据映射到内存和释放映射内存空间
//将通道数据映射到内存 public MappedByteBuffer map(java.nio.channels.FileChannel.MapMode mapmode, long l, long l1) throws IOException { ... mappedbytebuffer = Util.newMappedByteBufferR(0, 0L, j, null); ... } //释放映射内存空间 private static void unmap(MappedByteBuffer mappedbytebuffer) { Cleaner cleaner = ((DirectBuffer)mappedbytebuffer).cleaner(); if(cleaner != null) cleaner.clean(); }
3.
else return transferToArbitraryChannel(l, i, writablebytechannel);
private long transferToArbitraryChannel(long l, int i, WritableByteChannel writablebytechannel) throws IOException { ByteBuffer bytebuffer; long l1; long l2; int j = Math.min(i, 8192); //从线程缓存获取临时DirectByteBuffer bytebuffer = Util.getTemporaryDirectBuffer(j); l1 = 0L; l2 = l; long l3; Util.erase(bytebuffer); do { if(l1 >= (long)i) break; bytebuffer.limit(Math.min((int)((long)i - l1), 8192)); int k = read(bytebuffer, l2); if(k <= 0) break; bytebuffer.flip(); //调用目的通道的写操作,直接写临时DirectByteBuffer int i1 = writablebytechannel.write(bytebuffer); l1 += i1; if(i1 != k) break; l2 += i1; bytebuffer.clear(); } while(true); l3 = l1; Util.releaseTemporaryDirectBuffer(bytebuffer); return l3; ... }
从上面可以看出文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
再看文件通道传输方法transferFrom
public long transferFrom(ReadableByteChannel readablebytechannel, long l, long l1) throws IOException { ensureOpen();//确保当前通道打开 if(!readablebytechannel.isOpen())//确保源通道打开 throw new ClosedChannelException(); if(!writable)//如果当前通道不可写 throw new NonWritableChannelException(); if(l < 0L || l1 < 0L)//检查postion和count参数 throw new IllegalArgumentException(); if(l > size())//位置大于当前文件size,则直接返回 return 0L; //如果源通道为文件通道 if(readablebytechannel instanceof FileChannelImpl) return transferFromFileChannel((FileChannelImpl)readablebytechannel, l, l1); //其他可读通道 else return transferFromArbitraryChannel(readablebytechannel, l, l1); }
这个方法我们需要关注2点
1.
//如果源通道为文件通道 if(readablebytechannel instanceof FileChannelImpl) return transferFromFileChannel((FileChannelImpl)readablebytechannel, l, l1);
private long transferFromFileChannel(FileChannelImpl filechannelimpl, long l, long l1) throws IOException { if(!filechannelimpl.readable) throw new NonReadableChannelException(); Object obj = filechannelimpl.positionLock; JVM INSTR monitorenter ; long l2; long l3; long l4; long l5; l2 = filechannelimpl.position(); l3 = Math.min(l1, filechannelimpl.size() - l2); l4 = l3; l5 = l2; _L2: MappedByteBuffer mappedbytebuffer; if(l4 <= 0L) break; /* Loop/switch isn't completed */ long l6 = Math.min(l4, 8388608L); //将源通道数据映射到内存 mappedbytebuffer = filechannelimpl.map(java.nio.channels.FileChannel.MapMode.READ_ONLY, l5, l6); //委托writer方法 long l8 = write(mappedbytebuffer, l); if(!$assertionsDisabled && l8 <= 0L) throw new AssertionError(); l5 += l8; l += l8; l4 -= l8; unmap(mappedbytebuffer); if(true) goto _L2; else goto _L1 IOException ioexception; ioexception; if(l4 == l3) throw ioexception; //读完,则释放通道映射内存 unmap(mappedbytebuffer); goto _L1 Exception exception; exception; unmap(mappedbytebuffer); throw exception; _L1: long l7; l7 = l3 - l4; //未读完移动源通道的position filechannelimpl.position(l2 + l7); return l7; Exception exception1; exception1; throw exception1; }
再来看
//委托writer方法 long l8 = write(mappedbytebuffer, l);
public int write(ByteBuffer bytebuffer, long l) throws IOException { ... //这段代码又来了,不过此处的nd,为FileDispatcherImpl,与SocketDispatcher没有太多的区别 只不过多了几个turncate和force等方法而已 do i = IOUtil.write(fd, bytebuffer, l, nd, positionLock); while(i == -3 && isOpen()); ... }
//IOUtil
static int write(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj) throws IOException { ... int i1 = writeFromNativeBuffer(filedescriptor, bytebuffer1, l, nativedispatcher, obj); ... } private static int writeFromNativeBuffer(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj) throws IOException { ... if(l != -1L) i1 = nativedispatcher.pwrite(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k, l, obj); else i1 = nativedispatcher.write(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k); if(i1 > 0) bytebuffer.position(i + i1); return i1; }
//FileDispatcherImpl
class FileDispatcherImpl extends FileDispatcher { ... //这一部分,没有什么好说的,看看就行 int write(FileDescriptor filedescriptor, long l, int i) throws IOException { return write0(filedescriptor, l, i, append); } static native int write0(FileDescriptor filedescriptor, long l, int i, boolean flag) throws IOException; int pwrite(FileDescriptor filedescriptor, long l, int i, long l1, Object obj) throws IOException { Object obj1 = obj; JVM INSTR monitorenter ; return pwrite0(filedescriptor, l, i, l1); Exception exception; exception; throw exception; } static native int pwrite0(FileDescriptor filedescriptor, long l, int i, long l1) throws IOException; ... }
2.其他可读通道
else return transferFromArbitraryChannel(readablebytechannel, l, l1);
private long transferFromArbitraryChannel(ReadableByteChannel readablebytechannel, long l, long l1) throws IOException { ByteBuffer bytebuffer; long l2; long l3; int i = (int)Math.min(l1, 8192L); bytebuffer = Util.getTemporaryDirectBuffer(i); l2 = 0L; l3 = l; long l4; Util.erase(bytebuffer); do { if(l2 >= l1) break; bytebuffer.limit((int)Math.min(l1 - l2, 8192L)); //从源通道读取数据到临时DirectByteBuffer int j = readablebytechannel.read(bytebuffer); if(j <= 0) break; bytebuffer.flip(); //委托write,写DirectByteBuffer,即由IOUtil协助FileDispatcherImpl完成 int k = write(bytebuffer, l3); l2 += k; if(k != j) break; l3 += k; bytebuffer.clear(); } while(true); l4 = l2; Util.releaseTemporaryDirectBuffer(bytebuffer); ... }
从上面可以看出文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer
写入当前通道。
再来看force操作:
public void force(boolean flag) throws IOException { ... do i = nd.force(fd, flag); while(i == -3 && isOpen()); ... }
//FileDispatcherImpl
int force(FileDescriptor filedescriptor, boolean flag) throws IOException { return force0(filedescriptor, flag); } static native int force0(FileDescriptor filedescriptor, boolean flag) throws IOException;
再来看truncate方法
public FileChannel truncate(long l) throws IOException { ... do i = nd.truncate(fd, l); while(i == -3 && isOpen()); ... }
//FileDispatcherImpl
int truncate(FileDescriptor filedescriptor, long l) throws IOException { return truncate0(filedescriptor, l); } static native int truncate0(FileDescriptor filedescriptor, long l) throws IOException;
再来看其他函数
//返回通道当前位置 public long position() throws IOException { ... //append模式,则为文件尾,否则为文件头 do l = append ? nd.size(fd) : position0(fd, -1L); while(l == -3L && isOpen()); ... } //定位postion到位置l public FileChannel position(long l) throws IOException { ... do l1 = position0(fd, l); while(l1 == -3L && isOpen()); ... }
private native long position0(FileDescriptor filedescriptor, long l);
//获取通道当前size public long size() throws IOException { ... do l = nd.size(fd); while(l == -3L && isOpen()); ... }
//FileDispatcherImpl
long size(FileDescriptor filedescriptor) throws IOException { return size0(filedescriptor); } static native long size0(FileDescriptor filedescriptor) throws IOException;
总结:
文件通道的构造,主要是初始化通道读写模式,追加模式append及文件分发器,FileDispatcherImpl。
文件通道的读写操作的实际操作都是由IOUtil协助FileDispatcherImpl完成,这一点和SocketChannel通道读写思路基本相同。
文件通道传输方法transferTo,首先确保当前文件通道是否打开,是否可读,然后检查目的通道是否关闭,是否可写;然后先调用文件通道本地方法传输通道的数据到目的通道,如果失败,则将文件通道数据,映射到内存MappedByteBuffer,然后调用目的通道的写操作(MappedByteBuffer),如果再失败,则将通道数据,写到DirectByteBuffer中,然后在调用目的通道的写操作(DirectByteBuffer)。
文件通道传输方法transferFrom,确保当前通道可写,打开,源通道可读打开,如果源通道为文件通道,将源通道数据映射的内存MappedByteBuffer,然后由IOUtil协助FileDispatcherImpl,将MappedByteBuffer
写入当前通道,如果源通道非文件通道,则先调用源通道的读操作,从源通道读取数据,写到临时DirectByteBuffer,委托write,写DirectByteBuffer到当前通道,即由IOUtil协助FileDispatcherImpl,将DirectByteBuffer写入当前通道。
文件通道解析二(文件锁,关闭通道):http://donald-draper.iteye.com/blog/2374736
附:
//FileDispatcher
abstract class FileDispatcher extends NativeDispatcher { FileDispatcher() { } abstract int force(FileDescriptor filedescriptor, boolean flag) throws IOException; abstract int truncate(FileDescriptor filedescriptor, long l) throws IOException; abstract long size(FileDescriptor filedescriptor) throws IOException; abstract int lock(FileDescriptor filedescriptor, boolean flag, long l, long l1, boolean flag1) throws IOException; abstract void release(FileDescriptor filedescriptor, long l, long l1) throws IOException; abstract FileDescriptor duplicateForMapping(FileDescriptor filedescriptor) throws IOException; public static final int NO_LOCK = -1; public static final int LOCKED = 0; public static final int RET_EX_LOCK = 1; public static final int INTERRUPTED = 2; }
发表评论
-
文件通道解析二(文件锁,关闭通道)
2017-05-16 23:17 1063文件通道解析一(读写操作,通道数据传输等):http://do ... -
文件通道创建方式综述
2017-05-15 17:39 1065Reference定义(PhantomReference,Cl ... -
文件读写方式简单综述后续(文件,流构造)
2017-05-14 23:04 1479Java Socket通信实例:http://donald-d ... -
文件读写方式简单综述
2017-05-14 11:13 1135Java Socket通信实例:http://donald-d ... -
FileChanne定义
2017-05-12 23:28 936文件读写方式简单综述:http://donald-draper ... -
SeekableByteChannel接口定义
2017-05-11 08:43 1234ByteChannel,分散聚集通道接口的定义(SocketC ... -
FileChannel示例
2017-05-11 08:37 991前面我们看过socket通道,datagram通道,以管道Pi ... -
PipeImpl解析
2017-05-11 08:41 932ServerSocketChannel定义:http://do ... -
Pipe定义
2017-05-10 09:07 903Channel接口定义:http://donald-drape ... -
NIO-Pipe示例
2017-05-10 08:47 904PipeImpl解析:http://donald-draper ... -
DatagramChannelImpl 解析四(地址绑定,关闭通道等)
2017-05-10 08:27 776DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析三(多播)
2017-05-10 08:20 1892DatagramChannelImpl 解析一(初始化):ht ... -
NIO-UDP实例
2017-05-09 12:32 1584DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析二(报文发送与接收)
2017-05-09 09:03 1404DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析一(初始化)
2017-05-08 21:52 1406Channel接口定义:http://donald-drape ... -
MembershipKeyImpl 简介
2017-05-08 09:11 922MembershipKey定义:http://donald-d ... -
DatagramChannel定义
2017-05-07 23:13 1227Channel接口定义:http://donald-drape ... -
MulticastChanne接口定义
2017-05-07 13:45 1136NetworkChannel接口定义:ht ... -
MembershipKey定义
2017-05-06 16:20 915package java.nio.channels; i ... -
SocketChannelImpl 解析四(关闭通道等)
2017-05-05 08:38 2527SocketChannelImpl 解析一(通道连接,发送数据 ...
相关推荐
源代码通常会涉及文件流操作、内存映射以及位操作等技术。 7. **应用与扩展** BMP文件格式简单直观,适合教学和实验。然而,由于其未压缩的特点,文件体积较大,不适合网络传输或存储。在实际应用中,更常见的图像...
3. 解析和响应命令:循环读取控制通道的输入,解析为FTP命令,根据命令执行相应操作,如验证用户身份、改变工作目录等。 4. 数据通道管理:根据FTP命令(如RETR或STOR)创建和管理数据通道,进行文件的读写。 5. ...
在Java中,文件读写是通过流来实现的,流是一种从源头到目的地的数据传输通道。Java支持两种基本类型的流:**字节流**和**字符流**。 - **字节流**:适用于任何类型的数据,如图片、音频、视频等二进制文件。主要的...
总的来说,TCP文件传输服务器涉及了网络编程、并发处理、文件操作等多个方面的知识,是学习和实践网络通信技术的一个很好的应用场景。通过分析和实现这样的系统,开发者可以深入理解TCP/IP协议栈的工作原理,并提高...
在深入探讨如何利用Java进行socket文件传输之前,我们首先需要理解几个关键概念:socket编程、非阻塞IO、选择器(Selector)、以及文件读写操作。本文将详细解释这些概念,并通过分析提供的部分Java代码片段,阐述...
在C/S架构中,服务器负责监听客户端的连接请求,一旦有请求到来,就会建立一个新的连接并处理数据传输。客户端则通过发起连接请求,与服务器建立通信通道,用于发送文件或接收文件。 3. **多线程技术**: 为了...
设计模式中的接口则可以用来规范不同组件之间的交互,例如定义一个`FileTransfer`接口,规定文件传输的相关操作,如`sendFile()`和`receiveFile()`,这样可以使代码更具扩展性和可维护性。 5. **源码解析**: ...
它的主要功能是管理存储设备上的数据,包括文件的创建、读取、修改和删除等操作。FAT文件系统有多种版本,如FAT12、FAT16、FAT32,以及后来的VFAT,后者主要是为了解决FAT32对长文件名的支持问题。 在这个"SD卡实验...
在Linux操作系统中,文件系统包含了各种类型的文件,其中包括普通文件、目录文件以及一系列特殊文件,如设备文件(块设备和字符设备)、管道文件、符号链接(软链接)和硬链接等。这些特殊文件在Linux中扮演着至关...
总结来说,“top_block.zip”中的FTP文件传输服务器端实现是基于Python的,它能够提供基本的FTP服务,包括连接管理、身份验证、文件操作等,确保了文件在客户端和服务器之间的安全传输。通过分析和理解“top_block....
总的来说,NIO数据传输稳定性优化是一项复杂的工作,涉及到多个层面的考虑和调整。通过不断迭代和优化,我们可以逐步提升系统的可靠性和用户体验。对于开发者来说,理解和掌握这些优化技巧是提升服务质量的关键。
3. **数据传输的完整性与可靠性**:TCP协议通过序列号、确认应答、重传机制等确保了数据的完整性和可靠性。在Java中,通过Socket的输入/输出流(InputStream和OutputStream的子类,如DataInputStream和...
### Linux IO数据通道详解 #### 一、IO数据通道处理层次 在Linux系统中,输入/输出(Input/Output,简称IO)操作是一项基础而...这些机制不仅保证了系统的稳定性和可靠性,也为应用程序提供了高效的数据传输能力。
驱动需要设置DMA通道,处理数据传输的开始和结束,并在中断服务程序中处理错误。 4. **错误处理**:在驱动开发过程中,需要考虑到各种可能出现的错误情况,如命令超时、数据校验失败等,并提供相应的恢复机制。 5....
9. **FTP源码分析**:压缩包中的"FTP"文件可能是FTP程序的源代码,分析这个源码可以帮助我们深入理解FTP文件传输的具体实现,包括如何建立连接、发送命令、处理响应以及进行文件读写等操作。 总的来说,这个压缩包...
- **Buffers**:用来存储数据的对象,是数据传输的载体。 - **Selectors**:多路复用器,用于监控多个Channel的状态变化,支持高效地处理大量并发连接。 - **FileChannel**:用于与文件进行交互的Channel,提供了...
- **传输数据:**DataNode接收到请求后,将文件数据传输回客户端。 - **本地处理文件:**客户端接收到数据后,在本地对文件进行相应的处理操作。 #### 二、基础API案例 **1、基础演示接口** 在HDFS中,为了简化...
4. **数据传输**:客户端和服务器通过各自创建的流对象进行数据读写操作。可以使用`StreamReader`和`StreamWriter`进行文本数据交换,或者直接操作`Stream`进行二进制数据交换。 5. **关闭连接**:通信完成后,应...
4. **数据传输**:FTP使用两种通道,控制通道和数据通道。控制通道处理命令交互,数据通道则负责实际的文件传输。 5. **断开连接**:完成操作后,客户端会发送QUIT命令,关闭控制通道,然后断开连接。 【FTP协议的...