原文出自:http://blog.csdn.net/lirx_tech/article/details/51396268

1. 通道映射技术:

1) 其实就是一种快速读写技术,它将通道所连接的数据节点中的全部或部分数据直接映射到内存的一个Buffer中,而这个内存Buffer块就是节点数据的映像,你直接对这个Buffer进行修改会直接影响到节点数据,而这个Buffer也不是普通的Buffer,叫做MappedBuffer,即镜像Buffer,对该Buffer进行修改会直接影响到实际的节点(更新到节点);

2) 由于是内存镜像,因此处理速度非常快!!

3) map原型:MappedByteBuffer map(MapMode mode, long position, long size);  // 将节点中从position开始的size个字节映射到返回的MappedByteBuffer中

4) mode印出来映射的三种模式,在这三种模式下得到的将是三种不同的MappedByteBuffer:三种模式都是Channel的内部类MapMode中定义的静态常量,这里以FileChannel举例

i. FileChannel.MapMode.READ_ONLY:得到的镜像只能读不能写(只能使用get之类的读取Buffer中的内容);

ii. FileChannel.MapMode.READ_WRITE:得到的镜像可读可写(既然可写了必然可读),对其写会直接更改到存储节点;

iii. FileChannel.MapMode.PRIVATE:得到一个私有的镜像,其实就是一个(position, size)区域的副本罢了,也是可读可写,只不过写不会影响到存储节点,就是一个普通的ByteBuffer了!!

5) 映射的规矩:

i. 使用InputStream获得的Channel可以映射,使用map时只能指定为READ_ONLY模式,不能指定为READ_WRITE和PRIVATE,否则会抛出运行时异常!

ii. 使用OutputStream得到的Channel不可以映射!!并且OutputStream的Channel也只能write不能read!

iii. 只有RandomAccessFile获取的Channel才能开启任意的这三种模式!

6) MappedByteBuffer的用法和普通的ByteBuffer一样,只不过它的功能被上述的映射规则所限制了,比如只读的就只能get不能put,可写的以及私有的put、get都能用;

7) 示例:只读映射

  1. public class Test {
  2. public static void main(String[] args) throws IOException {
  3. File f = new File("out.txt");
  4. try (
  5. FileChannel fcin = new FileInputStream(f).getChannel();
  6. FileChannel fcout = new FileOutputStream("a.txt").getChannel();
  7. ) {
  8. MappedByteBuffer mbb = fcin.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
  9. Charset cn = Charset.forName("GBK");
  10. System.out.println(cn.decode(mbb));
  11. mbb.flip(); // 写出去之前要操作就绪
  12. fcout.write(mbb);
  13. }
  14. }
  15. }

2. RandomAccessFile的通道映射可读可写:

1) RandomAccessFile也有getChannel方法获取相应的NIO通道;

2) 其实NIO通道映射技术最大的受益者就是RandomAccessFile了,因为RandomAccessFile本身就是可读可写I/O通吃,如果RandomAccessFile的节点文件映射到内存中,直接对内存镜像修改来更新文件节点那岂不是效率大大提高吗?

3) RandomAccessFile获取的通道同样是FileChannel,因此其使用上和之前讲过任何一个普通的Channel没有区别,映射map也是理所当然的一样;

4) 只不过其Channel在map时只读、读写、私有三种模式都可以使用,不像InputStream和OutputStream那样有种种约束;

!!只不过读写模式下,对内存镜像做出的修改会直接更新到节点文件!!

!!这里插播一个Channel常用的方法:long position(); // 获取当前操作到节点文件的哪个位置

5) 示例:将文件第一个字符改成“牛”,然后将改动好的整个文件内容复制一遍再追加到文件末尾!

  1. public class Test {
  2. public static void main(String[] args) throws IOException {
  3. File f = new File("out.txt");
  4. try (
  5. FileChannel fc = new RandomAccessFile(f, "rw").getChannel();
  6. ) {
  7. MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, f.length());
  8. mbb.put("牛".getBytes()); // 注意是字节,一定要转换成字节才行,这里对镜像的修改直接生效到节点文件中了!
  9. fc.position(f.length()); // 定位到文件末尾
  10. mbb.clear(); // 注意!一定要是clear,将limit定位到capacity!如果是flip则当前limit才在第二个字符位置!
  11. fc.write(mbb);
  12. }
  13. }
  14. }

!!注意:flip和clear要灵活运用,要根据他们的定义来(limit、position的变化);

