<Java编程思想>中I/O部分学习记录(未完待续~~)

ByteBuffer的用法:

  • 提高速度在于所使用的结构更接近于操作系统执行I/O的方式:通道和缓冲器
  • getChannel():用以产生流的通道,会返回一个FileChannel,可以向它传送用于读写的ByteBuffer
    缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数。

1

  • 所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循:mark <= position <=
    limit <= capacity,下表格是对着4个属性的解释:
属性 描述
Capacity 容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
Limit 表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的
Position 位置,下一个要被读或写的元素的索引,每次读写缓冲区数据时都会改变改值,为下次读写作准备
Mark 标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置

java.nio.Buffer类是一个抽象类,不能被实例化。Buffer类的直接子类,如ByteBuffer等也是抽象类,所以也不能被实例化
ByteBuffer类提供了4个静态工厂方法来获得ByteBuffer的实例:

方法 描述
allocate(int capacity) 从堆空间中分配一个容量大小为capacity的byte数组作为缓冲区的byte数据存储器
allocateDirect(int capacity) 是不使用JVM堆栈而是通过操作系统来创建内存块用作缓冲区,它与当前操作系统能够更好的耦合,因此能进一步提高I/O操作速度。但是分配直接缓冲区的系统开销很大,因此只有在缓冲区较大并长期存在,或者需要经常重用时,才使用这种缓冲区
wrap(byte[] array) 这个缓冲区的数据会存放在byte数组中,bytes数组或buff缓冲区任何一方中数据的改动都会影响另一方。其实ByteBuffer底层本来就有一个bytes数组负责来保存buffer缓冲区中的数据,通过allocate方法系统会帮你构造一个byte数组
wrap(byte[] array,int offset, int length) 在上一个方法的基础上可以指定偏移量和长度,这个offset也就是包装后byteBuffer的position,而length呢就是limit-position的大小,从而我们可以得到limit的位置为length+position(offset)
  • buffer.flip():读写转换的时候可以用得上
    作用:缓冲流写一段数据,将当前位置下标position置为limit,并重置position为0;下一次读操作的时候可以从头开始,只读取到limit位置的数据
// 源码
public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }
  • bufferedReader
    这个类就是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提供读的效率而设计的。
  • StringReader 你要解析字符串的时候,用StringReader包装一下

IO重定向

如果我们开始在显示器创建大量输出,而这些输出滚动得太快以至于无法阅读时,重定向输出就显得极为有用

  • setIn(InputStream)
  • setOut(printStream)
  • setErr(PrintStream)

转换数据

缓冲器容纳得是普通的字节,为了把他们转换成字符,我们要么再输入它们的时候对其进行编码,要么在将其从缓冲器输出时对它们进行解码。可以使用java.nio.charset.Charset类实现这些功能,该类提供了把数据编码成多种不同类型的字符集的工具:
例子:
首先,获取Charset对象需要提供字符集的名称,比如GBK。我们通过Charset类打印JDK支持的所有字符集

// 获取Java支持的全部字符集
SortedMap<String,Charset>  map = Charset.availableCharsets();
for (String alias : map.keySet()){	
    // 输出字符集的别名	
    System.out.println(alias);
}

接下来使用编码器将CharBuffer中的字符序列转换为字节序列ByteBuffer。CharBuffer和ByteBuffer是java NIO中的IO操作类

// 创建简体中文对应的Charset
Charset charset = Charset.forName("GBK");
// 获取charset对象对应的编码器
CharsetDecoder charsetDecoder = charset.newDecoder();
// 创建一个ByteBuffer对象
ByteBuffer byteBuffer = ByteBuffer.allocate(50);
byteBuffer.put("测试数据类型转换".getBytes("GBK"));
byteBuffer.flip();
 
// 将ByteBuffer的数据解码成字符序列
System.out.println(charsetDecoder.decode(byteBuffer));

然后使用解码器将ByteBuffer中的字节序列转换为字符序列CharBuffer(字符串)

// 创建简体中文对应的CharsetCharset 
charset = Charset.forName("GBK");
// 获取charset对象对应的编码器
CharsetDecoder charsetDecoder = charset.newDecoder();
// 创建一个ByteBuffer对象
ByteBuffer byteBuffer = ByteBuffer.allocate(50);
byteBuffer.put("测试数据类型转换".getBytes("GBK"));
byteBuffer.flip(); 

// 将ByteBuffer的数据解码成字符序列
System.out.println(charsetDecoder.decode(byteBuffer));

猜你喜欢

转载自blog.csdn.net/JavaPorter/article/details/108383572
今日推荐