关于龙哥在Netty课程中的FileChannel调用read方法返回0的原因解析

结论:fileChannel在调用read方法时会先对positionlimit的值进行检查,如果limitposition的值相等或者position大于limit则直接返回0,不会再调用操作系统的read方法了。

我们可以查看FileChannel抽象类的实现类FileChannelImplread(ByteBuffer byteBuffer)的源码:

/*      */   public int read(ByteBuffer paramByteBuffer) throws IOException
/*      */   {
/*  136 */     ensureOpen();
/*      中间的代码为判断文件是否打开,没有打开则执行对应的代码,其实不用看,因为ensureOpen()就已经在判断文件是否打开,没有则抛出异常,这可能
        是为了在多线程的情况下出现的异常才做的第二次判断 */ 
/*      */         do
/*      */         {
                     //IOUtil.read将会从这个文件中读出数据进入buffer中,并返回一个状态码,不等于-3则退出循环
/*  149 */           i = IOUtil.read(this.fd, paramByteBuffer, -1L, this.nd);
/*  150 */         } while ((i == -3) && (isOpen()));
/*  151 */         int k = IOStatus.normalize(i);//当传入的值为0时,最终也会返回0
/*  153 */         this.threads.remove(j);
/*  154 */         IoTrace.fileReadEnd(localObject1, i > 0 ? i : 0L);
/*  155 */         end(i > 0);
                   //返回状态信息 
/*  156 */         assert (IOStatus.check(i));return k;
/*      */       }
/*      */       finally
/*      */       {
/*       省略...*/ 
/*      */       }
/*      */     }
/*      */   }

我们查看IOUtil.read的源码

/*     */   static int read(FileDescriptor paramFileDescriptor, ByteBuffer paramByteBuffer, long paramLong, NativeDispatcher paramNativeDispatcher)
/*     */     throws IOException
/*     */   {
/*           这里是针对buffer进行只读或者是直接缓冲区的判断*/
/*     */     
/* 195 */     ByteBuffer localByteBuffer = Util.getTemporaryDirectBuffer(paramByteBuffer.remaining());
/*     */     try {
                //调用本类的readIntoNativeBuffer方法,并将其返回值进行返回
/* 197 */       int i = readIntoNativeBuffer(paramFileDescriptor, localByteBuffer, paramLong, paramNativeDispatcher);
/* 198 */       localByteBuffer.flip();
/* 199 */       if (i > 0)
/* 200 */         paramByteBuffer.put(localByteBuffer);
/* 201 */       return i;
/*     */     } finally {
/* 203 */       Util.offerFirstTemporaryDirectBuffer(localByteBuffer);
/*     */     }
/*     */   }

查看readIntoNativeBuffer方法的源码

/*     */   private static int readIntoNativeBuffer(FileDescriptor paramFileDescriptor, ByteBuffer paramByteBuffer, long paramLong, NativeDispatcher paramNativeDispatcher)
/*     */     throws IOException
/*     */   {
              //获得当前buffer的position值
/* 211 */     int i = paramByteBuffer.position();
              //获取当前buffer的limit值
/* 212 */     int j = paramByteBuffer.limit();
/* 213 */     assert (i <= j);
              当buffer的position值和limit值相等时,k的值就会是0,
/* 214 */     int k = i <= j ? j - i : 0;
/*     */     //k等于0,则返回0
/* 216 */     if (k == 0)
/* 217 */       return 0;
/* 218 */     int m = 0;
/* 219 */     if (paramLong != -1L) {
/* 220 */       m = paramNativeDispatcher.pread(paramFileDescriptor, ((DirectBuffer)paramByteBuffer).address() + i, k, paramLong);
/*     */     }
/*     */     else {
/* 223 */       m = paramNativeDispatcher.read(paramFileDescriptor, ((DirectBuffer)paramByteBuffer).address() + i, k);
/*     */     }
/* 225 */     if (m > 0)
/* 226 */       paramByteBuffer.position(i + m);
/* 227 */     return m;
/*     */   }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值