`
zhaohaolin
  • 浏览: 982212 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java NIO 入门学习(读写文件)

    博客分类:
  • JAVA
 
阅读更多

我们用原有 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 实现起来还更简洁些呢! (文/隔叶黄莺

参考:
1. NIO文件读写
2. 使用NIO的读文本文件 [ 评价与收藏 ]

分享到:
评论

相关推荐

    JAVA上百实例源码以及开源项目源代码

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术,...

    JAVA上百实例源码以及开源项目

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术,...

    java开源包4

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包101

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包11

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包6

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包9

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    Java SE实践教程 pdf格式电子书 下载(四) 更新

    本书从编程技术、项目实践以及软件工程的角度出发,如果大家想学习基础语法部分,建立去下载别的书籍。当然这本书也讲解了语法,是从实战的角度讲解的。 目录回到顶部↑第1章 进驻爪哇岛——JAVA的基本语法. 1 1.1 ...

    java开源包8

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包5

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包10

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包1

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包3

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包2

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包7

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    Java资源包01

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    疯狂JAVA讲义

    学生提问:老师,我想学习Java编程,到底是学习Eclipse好呢,还是学习JBuilder好呢? 21 1.9 本章小结 22 本章练习 22 第2章 理解面向对象 23 2.1 面向对象 24 2.1.1 结构化程序设计简介 24 2.1.2 程序的三种...

    mycat从入门到跑路

    MySQL字段类型问题 MySQL Cache问题 MySQL常见误区 第11课 Mycat eye Mycat eye的规划方向 Mycat eye功能介绍 第12课 Mycat开发入门 Mycat项目编译与运行 Mycat主要模块分析 第13课 Mycat源码分析 NIO源码分析 ...

    spring-boot示例项目

    该项目包含helloworld(快速入门)、web(ssh项目快速搭建)、aop(切面编程)、data-redis(redis缓存)、quartz(集群任务实现)、shiro(权限管理)、oauth2(四种认证模式)、shign(接口参数防篡改重放)、encoder(用户...

Global site tag (gtag.js) - Google Analytics