`
wsqwsq000
  • 浏览: 678260 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

用NIO读写文件

    博客分类:
  • j2ee
 
阅读更多
我们用原有 IO 读写文件应该不会陌生了,顺带回顾一下,大致两种:

1. 在 InputStream 或 OutputStream 上读写字节或字节数组,读 InputStream 时用是否返回 -1 来判断是否到达末尾。
2. 包装成 Reader/Writer 可以直接读写字符串,进一步包装到 BufferedReader/BufferedWriter 就可以按行读写了。readLine() 时看是否返回 null 断定是否读完了最后一行。

现在我们要用 NIO 来读写文件,肯定是要用到 Channel 和 Buffer 了。一句话描述过程就是从 FileInputStream 得到的 FileChannel 中读取数据到 Buffer 中,再处理 Buffer 中的数据。看代码:
  1. 01.public static void main(String[] args) throws Exception {
  2. 02.    FileInputStream fis = new FileInputStream("C:/Java/jdk1.6.0_18/LICENSE");
  3. 03.   
  4. 04.    //得到文件通道
  5. 05.    FileChannel fc = fis.getChannel();
  6. 06.   
  7. 07.    //分配与文件尺寸等大的缓冲区
  8. 08.    ByteBuffer bf = ByteBuffer.allocate((int) fc.size());
  9. 09.   
  10. 10.    //整个文件内容全读入缓冲区,即是内存映射文件
  11. 11.    fc.read(bf);
  12. 12.   
  13. 13.    //把缓冲中当前位置回复为零
  14. 14.    bf.rewind();
  15. 15.   
  16. 16.    //输出缓冲区中的内容
  17. 17.    while (bf.hasRemaining()) {
  18. 18.        System.out.print((char) bf.get());
  19. 19.    }
  20. 20.}
复制代码
上面程序使用了一个与文件尺寸等大的缓冲区,正好能一次性把文件内容全部读入内存,如果文件过多将是十分耗费的内存的,所以我们可能须手工指定某个大小(如 1024,2048) 的缓冲区,然后分多次读入文件内容到缓冲区中。这时候程序就是下面那样子了:
  1. 01.public static void main(String[] args) throws Exception {
  2. 02.    FileInputStream fis = new FileInputStream("C:/Java/jdk1.6.0_18/LICENSE");
  3. 03.
  4. 04.    // 得到文件通道
  5. 05.    FileChannel fc = fis.getChannel();
  6. 06.
  7. 07.    // 指定大小为 1024 的缓冲区
  8. 08.    ByteBuffer bf = ByteBuffer.allocate(1024);
  9. 09.
  10. 10.    // 读取通道中的下一块数据到缓冲区中
  11. 11.    // 缓冲区的 position 即为当前缓冲区中最后有效位置
  12. 12.    while (fc.read(bf) != -1) {
  13. 13.
  14. 14.        //把缓冲中当前位置回复为零,前把缓冲区的 limit 设置为之前 position 值
  15. 15.        bf.flip();
  16. 16.
  17. 17.        // 输出缓冲区中的内容
  18. 18.        while (bf.hasRemaining()) {
  19. 19.            System.out.print((char) bf.get());
  20. 20.        }
  21. 21.
  22. 22.        // 清理缓冲区,准备再次读取数据
  23. 23.        bf.clear();
  24. 24.    }
  25. 25.}

  26. 留意对缓冲区的 rewind()/flip()/clear() 操作所产生的影响,即对 position/limit/mark 等标志的影响。最后提醒操作完之后,要关闭通道和输入流。

  27. 用 ByteBuffer 知道了怎么读文件内容(当然,还未涉及到中文内容)并打印到屏幕后,再来看看 NIO 怎么写文件:

  28. view source
  29. print?
  30. 01.public static void main(String[] args) throws FileNotFoundException, IOException{
  31. 02.    FileOutputStream fos = new FileOutputStream("c:/nio.tst");
  32. 03.
  33. 04.    // 得到文件通道
  34. 05.    FileChannel fc = fos.getChannel();
  35. 06.
  36. 07.    // 指定大小为 1024 的缓冲区
  37. 08.    ByteBuffer bf = ByteBuffer.allocate(1024);
  38. 09.
  39. 10.    // 要写入文件的字符串
  40. 11.    String greeting = "Hello, Java NIO";
  41. 12.   
  42. 13.    //把以上字符串逐字放入缓冲区
  43. 14.    for (int i = 0; i < greeting.length(); i++) {
  44. 15.        bf.putChar(greeting.charAt(i));
  45. 16.    }
  46. 17.   
  47. 18.    // 记得执行这个方法,使得 position=0, limit=30, 才能写入正确的数据
  48. 19.    // 否则 position 为 30, limit 为 1024,将会把 30 之后的全部空数据(0) 填到文件中
  49. 20.    bf.flip();
  50. 21.
  51. 22.    // 缓冲区数据写入到文件中,会把缓冲区中从 position 到 limit 之间的数据写入文件
  52. 23.    fc.write(bf);
  53. 24.   
  54. 25.    fc.close(); //关闭文件通道
  55. 26.    fos.close(); //关闭文件输出流
  56. 27.}
复制代码
同样的,如果是写入中文内容,也需要进行字符集的相关处理。执行后在 C 盘根目录下产生 nio.tst 文件,内容就是 Hello, Java NIO。此代码的关键之处就是对缓冲的 flip() 调用,你可以在调试模式下观察到 flip() 方法调用前后,缓冲区 bf 的 position/limit 属性的变化。试着注释掉 flip() 代码,看看两次生成的 nio.tst 文件内容是不是大相径庭。

所以,要用好 NIO,缓冲区的 mark/position/limit/capacity 属性应理解,以及 clear()/flip()/rewind() 分别会怎么影响到以上属性。

还有,虽然说通道是双向的,字面上不像流那样区分输入通道或是输出通道,但实际通道也存在只读或只写的特性,例如由 FileInputStream.getChannel() 获得的通道是无法写入内容的,由 FileOutputStream.getChannel() 获得的通道是不能读的,否则会抛出相应的异常 NonWritableChannelException 和 NonReadableChannelException。而且 Buffer 也存在着是否只读的属性。

前面的代码在这里只是说明用 NIO 读写文件应如何处理,并不是说比起用旧 IO 流式的写法效率就更高了。NIO 的高效率只会体现在有些时候,并非任何时候都优于旧 IO,那是块操作和字节操作的区别,用 NIO 时要小心内存。伸手就能摘到的梨用不着搬个凳子,何况旧 IO 实现起来还更简洁些呢!
分享到:
评论

相关推荐

    Java文件读写IO/NIO及性能比较详细代码及总结

    主要介绍了Java文件读写IO/NIO及性能比较详细代码及总结,具有一定借鉴价值,需要的朋友可以参考下。

    JAVA_IO/NIO(demo,压缩jar文件)

    io/nio各种文件读写方法。文件压缩成jar包。

    javaNIO实例

    该资源包含了一个用javaNIO实现的读写文件以及复制文件的简单的demo,程序注释清晰,简单易懂,喜欢的下载!!!

    Java NIO原理和使用

    Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内容,如果没有内容进来,...

    java.nio新功能的优点

    java 1.4中推出的java.nio(新输入/输出)软件包允许像在其他低级语言——如C语言——中一样进行输入/输出。许多开发者认为这些新功能只能进行非阻塞操作;但是,这些新功能提供许多其他新鲜有趣的特性,它们包括:...

    java文件读写处理

    对文件的读取,写入,文件复制等,包括:customBuffer复制文件,nioBuffer复制文件,nioTransfer复制文件

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    利用JDK7的NIO2.0进行I/O读写和监视

    NULL 博文链接:https://sharong.iteye.com/blog/1569883

    JAVA Nio 学习探究

    包含NIO核心概念、基本文件读写、缓冲区内部实现机制、异步IO、缓冲区更多特性探究、文件锁与字符集

    NIO概述

    2.2 NIO概述 NIO NIO ==&gt; New IO(新IO), ... 缓冲使用可以提供操作效率,减少不必要的读写次数 选择器 Selector 真·核心 老大 boss 2.3 Buffer Channel完成文件操作 2.3.1 常用API java.nio.Buffer Buffe

    javasnmp源码-nio-learn:JavaNIO使用示例,NIO的使用,TCP,UDP的简单示例

    NIO将以更加高效的方式进行文件的读写操作。 Java NIO与普通IO的主要区别 io nio 面向流 面向缓冲区(buffer,channel) 堵塞io 非堵塞io - 选择器 java nio主要的核心组件 缓冲区 buffer 通道 Channels 选择器 ...

    Java NIO 网络编程初探

    NIO同样拥有文件读写,网络通信等IO操作,今天我们来看看NIO中的TCP网络通信的使用方法。 2. Java NIO 三大核心 Java NIO 有三大核心要素:Channel、Buffer和Selector。Java IO 的操作都是基于输入输出流的,而NIO则...

    Java性能优化之使用NIO提升性能(Buffer和Channel)

    在软件系统中,由于IO的速度要比内存慢,因此,I/O读写在很多场合都会成为系统的瓶颈。提升I/O速度,对提升系统整体性能有着很大的好处。...使用java.nio.charset.Charset作为字符集编码解码解决方案;

    详解JavaNIO

    所以,jdk1.4发布了NIO包,NIO的文件读写设计颠覆了传统IO的设计,采用『通道』+『缓存区』使得新式的IO操作直接面向缓存区,并且是非阻塞的,对于效率的提升真不是一点两点,我们一起来看看。我们说过,NIO的核心...

    java文件读写工具类分享

    主要为大家详细介绍了java文件读写工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    Java流NIO

    NIO于原来的IO有相同的功能,但是他们之间的使用方式是完全不同的,NIO是面向缓冲区,面向通道的的IO操作,NIO拥有更加高效的进行文件读写。 另外NIO在网络编程可以是一个无阻塞的IO交互,可以大大提升Socket交互的...

    nio-demo:NIO编辑演示

    nio-demo NIO编程demo 主要内容: 1、使用NIO实现文件读写,文件拷贝 2、使用NIO实现Socket编程 注:com.minghui.nio.demo包下是IBM官方demo

    fdt:FDT是高效数据传输的应用程序,它能够以磁盘速度在广域网(使用标准TCP)上进行读写。 它是用Java编写的,可以在所有主要平台上运行,并且易于使用。 FDT基于异步,灵活的多线程系统,并使用Java NIO库的功能

    它是用Java编写的,可以在所有主要平台上运行,并且易于使用。 FDT基于异步,灵活的多线程系统,并且正在使用Java NIO库的功能。 其主要特点是: 通过一个或多个TCP套接字使用托管的缓冲池,连续流式传输数据集...

Global site tag (gtag.js) - Google Analytics