利用java.nio的FileChannel能够实现按行读取文件吗?(解决了)

利用java.nio的FileChannel能够实现按行读取文件吗?(解决了),第1张

利用java.nio的FileChannel能够实现按行读取文件:

具体思路是:设置两个缓冲区,一大一小,大的缓冲区为每次读取的量,小的缓冲区存放每行的数据(确保大小可存放文本中最长的那行)。读取的时候判断是不是换行符13,是的话则返回一行数据,不是的话继续读取,直到读完文件。

实现方法:

        FileChannel fc=raf.getChannel()

       //一次读取文件,读取的字节缓存数

       ByteBuffer fbb=ByteBuffer.allocate(1024*5)

        fc.read(fbb)

        fbb.flip()

     //每行缓存的字节   根据你的实际需求     

      ByteBuffer bb=ByteBuffer.allocate(500)

   

              //判断是否读完文件

public boolean hasNext() throws IOException {

        if(EOF)return false

        if(fbb.position()==fbb.limit()){//判断当前位置是否到了缓冲区的限制

            if(readByte()==0)  return false

        }

        while(true){

            if(fbb.position()==fbb.limit()){

                if(readByte()==0)  break

            }

            byte a=fbb.get()

            if(a==13){

                if(fbb.position()==fbb.limit()){

                    if(readByte()==0)  break

                }

                return true

            }else{

                if (bb.position() < bb.limit()) {

                    bb.put(a)

                }else {

                    if(readByte()==0)  break

                }

            }

        }

        return true

    }

用你的方法,当你锁住文件再解锁的时候你会发现,原来文件里的内容不见了,所以后一段读文本的程序只能读到一个null ,你可以参考这个http://blog.csdn.net/wangjichen_1/article/details/6205779

java.NIO包里包括三个基本的组件

l buffer:因为NIO是基于缓冲的,所以buffer是最底层的必要类,这也是IO和NIO的根本不同,虽然stream等有buffer开头的扩展类,但只是流的包装类,还是从流读到缓冲区,而NIO却是直接读到buffer中进行 *** 作。

因为读取的都是字节,所以在 *** 作文字时,要用charset类进行编解码 *** 作。

l channel:类似于IO的stream,但是不同的是除了FileChannel,其他的channel都能以非阻塞状态运行。FileChannel执行的是文件的 *** 作,可以直接DMA *** 作内存而不依赖于CPU。其他比如socketchannel就可以在数据准备好时才进行调用。

l selector:用于分发请求到不同的channel,这样才能确保channel不处于阻塞状态就可以收发消息。

面向流与面向缓冲

Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java

IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

补充一点:NIO的buffer可以使用直接内存缓冲区,该缓冲区不在JVM中,性能会比JVM的缓冲区略好,不过会增加相应的垃圾回收的负担,因为JVM缓冲区的性能已经足够好,所以除非在对缓冲有特别要求的地方使用直接缓冲区,尽量使用JVM缓冲。

阻塞与非阻塞

Java IO是阻塞式的 *** 作,当一个inputstream或outputstream在进行read()或write() *** 作时,是一直处于等待状态的,直到有数据读/写入后才进行处理.而NIO是非阻塞式的,当进行读写 *** 作时,只会返回当前已经准备好的数据,没有就返回空,这样当前线程就可以处理其他的事情,提高了资源的使用率.

与传统IO的优势

在老的IO包中,serverSocket和socket都是阻塞式的,因此一旦有大规模的并发行为,而每一个访问都会开启一个新线程。这时会有大规模的线程上下文切换 *** 作(因为都在等待,所以资源全都被已有的线程吃掉了),这时无论是等待的线程还是正在处理的线程,响应率都会下降,并且会影响新的线程。

而NIO包中的serverSocket和socket就不是这样,只要注册到一个selector中,当有数据放入通道的时候,selector就会得知哪些channel就绪,这时就可以做响应的处理,这样服务端只有一个线程就可以处理大部分情况(当然有些持续性 *** 作,比如上传下载一个大文件,用NIO的方式不会比IO好)。

通过两个图的比较,可以看出IO是直连的,每个请求都给一条线程来处理,但是NIO却是基于反应堆(selector)来处理,直到读写的数据准备好后,才会通知相应的线程来进行处理。一言以蔽之:“selector不会让channel白占资源,没事的时候给我去睡觉。”

PS:NIO基于字节进行传输,在IO时要注意decode/encode。

更具体的信息请参阅:http://blog.csdn.net/zhansong_1987/article/details/45873861


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11528286.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存