java编程思想笔记(十三)I/O(三)
程序员文章站
2022-03-15 11:44:47
...
1.转换数据编码
直接获取asCharBuffer() 会乱码,因为拿到的都是没经过编码的字节,解决方法是装入字节前就编码好,或者使用Charset编码,再或者用视图缓冲器放入,再输出
import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.io.*; public class BufferToText { private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { FileChannel fc = new FileOutputStream("data2.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text".getBytes())); fc.close(); fc = new FileInputStream("data2.txt").getChannel(); ByteBuffer buff = ByteBuffer.allocate(BSIZE); fc.read(buff); buff.flip(); // 没编码过会输出乱码 System.out.println(buff.asCharBuffer()); // Charset使用系统默认编码 buff.rewind(); String encoding = System.getProperty("file.encoding"); System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff)); // 或者在wrap前就编码 fc = new FileOutputStream("data2.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE"))); fc.close(); // Now try reading again: fc = new FileInputStream("data2.txt").getChannel(); buff.clear(); fc.read(buff); buff.flip(); System.out.println(buff.asCharBuffer()); // 用视图缓冲器 asCharBuffer()的put方法放入内容 fc = new FileOutputStream("data2.txt").getChannel(); buff = ByteBuffer.allocate(24); // More than needed buff.asCharBuffer().put("Some text"); fc.write(buff); fc.close(); // Read and display: fc = new FileInputStream("data2.txt").getChannel(); buff.clear(); fc.read(buff); buff.flip(); System.out.println(buff.asCharBuffer()); } }
输出结果:
????
Decoded using UTF-8: Some text
Some text
Some text
2.视图缓冲器
视图缓冲器可以让我们通过某个特定的基本数据类型的视窗去查看它的ByteBuffer,ByteBuffer依然是它最底层储存数据的地方,下面是java的7种基本数据类型视图(没boolean)
import java.nio.*;
public class ViewBuffer{
private static final int BSIZE = 1024;
public static void main(String[] args){
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
int i = 0;
//检查字节缓冲器的内容是否为0
while(i++ < bb.limit()){
if(bb.get() != 0){
System.out.println(“nonzero”);
}
System.out.println(“i = ” + i);
//回到字节缓冲器开始处
bb.rewind();
}
//创建字节缓冲区视图,作为char缓冲
bb.asCharBuffer().put(“Hello!”);
char c;
while((c = bb.getChar)) != 0){
System.out.println(c + “ ”);
}
bb.rewind();
//创建字节缓冲区视图,作为short缓冲
bb.asShortBuffer().put((Short)12390);
System.out.println(bb.getShort());
bb.rewind();
//创建字节缓冲区视图,作为int缓冲
bb.asIntBuffer().put(99471142);
System.out.println(bb.getInt());
bb.rewind();
//创建字节缓冲区视图,作为long缓冲
bb.asLongBuffer().put(99471142);
System.out.println(bb.getLong());
bb.rewind();
//创建字节缓冲区视图,作为float缓冲
bb.asFloatBuffer().put(99471142);
System.out.println(bb.getFloat());
bb.rewind();
//创建字节缓冲区视图,作为double缓冲
bb.asDoubleBuffer().put(99471142);
System.out.println(bb.getDouble());
}
}
输出结果:
i = 1025
H e l l o !
12390
99471142
99471142
9.9471142E7
9.9471142E7
3.缓冲器的细节
通道和缓冲器的细节
由内容和4个索引组合而成
mark(标记):使缓冲区能够记住一个位置并在之后将其返回。并非总需要定义标记,但在定义标记时,不能将其定义为负数,且不能大于其位置。
position(当前位置):是缓冲区下一个要读取或写入元素的索引,位置不能为负,且不能大于其限制。limit(限制 指向最后一个位置):是第一个不应该读取或写入的元素的索引,限制不能为负,且不能大于其容量。
capacity(容量):是缓冲区所包含的元素数量,不能为负,且不能更改。
缓冲区索引遵循以下不变公式:
0 <= 标记 <= 位置 <= 限制 <= 容量
0 <= 标记 <= 位置 <= 限制 <= 容量
通过这些索引,缓冲区可以高效的访问和操作缓冲区中的内容数据,新创建的缓冲区总有一个0位置和一个未定义的标记,初始限制可以为0,也可以为其他值,取决于缓冲区类型和构建方式。
缓冲区的以下方法可以查询,设置和充值缓冲区的索引:
(1).capacity()方法:
返回此缓冲区的容量。
(2).clear()方法:
清除此缓冲区,将缓冲区位置设置为0,将缓冲区限制设置为容量,并丢弃标记。
(3).flip()方法:
反转此缓冲区,首先将限制设置为当前位置,然后将位置设置为0,如果已定义了标记,则丢弃该标记。
(4).limit()方法:
返回此缓冲区的限制。
(5).limit(int lim)方法:
设置此缓冲区的限制,如果位置大于新的限制,则将位置设置为新的限制,如果标记已定义且大于新限制,则丢弃该标记。
(6).mark()方法:
在此缓冲区的位置设置标记。
(7).position()方法:
返回此缓冲区的位置。
(8).position(int pos)方法:
设置此缓冲区的位置,如果标记已定义且大于新的位置,则丢弃该标记。
(9).remaining()方法:
返回当前位置与限制之间的元素个数,即limit-position。
(10).hasRemaining()方法:
判断在当前位置和限制之间是否有元素。
(11)rewind()方法:
当前位置position调到到起始位置.
(12)reset()方法:
当前位置position调到mark标记的位置.