00:00
再看一个关于通道的案例。那前面呢,我们是分别用单独的八本来读取。或者是写入数据。现在呢,我们用使用一个buffer完成文件的读取和写入,那案例的要求是这样子的,使用channel,呃,Fair channel和相关的方法read和write完成文件的一个拷贝。我们要拷贝的一个文件呢,叫T,呃,1.txt,然后把它放在项目下面,我们会把这个文件里面内容拷贝到另外一个文件,比如说是2.txt,但是在这个过程中呢,我们只允许使用一个buffer。我先把他的示意图画一下。大家看我们在前面呢,是。我们第一个案例是走的这条线。是这样子吧,第二个案例呢,指的是这条线,这里面我们用了两个buffer。而我们知道buffer呢,它既可以读也可以写,所以说我们这次呢,用一个buffer,大概的意思是这样子的。
01:06
呃,大概。我们要做的事情是这样子,我把这个往下面复制一份。我要做件什么事情呢?比如说这边我有一个文件。我有一个文件,比如说这个文件的名字我们就叫一。TXT。没有问题,然后呢,我会创建一个我Java的输入流对象里面呢,我会去得到它相关联的channel。然后呢,我会把这面数据放到我们这个channel里面,然后从这个圈里面的数据呢,把它又放到我们这一个bit buffer,放到这个better buffer过后我怎么办呢?OK。我下面继续这样做。我会把这个buffer里面的数据再去创建。这样一个对象。就是另外一个通道。
02:00
对,然后进行的操作就是这样子的。对,这样子一个操作。大家看清楚了哈,就是我先把这个文件。那这个文这个文件和一个发圈的关联,然后把这个发圈的数据呢,放到这个buffer,放这个buffer过后呢,我再去得到一个输出流对象里面呢,又会有一个fair channel,然后把这个buffer的数据放到这个圈里面去,然后把这个呃输出呃流对关联的fair channel数据放到我们一个新的文件里面去,最后呢,相当于说就完成了一个拷贝。关键口碑。大家可以看到,如果我们是传统的。传统的阻塞型的。这个文件拷贝呢,实际上中间是可以不需要这个buffer的,但是现在因为我们使用是文件通道。加buffer的机制来完成的,所以说拷贝一个文件呢,是这样一个流程,我们来举例说明,示意图已经说好了,现在呢,我们编写这个代码。
03:06
新建一类叫ne,还是我们的fire channel。对不对,这是我们的第三个小案例。开始编写。主方法,那首先呢,我们先建一个这样的文件哈,在SR上去建一个文本文件1.txt。我就写一些比较简单的数据吧,比如说hello world上硅谷。你好,好吧,再来一个hello OK,好了,可以了。这是我们准备进行拷贝的文件,就是跟图上对应的就是1.txt文件,那下面呢,我们要分别创建的是输入流对象和它的关联的fair channel,输出流对象和它关联的fair channel,然后呢,还得有一个字节。
04:01
是不是这是字节八份好的,那现在呢,回到我们刚才建的零三就开始编写了,那这里呢,我们就快速走向,有些注释我就不写了哈,这反而input。我们首先要指向的是1.tt,因为他现在呢,就放在我们项目的根部下面,就不需要再路径了。好,这是我们的输文件输出流对象。我扔出异常。简单一点哈,我们扔出一个异常就行了,当然你也可以把它包起来,然后再获取到这一个输出输入啊,这是输入流,输入流对象对应的channel。没问题,我们得到文件channel,比如说这个名字呢,我们取个零一。以示区别,紧接着继续往下编写,干什么呢,六。我们的文件输出流对象,这次是一个输出流,因为待会儿要写嘛。
05:05
Fire output。Output,那关联的文件呢,我们就叫2.tat,如果没有这个文件,它会自动创建。好,创建好了,同样我们也得到该流对应的文件channel。没问题,取个名字叫fire channel,零二没问题,紧接着继续往下走,因为在整个过程中呢,大家也知道我们需要一个buffer China做一个中转,因为这就是NIO编程的一种模式,我们必须遵守,那下面呢,我们就来创建一个bit buffer。对不对,方法allocate大小呢?咱们可以拿一个512。啊,当然你也可以根据实际情况来填字,填写bad buffer搞定,有了bad buffer过后呢,我就用Y循环开始来读取,因为我们并不知道这个文件到底有多大,所以说我肯定是用while循环来循环的读取,循环读取。
06:09
下面怎么读呢?大家想一想,首先我们是不是要把这个文件的内容。呃,放到我们这,呃写叫。就放到我们这个ne向上,这个其实就是它的一个。读取。读取。那现在我们要读取的话呢,那现在我们就来开始继续往下走。读取的时候,同学们,我们就应该选用哪个方法呢?大家不要搞混淆了,应该选用的是read的方法,因为read的方法是把通从通道读取数据并放入到缓冲区,因为你现在呢,这个通道已然跟我们这个文件关联了,对不对?也就是相当于说我们现在就把这个数据扔到这里面去,因为你现在这个通道呢,已经跟这个文件关联了。
07:00
好的。那既然关联了,下面我们就开始来走,哪一句话呢?是不是就应该使用我们的这一个?第一个。发。穿着衣。点read,把它放到哪里去呢?放到bit。Buffer里面去这边它会返回一个什么呀,大家看会返回一个int,这个int呢,呃,这个int值它其实就是代表它,呃读取到的这个数据是多少?呃,首先我们可以看到,如果RAID它等于负一。这里要注意,如果等于负一,代表读取结束。表示。啊,读完了,读完了,读完。如果是读完的话呢,那就没有什么可说的,我们就break循环,那如果说没有读完,是不是要进行下次的读取啊,所以说呃,下次读取,所以你还不能退出。
08:00
那么同学们知道我们在这里数据已经放在这个buffer,现在是不是还要把这个buffer放到这个China里面去,这就是相当于又要做下一个工作什么呢?OK。下一个工作就是要把buffer里面的数据放入到我们这个channel,而这个呢,大家知道已经跟我们的2.tc关联的,因此你在往把这个buffer数据往这个圈里面写的时候,就相当于写到这个文件里面去了,为什么?因为他们两者已经关联了,怎么关联的呢?是相关联的,是通过一个output。流对象和这个文件关联,而这个output流流对象呢,又跟又拿又得到了对应的fair channel,所以说它呢,其实你你可以理解成就是跟我们这个文件关联起来了,明白好,现在呢,我们读了一部分呢,就直接写入将。八份中的注意看啊,它是一步步来的哦,八份。
09:00
中的数据写入到,写入到哪里呢?朋友们是不是应该写入到我们这一个fire china02,而这个FIRE02呢,实际上是跟2.tc做完的。是不是这个道理,好的,那这样子写入,像buffer中的数据写入到发圈零二里面去,是不是就应该用read的方法了,那应该是对哪一个操作呢?是零二,注意啊,不要写错了,零二零二点什么呢?同学们是不是right了?是不是right的话,是不是把我们这个buffer里面扔进去就可以了,但是这样做有没有问题?同学们想你原先这个buffer是处于往里面放的状态,是put的状态,现在你要从这个buffer里面读数据,再放到我们这个圈儿里面去,是不是要进行一个反转,不要忘了这件事情啊,否则的话,这个代码是错的,一定有一个。颁奖的动作。Flip。
10:00
这就写完了。那么这样写完以后,同学们看我们这个代码有没有bug呢?这段代码其实是有bug的,为什么有bug,同学们想。你现在是512。假设我是五呢,你就意味着你第一次是读不完,你一次可能是读不完一点贴写内容的,如果你读不完的话,他下次下次再来读的话,这边就可能会读到一个零,因为那个时候你原生的这一个什么呢?Position和limit是相同的。所以说你如果这个量很小,你会发现呢,这个地方就会循环的读取出不来,因为它读不到负一。我不知道大家听清楚没有,这样子吧,我们先按一个正常流程走,走完了过后我们再来玩,好吧。那这样子我们这里面需要有一段代码,要进行什么呢?这里要一个重要的操作,一定不要忘了哪个操作呢,就是复位,也就是说我们要调一个bad buffer clean。
11:06
可令,这个可令的方法,要把我们这个buffer这个可令的动作是干什么呢?其实就是把我们的这些呃标志位重置一下。重置一下,好,这个是重置。就是干嘛清空我们数据吧,我要清空。清空我们这一个buffer。经过那个barber的动作,我们看他到底做一件什么事情,其实就是做这个工作。那这个工作就是把我们的什么呢?其实就是相当于把我们这些关键的,关键的这些属性重置一下,是不是把CA。付给我们limit把po制成零,否则的话你这个不做这个工作,并且把mark把它作废,否呃失效或者叫失效,如果你没有这个工作的话,你会发现这个数据呢会出问题。就是整整个代码会会出问题的,好的同学们,我们先把这个拿过来。
12:03
那待会到底为什么有这句话,待会老师再给他分析,我去掉过后你会看到他是发生一个什么事情,一下就明白了。好,同学们,这一段代码写完了,过后呢,我们紧接着按正常流程走,待会儿再做分析,好吧。关闭,写完了以后不要忘了一件事情,什么事情呢?关闭啊,关闭相关的。相关的这个,呃,这个流。那这时呢,我们可以这样关闭,两个都可以啊,我们从这关闭可以了。Close。对吧,这边呢,有一个output,我们也把它关闭了。Close掉就可以,好,现在同学们我们来玩一把,看看此时此刻运行起来过代码能不能顺利的运得到这个结果哈,来,走起来,跑起。好。
13:00
跑起来过后,我们看到这边。那这个1.tt文件,他们是不是我分错位置了。哦,这个位置放的不对,哦,这个位置放的不对,应该放在这个项目下边去。好,放到下面去。这样就没问题了啊,我把它挪到了。这这个项目下边去就没事了,好我们再来运行一下,刚才位置没有放对。再运行跑起来。好的。那这时呢,我们就得到了一个2.t,我们打开看是不是这样的文件,好,同学们看,Hello word没有任何问题,数据呢是一样的,那现在呢,我们回头再对刚才这个文件呢做一点分析,就是如果我们去掉这句话会有什么后果哈。这句话去掉会有什么后果?我们看一下,如果我们去掉这句话过后。啊,我们这样子,我们先来看第一次他得到的数据是多大。
14:03
都同学们要注意分析一下啊,Read等于。加read。大家可以想象第一次这个读到是多少,第一次因为我们这个空间是512,所以说它其实第一次就把整个这个文件就全部读到了,大家可以算一下是多大呢,你看啊,这边呢,有一二三四五六七八九十十一,再加上一个。换行是吧,所以说它其实就应该是什么呢。对不对,它就应该是一二三四五六七八九十,十一十一,再加一个回车换行就是13。这是13。13再加一个九,九加一个二,就11,再加一个什么呢?再加这十六六,再加回收方向就八,再加下面这个12345678,好停了再加八,那也就是说他第一次应该读到的字节数应该是24加16。
15:06
那等于多少呢?等于40,好,我们看是不是等于40,我们算一下刚刚刚才的这个这个分析哈,是不对的,我们运行。我们运行一把,跑起来,看看read的数据是不是等于40。好,我们可以看到的确它是事实,那么当他读第二遍的时候呢,因为已经读到了我们第一个文件的结束,所以它就返回一个负一,刚好就。Break,那这句话重不重要呢?同学们看,我们来看一下这句话啊,这句话是非常重要的,如果你没有这句话呢,后果是这样子的。它会反复的得到,得到一个RAID0,你看它会循环在这里看,大家看。是不是循环的读我就停下啊?为为什么会循环读到一个零呢?同学们想。为什么循环会循环读到一个零呢?就是因为你。你到最后的时候,你没有复位,没有复位这个数据他读到最后了,读到最后,读到最后这个position。
16:08
Po人和这个雷。零米对它相等,你们可以试一下,它一旦相等再去读的时候呢,它就返回是个零了呀,所以说就没有机会等于负一,因此它就死循环,同学们可以给大家在这下个断点,你们看一下就可以了,如果你没有这个肯定是要出大问题的,来我们看一下。他一旦读完了过后啊,我们在这反转了过,反转了过后这边就会相等,我们来跑一个,肯定要读,读完一次你才会发现它们相等嘛,来走一个哈。我们调试一把。好,继续往下走。往下走,我们主要是找这个八份。好的,同学们看这现在这个buffer呢,Position是事实,Limit是512,因为你初始化的时候,Limit和capital是一样的,这个没有问题,接着往下走。
17:01
好,这边它会读,读完了过后大家有发现啊,继续往下走,走到这儿,走到这个地方的时候呢,你要反转。Flip要反转,因为你现在要开始,呃,从这个buffer里面取数据了嘛,或者是读数据接着往下走,好同学们看FLIP1做这福利一做过后呢,我们可以看到。看到这个地方position等于零了。Position等于零,但是你还没right嘛,没有动它,没有读它,所以说这个position现在等于零是正正确的,但是一度完了以后呢,这个position就会跟limit米相等,来看一下哦,OK,看position和limit相等了,Position和limit相等,你又回到这边再读,大家看,接着往下走。是不是这个时候再一读,因为这两两者相同,所以说它返回一个什么呢?返回一个零,Read是等于零的啊,我看那看是等零零不等于负一,于是他就在这反复的执行。
18:00
反复的执行。OK,就这样一个原因,好,就这样一个原因,我就分析到这里,大家看懂了没有,所以说这个地方必须要复位,复位过后呢,他才是相当于进行下一次的一个完整的一个read和一个呃,Right的一个操作。好,同学们。关于。关于这一个案例,就是我们讲的第三个案例,用一个buffer完成文件的读取,啊,读和写,我们就说到这里,大家看。能否理解?
我来说两句