使用ByteBuffer一个一个字节读取数据
2017-06-25 00:00
423 查看
最近在使用Java NIO读取一篇文章(txt),是使用ByteBuffer读取的。代码如下:
RandomAccessFile aFile = new RandomAccessFile("E:/test1.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get());// read 1 byte at a time
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
运行的结果显示是乱码,如:ᄏ₩ワᆲロᆴ¥ᄑユ¦ᄌᄎ│ナ←ロᄋワヒワヒレトᄐモ¥ᆳリロᆴ¥ᄑユ ̄タツ
其实也可以预想到不同编码格式,使用的字节数不一样。我读的文本时UTF-8的,但是UTF-8使用的字节数不一样,最大为4个字节。为了等正确的读出文字(不乱码),查看了一下UTF-8的编码格式:
一个utf8数字占1个字节
一个utf8英文字母占1个字节
少数是汉字每个占用3个字节,多数占用4个字节。
那怎么知道一个汉字占几个字节那,原来可以通过第一个字节中高4中1的个数来确定。包含几个1,就说明占几位。先看一下UTF-8的一点知识:
UTF-8是Unicode的实现方式之一。
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
从网上找个图更直观:
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
既然知道规则,那个就按照规则解析了。修改一下代码:
RandomAccessFile aFile = new RandomAccessFile("E:/test1.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
byte b = buf.get();
int a=b&0xf0;//获取高4位1的个数
int cout=1;
switch (a) {
case 0x80: //0x80 表示1个1
cout=1;
break;
case 0xC0://0x80 表示2个1
cout=2;
break;
case 0xE0://0x80 表示3个1
cout=3;
break;
case 0xF0://0x80 表示4个1
cout=4;
break;
default:
break;
}
byte[] by=new byte[4]; //用于存储一个UTF-8字符
by[0]=b;
for (int i = 2; i <= cout; i++) { //获取一个完整UTF-8字符
by[i]=buf.get();
}
System.out.print(new String(by,0,cout));
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
OK,正确读出文字了,不乱码了。可能不太全面。
RandomAccessFile aFile = new RandomAccessFile("E:/test1.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get());// read 1 byte at a time
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
运行的结果显示是乱码,如:ᄏ₩ワᆲロᆴ¥ᄑユ¦ᄌᄎ│ナ←ロᄋワヒワヒレトᄐモ¥ᆳリロᆴ¥ᄑユ ̄タツ
其实也可以预想到不同编码格式,使用的字节数不一样。我读的文本时UTF-8的,但是UTF-8使用的字节数不一样,最大为4个字节。为了等正确的读出文字(不乱码),查看了一下UTF-8的编码格式:
一个utf8数字占1个字节
一个utf8英文字母占1个字节
少数是汉字每个占用3个字节,多数占用4个字节。
那怎么知道一个汉字占几个字节那,原来可以通过第一个字节中高4中1的个数来确定。包含几个1,就说明占几位。先看一下UTF-8的一点知识:
UTF-8是Unicode的实现方式之一。
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
从网上找个图更直观:
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
既然知道规则,那个就按照规则解析了。修改一下代码:
RandomAccessFile aFile = new RandomAccessFile("E:/test1.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
byte b = buf.get();
int a=b&0xf0;//获取高4位1的个数
int cout=1;
switch (a) {
case 0x80: //0x80 表示1个1
cout=1;
break;
case 0xC0://0x80 表示2个1
cout=2;
break;
case 0xE0://0x80 表示3个1
cout=3;
break;
case 0xF0://0x80 表示4个1
cout=4;
break;
default:
break;
}
byte[] by=new byte[4]; //用于存储一个UTF-8字符
by[0]=b;
for (int i = 2; i <= cout; i++) { //获取一个完整UTF-8字符
by[i]=buf.get();
}
System.out.print(new String(by,0,cout));
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
OK,正确读出文字了,不乱码了。可能不太全面。
相关文章推荐
- Java基础知识强化之IO流笔记27:FileInputStream读取数据一次一个字节数组byte[ ]
- muduo源码分析之使用封装的Buffer读取数据
- 基于流模式的字节byte缓存区 bytebuffer.cs 用于tcp/udp的网络数据高效处理
- 读取ByteBuffer有效的数据
- 使用MappedByteBuffer读取大文件(1G以上)和释放MappedByteBuffer的资源
- 使用byteBuffer的 position和limit方法分段读取字节流
- JAVA基础初探(十三)IO简介、字节流与字符流区别、带缓冲的字节/字符流读取数据、FileReader/FileWriter便捷类、Apache IO库使用说明
- python语言 buffer类型数据的使用 'ascii' codec can't decode byte 0xe5 问题的解决
- 使用NIO的FileChannel和ByteBuffer高效读取文件
- 使用MappedByteBuffer(映射文件)对excel表格进行随机定位和读取
- 【AE】大数据点文件读取生成SHP文件时使用IFeatureBuffer快速提高读取效率
- Java SocketChannel 读取ByteBuffer字节的处理模型
- Java使用ByteBuffer读取大文件
- ASP中使用XMLHTTP读取远程数据3
- 使用Robot循环读取Excel中的数据
- vbs中使用 ADO 读取所有数据均在一行上的文本文件的代码
- 使用SqlDataReader读取数据示例
- 演练:使用 DataGrid Web 控件读取和写入数据
- [教程]使用AODKeycap读取数据
- 在.NET中使用XML、读取XML文件,插入数据到XML文档中。