(转)[疯狂Java]NIO:Channel的map映射的更多相关文章

  1. Java NIO Channel之FileChannel [ 转载 ]

    Java NIO Channel之FileChannel [ 转载 ] @author zachary.guo 对于文件 I/O,最强大之处在于异步 I/O(asynchronous I/O),它允许 ...

  2. Java NIO Channel和Buffer

    Java NIO Channel和Buffer @author ixenos Channel和Buffer的关系 1.NIO速度的提高来自于所使用的结构更接近于OS执行I/O的方式:通道和缓冲器: 2 ...

  3. Java NIO Channel通道

    原文链接:http://tutorials.jenkov.com/java-nio/channels.html Java NIO Channel通道和流非常相似,主要有以下几点区别: 通道可以读也可以 ...

  4. (三:NIO系列) Java NIO Channel

    出处: Java NIO Channel 1.1. Java NIO Channel的特点 和老的OIO相比,通道和NIO流(非阻塞IO)主要有以下几点区别: (1)OIO流一般来说是单向的(只能读或 ...

  5. [翻译] java NIO Channel

    原文地址:http://tutorials.jenkov.com/java-nio/channels.html JAVA NIO channels和流的概念很像,下面是他们的一些区别: 你可以对cha ...

  6. Java NIO Channel to Channel Transfers通道传输接口

    原文链接:http://tutorials.jenkov.com/java-nio/channel-to-channel-transfers.html 在Java NIO中如果一个channel是Fi ...

  7. Java NIO Channel to Channel Transfers

    In Java NIO you can transfer data directly from one channel to another, if one of the channels is a ...

  8. Java NIO Channel 使用

    Java NIO 中的 Channel 分类: FileChannel SocketChannel ServerSocketChannel DatagramChannel channel 分类 Fil ...

  9. 【JAVA】【NIO】3、Java NIO Channel

    Java NIO和流量相似,但有些差异: ·通道可读写,流仅支持单向.读或写 ·异步通道读取 ·通道读写器,他们是和Buffer交替 道的实现 下面是Java NIO中最重要的通道的实现: ·File ...

随机推荐

  1. JSP学习(一)之中文乱码问题的解决

    一.响应中的乱码 我们所看到的页面,是由服务器把内容放入响应(response)中,然后发送给浏览器的.如果响应中的数据无法被正常解析,就会出现中文乱码.为什么英文不存在乱码问题?因为无论是ISO-8 ...

  2. 201521123068 《java程序设计》 第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1.MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己 ...

  3. 聊聊JAVA中 String类为什么不可变

    前言 "我的风格比较偏传统和经典" 小明说,"我们在打扮自己的问题上还是蛮冒险的...我觉得当你是只狗的时候,穿什么都hold的住!" 哈哈哈,脱离单身狗快两年 ...

  4. python之进程----Queue

    一.Queue是通过multiprocessing使用 from multiprocessing import Process,Queue import time import random impo ...

  5. Winfrom 简单的安卓手机屏幕获取和安卓简单操作

    为啥我要做这个东西了,是因为经常要用投影演示app ,现在有很多这样的软件可以把手机界面投到电脑上 ,但都要安装,比如说360的手机助手,我又讨厌安装,于是就自己捣鼓了下 做了这个东西, 实现了以下简 ...

  6. 定位页面元素之xpath详解以及定位不到测试元素的常见问题

    一.定位元素的方法 id:首选的识别属性,W3C标准推荐为页面每一个元素设置一个独一无二的ID属性, 如果没有且很难找到唯一属性,解决方法:(1)找开发把id或者name加上.如果不行,解决思路可以是 ...

  7. mysql水平分表和垂直分表的优缺点

    表分割有两种方式: 1.水平分割:根据一列或多列数据的值把数据行放到两个独立的表中. 水平分割通常在下面的情况下使用. •表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数 ...

  8. c# 第一节课 一些简单的应用

    注册要钱 我没钱

  9. CSS1-3基礎知識

    CSS1-3基礎知識 1.css排版 css在html內排版: <style type='text/css'> 標記名{} .類型名{} #ID名{} 標記名,.類型名,#ID名{} &l ...

  10. this的四种绑定形式

    一 , this的默认绑定 当一个函数没有明确的调用对象的时候,也就是单纯作为独立函数调用的时候,将对函数的this使用默认绑定:绑定到全局的window对象. 一个例子 function fire ...