java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx

上传人:b****2 文档编号:5829301 上传时间:2023-05-05 格式:DOCX 页数:32 大小:49.24KB
下载 相关 举报
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第1页
第1页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第2页
第2页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第3页
第3页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第4页
第4页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第5页
第5页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第6页
第6页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第7页
第7页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第8页
第8页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第9页
第9页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第10页
第10页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第11页
第11页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第12页
第12页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第13页
第13页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第14页
第14页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第15页
第15页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第16页
第16页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第17页
第17页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第18页
第18页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第19页
第19页 / 共32页
java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx_第20页
第20页 / 共32页
亲,该文档总共32页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx

《java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx》由会员分享,可在线阅读,更多相关《java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx(32页珍藏版)》请在冰点文库上搜索。

java io系列14之 DataInputStream数据输入流的认知源码和示例Word文档格式.docx

DataInputStream中比较难以理解的函数就只有readUTF(DataInputin);

下面,对这个函数进行详细的介绍,其它的函数请参考源码中的注释。

readUTF(DataInputin)源码如下:

1publicfinalstaticStringreadUTF(DataInputin)throwsIOException{

2//从“数据输入流”中读取“无符号的short类型”的值:

3//注意:

UTF-8输入流的前2个字节是数据的长度

4intutflen=in.readUnsignedShort();

5byte[]bytearr=null;

6char[]chararr=null;

7

8//如果in本身是“数据输入流”,

9//则,设置字节数组bytearr="

数据输入流"

的成员bytearr

10//设置字符数组chararr="

的成员chararr

11//否则的话,新建数组bytearr和chararr

12if(ininstanceofDataInputStream){

13DataInputStreamdis=(DataInputStream)in;

14if(dis.bytearr.length<

utflen){

15dis.bytearr=newbyte[utflen*2];

16dis.chararr=newchar[utflen*2];

17}

18chararr=dis.chararr;

19bytearr=dis.bytearr;

20}else{

21bytearr=newbyte[utflen];

22chararr=newchar[utflen];

23}

24

25intc,char2,char3;

26intcount=0;

27intchararr_count=0;

28

29//从“数据输入流”中读取数据并存储到字节数组bytearr中;

从bytearr的位置0开始存储,存储长度为utflen。

30//注意,这里是存储到字节数组!

而且读取的是全部的数据。

31in.readFully(bytearr,0,utflen);

32

33//将“字节数组bytearr”中的数据拷贝到“字符数组chararr”中

34//注意:

这里相当于“预处理的输入流中单字节的符号”,因为UTF-8是1-4个字节可变的。

35while(count<

utflen){

36//将每个字节转换成int值

37c=(int)bytearr[count]&

0xff;

38//UTF-8的每个字节的值都不会超过127;

所以,超过127,则退出。

39if(c>

127)break;

40count++;

41//将c保存到“字符数组chararr”中

42chararr[chararr_count++]=(char)c;

43}

44

45//处理完输入流中单字节的符号之后,接下来我们继续处理。

46while(count<

47//下面语句执行了2步操作。

48//(01)将字节由“byte类型”转换成“int类型”。

49//例如,“11001010”转换成int之后,是“00000000000000000000000011001010”

50//(02)将“int类型”的数据左移4位

51//例如,“00000000000000000000000011001010”左移4位之后,变成“00000000000000000000000000001100”

52c=(int)bytearr[count]&

53switch(c>

>

4){

54//若UTF-8是单字节,即bytearr[count]对应是“0xxxxxxx”形式;

55//则bytearr[count]对应的int类型的c的取值范围是0-7。

56case0:

case1:

case2:

case3:

case4:

case5:

case6:

case7:

57/*0xxxxxxx*/

58count++;

59chararr[chararr_count++]=(char)c;

60break;

61

62//若UTF-8是双字节,即bytearr[count]对应是“110xxxxx10xxxxxx”形式中的第一个,即“110xxxxx”

63//则bytearr[count]对应的int类型的c的取值范围是12-13。

64case12:

case13:

65/*110xxxxx10xxxxxx*/

66count+=2;

67if(count>

utflen)

68thrownewUTFDataFormatException(

69"

malformedinput:

partialcharacteratend"

);

70char2=(int)bytearr[count-1];

71if((char2&

0xC0)!

=0x80)

72thrownewUTFDataFormatException(

73"

malformedinputaroundbyte"

+count);

74chararr[chararr_count++]=(char)(((c&

0x1F)<

<

6)|

75(char2&

0x3F));

76break;

77

78//若UTF-8是三字节,即bytearr[count]对应是“1110xxxx10xxxxxx10xxxxxx”形式中的第一个,即“1110xxxx”

79//则bytearr[count]对应的int类型的c的取值是14。

80case14:

81/*1110xxxx10xxxxxx10xxxxxx*/

82count+=3;

83if(count>

84thrownewUTFDataFormatException(

85"

86char2=(int)bytearr[count-2];

87char3=(int)bytearr[count-1];

88if(((char2&

=0x80)||((char3&

=0x80))

89thrownewUTFDataFormatException(

90"

+(count-1));

91chararr[chararr_count++]=(char)(((c&

0x0F)<

12)|

92((char2&

0x3F)<

93((char3&

0));

94break;

95

96//若UTF-8是四字节,即bytearr[count]对应是“11110xxx10xxxxxx10xxxxxx10xxxxxx”形式中的第一个,即“11110xxx”

97//则bytearr[count]对应的int类型的c的取值是15

98default:

99/*10xxxxxx,1111xxxx*/

100thrownewUTFDataFormatException(

101"

102}

103}

104//Thenumberofcharsproducedmaybelessthanutflen

105returnnewString(chararr,0,chararr_count);

106}

(01)readUTF()的作用,是从输入流中读取UTF-8编码的数据,并以String字符串的形式返回。

(02)知道了readUTF()的作用之后,下面开始介绍readUTF()的流程:

第1步,读取出输入流中的UTF-8数据的长度。

代码如下:

intutflen=in.readUnsignedShort();

UTF-8数据的长度包含在它的前两个字节当中;

我们通过readUnsignedShort()读取出前两个字节对应的正整数就是UTF-8数据的长度。

第2步,创建2个数组:

字节数组bytearr和字符数组chararr。

1if(ininstanceofDataInputStream){

2DataInputStreamdis=(DataInputStream)in;

3if(dis.bytearr.length<

4dis.bytearr=newbyte[utflen*2];

5dis.chararr=newchar[utflen*2];

6}

7chararr=dis.chararr;

8bytearr=dis.bytearr;

9}else{

10bytearr=newbyte[utflen];

11chararr=newchar[utflen];

12}

首先,判断该输入流本身是不是DataInputStream,即数据输入流;

若是的话,

则,设置字节数组bytearr="

 

设置字符数组chararr="

否则的话,新建数组bytearr和chararr。

第3步,将UTF-8数据全部读取到“字节数组bytearr”中。

in.readFully(bytearr,0,utflen);

注意:

这里是存储到字节数组,而不是字符数组!

第4步,对UTF-8中的单字节数据进行预处理。

1while(count<

2//将每个字节转换成int值

3c=(int)bytearr[count]&

4//UTF-8的单字节数据的值都不会超过127;

5if(c>

6count++;

7//将c保存到“字符数组chararr”中

8chararr[chararr_count++]=(char)c;

9}

UTF-8的数据是变长的,可以是1-4个字节;

在readUTF()中,我们最终是将全部的UTF-8数据保存到“字符数组(而不是字节数组)”中,再将其转换为String字符串。

由于UTF-8的单字节和ASCII相同,所以这里就将它们进行预处理,直接保存到“字符数组chararr”中。

对于其它的UTF-8数据,则在后面进行处理。

第5步,对“第4步预处理”之后的数据,接着进行处理。

//处理完输入流中单字节的符号之后,接下来我们继续处理。

while(count<

//下面语句执行了2步操作。

//(01)将字节由“byte类型”转换成“int类型”。

//例如,“11001010”转换成int之后,是“00000000000000000000000011001010”

//(02)将“int类型”的数据左移4位

//例如,“00000000000000000000000011001010”左移4位之后,变成“00000000000000000000000000001100”

c=(int)bytearr[count]&

switch(c>

//若UTF-8是单字节,即bytearr[count]对应是“0xxxxxxx”形式;

//则bytearr[count]对应的int类型的c的取值范围是0-7。

case0:

/*0xxxxxxx*/

count++;

chararr[chararr_count++]=(char)c;

break;

//若UTF-8是双字节,即bytearr[count]对应是“110xxxxx10xxxxxx”形式中的第一个,即“110xxxxx”

//则bytearr[count]对应的int类型的c的取值范围是12-13。

case12:

/*110xxxxx10xxxxxx*/

count+=2;

if(count>

thrownewUTFDataFormatException(

"

char2=(int)bytearr[count-1];

if((char2&

chararr[chararr_count++]=(char)(((c&

(char2&

//若UTF-8是三字节,即bytearr[count]对应是“1110xxxx10xxxxxx10xxxxxx”形式中的第一个,即“1110xxxx”

//则bytearr[count]对应的int类型的c的取值是14。

case14:

/*1110xxxx10xxxxxx10xxxxxx*/

count+=3;

char2=(int)bytearr[count-2];

char3=(int)bytearr[count-1];

if(((char2&

((char2&

((char3&

//若UTF-8是四字节,即bytearr[count]对应是“11110xxx10xxxxxx10xxxxxx10xxxxxx”形式中的第一个,即“11110xxx”

//则bytearr[count]对应的int类型的c的取值是15

default:

/*10xxxxxx,1111xxxx*/

}

}

(a)我们将下面的两条语句一起进行说明

c=(int)bytearr[count]&

switch(c>

4){...}

首先,我们必须要理解为什么要这么做(执行上面2条语句)呢?

原因很简单,这么做的目的就是为了区分UTF-8数据是几位的;

因为UTF-8的数据是1~4字节不等。

我们先看看UTF-8在1~4位情况下的格式。

--------------------+---------------------------------------------

1字节UTF-8的通用格式|0xxxxxxx

2字节UTF-8的通用格式|110xxxxx10xxxxxx

3字节UTF-8的通用格式|1110xxxx10xxxxxx10xxxxxx

4字节UTF-8的通用格式|11110xxx10xxxxxx10xxxxxx10xxxxxx

执行c=(int)bytearr[count]&

和c>

4这2项操作之后,上面的数据变成

1字节UTF-8的变换后对应的int类型值|00000000000000000000000000000xxx(范围是0~7)

2字节UTF-8的变换后对应的int类型值|0000000000000000000000000000110x(范围是12~13)

3字节UTF-8的变换后对应的int类型值|00000000000000000000000000001110(范围是14)

4字节UTF-8的变换后对应的int类型值|00000000000000000000000000001111(范围是15)

为什么会是这样呢?

我们以“2字节UTF-8的通用格式”来说明。

它的通用格式是“110xxxxx10xxxxxx”,我们在操作时,只会操作第1个字节,即只会操作“110xxxxx”

(a.1)在执行c=(int)bytearr[count]&

时,首先将bytearr[count]转换成int。

“110xxxxx”

转成int类型之后,变成

“111111111111111111111111110xxxxx”

因为“110xxxxx”是负数(第1为是1),所以转换成int类型时多出来的位补1。

(a.2)接着c=(int)bytearr[count]&

中,会将“转换成int类型后的bytearr[count]”与“0xff”进行逻辑与(即&

)操作。

结果如下:

“000000000000000000000000110xxxxx”

(a.3)执行c>

4时,会将上面的结果左移4位。

得到的结果如下:

“0000000000000000000000000000110x”

(b)上面的理解之后,swicth(c>

4){...}其中的省略号部分就相当容易理解了。

我们还是以“2字节UTF-8的通用格式”来说明。

它会执行case12和case13;

源码如下:

count+=2;

if(count>

char2=(int)bytearr[count-1];

if((char2&

chararr[chararr_count++]=(char)(((c&

6)|(char2&

(b.1)由于这种情况对应的UTF-8数据是“2字节”的,因此,执行count+2;

直接跳

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2