DataInputStream 源码分析

来源:互联网 发布:java实现订单管理系统 编辑:程序博客网 时间:2024/05/18 23:52

转自:http://www.fengfly.com/plus/view-214064-1.html

DataInputStream 是数据输入流。它继承于FilterInputStream。
DataInputStream 是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。应用程序可以使用DataOutputStream(数据输出流)写入由DataInputStream(数据输入流)读取的数据。

public class DataInputStream extends FilterInputStream implements DataInput {       // 构造函数。      public DataInputStream(InputStream in) {          super(in);      }       private byte bytearr[] = new byte[80];      private char chararr[] = new char[80];       // 从“数据输入流”中读取一个字节      public final int read(byte b[]) throws IOException {          return in.read(b, 0, b.length);      }       // 从“数据输入流”中读取数据并存储到字节数组b中。      // off是字节数组b中开始存储元素的起始位置。      // len是读取字节的个数。      public final int read(byte b[], int off, int len) throws IOException {          return in.read(b, off, len);      }       // 从“数据输入流”中读取数据并填满字节数组b中;没有填满数组b则一直读取,直到填满位置。      // 从字节数组b的位置0开始存储,并且读取的字节个数等于b的长度。      public final void readFully(byte b[]) throws IOException {          readFully(b, 0, b.length);      }       // 从“数据输入流”中读取数据并存储到字节数组b中;若没读取len个字节,直到一直读取直到读取完len个字节为止。      public final void readFully(byte b[], int off, int len) throws IOException {          if (len < 0)              throw new IndexOutOfBoundsException();          int n = 0;          while (n < len) {              int count = in.read(b, off + n, len - n);              if (count < 0)                  throw new EOFException();              n += count;          }      }       // 跳过n个字节      public final int skipBytes(int n) throws IOException {          int total = 0;          int cur = 0;           while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {              total += cur;          }           return total;      }       // 从“数据输入流”中读取boolean类型的值      public final boolean readBoolean() throws IOException {          int ch = in.read();          if (ch < 0)              throw new EOFException();          return (ch != 0);      }       // 从“数据输入流”中读取Byte类型的值      public final byte readByte() throws IOException {          int ch = in.read();          if (ch < 0)              throw new EOFException();          return (byte)(ch);      }       // 从“数据输入流”中读取“无符号的Byte类型”的值,即读取值为正数的byte值      public final int readUnsignedByte() throws IOException {          int ch = in.read();          if (ch < 0)              throw new EOFException();          return ch;      }       // 从“数据输入流”中读取“short类型”的值      public final short readShort() throws IOException {          int ch1 = in.read();          int ch2 = in.read();          if ((ch1 | ch2) < 0)              throw new EOFException();          return (short)((ch1 << 8) + (ch2 << 0));      }       // 从“数据输入流”中读取“无符号的short类型”的值      public final int readUnsignedShort() throws IOException {          int ch1 = in.read();          int ch2 = in.read();          if ((ch1 | ch2) < 0)              throw new EOFException();          return (ch1 << 8) + (ch2 << 0);      }       // 从“数据输入流”中读取“char类型”的值      public final char readChar() throws IOException {          int ch1 = in.read();          int ch2 = in.read();          if ((ch1 | ch2) < 0)              throw new EOFException();          return (char)((ch1 << 8) + (ch2 << 0));      }       // 从“数据输入流”中读取“int类型”的值      public final int readInt() throws IOException {          int ch1 = in.read();          int ch2 = in.read();          int ch3 = in.read();          int ch4 = in.read();          if ((ch1 | ch2 | ch3 | ch4) < 0)              throw new EOFException();          return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));      }       private byte readBuffer[] = new byte[8];       // 从“数据输入流”中读取“long类型”的值      public final long readLong() throws IOException {          readFully(readBuffer, 0, 8);          return (((long)readBuffer[0] << 56) +                  ((long)(readBuffer[1] & 255) << 48) +                  ((long)(readBuffer[2] & 255) << 40) +                  ((long)(readBuffer[3] & 255) << 32) +                  ((long)(readBuffer[4] & 255) << 24) +                  ((readBuffer[5] & 255) << 16) +                  ((readBuffer[6] & 255) <<  8) +                  ((readBuffer[7] & 255) <<  0));      }       // 从“数据输入流”中读取“float类型”的值      public final float readFloat() throws IOException {          return Float.intBitsToFloat(readInt());      }       // 从“数据输入流”中读取“double类型”的值      public final double readDouble() throws IOException {          return Double.longBitsToDouble(readLong());      }       private char lineBuffer[];       @Deprecated     public final String readLine() throws IOException {          char buf[] = lineBuffer;           if (buf == null) {              buf = lineBuffer = new char[128];          }           int room = buf.length;          int offset = 0;          int c;   loop:   while (true) {              switch (c = in.read()) {                case -1:                case '\n':                  break loop;                 case '\r':                  int c2 = in.read();                  if ((c2 != '\n') && (c2 != -1)) {                      if (!(in instanceof PushbackInputStream)) {                          this.in = new PushbackInputStream(in);                      }                      ((PushbackInputStream)in).unread(c2);                  }                  break loop;                 default:                  if (--room < 0) {                      buf = new char[offset + 128];                      room = buf.length - offset - 1;                      System.arraycopy(lineBuffer, 0, buf, 0, offset);                      lineBuffer = buf;                  }                  buf[offset++] = (char) c;                  break;              }          }          if ((c == -1) && (offset == 0)) {              return null;          }          return String.copyValueOf(buf, 0, offset);      }       // 从“数据输入流”中读取“UTF类型”的值      public final String readUTF() throws IOException {          return readUTF(this);      }       public final static String readUTF(DataInput in) throws IOException {          // 从“数据输入流”中读取“无符号的short类型”的值:          // 注意:UTF-8输入流的前2个字节是数据的长度          int utflen = in.readUnsignedShort();          byte[] bytearr = null;          char[] chararr = null;           // 如果in本身是“数据输入流”,          // 则,设置字节数组bytearr = "数据输入流"的成员bytearr          //     设置字符数组chararr = "数据输入流"的成员chararr          // 否则的话,新建数组bytearr和chararr          if (in instanceof DataInputStream) {              DataInputStream dis = (DataInputStream)in;              if (dis.bytearr.length < utflen){                  dis.bytearr = new byte[utflen*2];                  dis.chararr = new char[utflen*2];              }              chararr = dis.chararr;              bytearr = dis.bytearr;          } else {              bytearr = new byte[utflen];              chararr = new char[utflen];          }           int c, char2, char3;          int count = 0;          int chararr_count=0;           // 从“数据输入流”中读取数据并存储到字节数组bytearr中;从bytearr的位置0开始存储,存储长度为utflen。          // 注意,这里是存储到字节数组!而且读取的是全部的数据。          in.readFully(bytearr, 0, utflen);           // 将“字节数组bytearr”中的数据 拷贝到 “字符数组chararr”中          // 注意:这里相当于“预处理的输入流中单字节的符号”,因为UTF-8是1-4个字节可变的。          while (count < utflen) {              // 将每个字节转换成int值              c = (int) bytearr[count] & 0xff;              // UTF-8的单字节数据的值都不会超过127;所以,超过127,则退出。              if (c > 127) break;              count++;              // 将c保存到“字符数组chararr”中              chararr[chararr_count++]=(char)c;          }           // 处理完输入流中单字节的符号之后,接下来我们继续处理。          while (count < utflen) {              // 下面语句执行了2步操作。              // (01) 将字节由 “byte类型” 转换成 “int类型”。              //      例如, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”              // (02) 将 “int类型” 的数据左移4位              //      例如, “00000000 00000000 00000000 11001010” 左移4位之后,变成 “00000000 00000000 00000000 00001100”              c = (int) bytearr[count] & 0xff;              switch (c >> 4) {                  // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;                  // 则 bytearr[count] 对应的int类型的c的取值范围是 0-7。                  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:                      /* 0xxxxxxx*/                     count++;                      chararr[chararr_count++]=(char)c;                      break;                   // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”                  // 则 bytearr[count] 对应的int类型的c的取值范围是 12-13。                  case 12: case 13:                      /* 110x xxxx   10xx xxxx*/                     count += 2;                      if (count > utflen)                          throw new UTFDataFormatException(                              "malformed input: partial character at end");                      char2 = (int) bytearr[count-1];                      if ((char2 & 0xC0) != 0x80)                          throw new UTFDataFormatException(                              "malformed input around byte " + count);                      chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |                                                      (char2 & 0x3F));                      break;                   // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”                  // 则 bytearr[count] 对应的int类型的c的取值是14 。                  case 14:                      /* 1110 xxxx  10xx xxxx  10xx xxxx */                     count += 3;                      if (count > utflen)                          throw new UTFDataFormatException(                              "malformed input: partial character at end");                      char2 = (int) bytearr[count-2];                      char3 = (int) bytearr[count-1];                      if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))                          throw new UTFDataFormatException(                              "malformed input around byte " + (count-1));                      chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |                                                      ((char2 & 0x3F) << 6)  |                                                      ((char3 & 0x3F) << 0));                      break;                   // 若 UTF-8 是四字节,即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“11110xxx”                  // 则 bytearr[count] 对应的int类型的c的取值是15                   default:                      /* 10xx xxxx,  1111 xxxx */                     throw new UTFDataFormatException(                          "malformed input around byte " + count);              }          }          // The number of chars produced may be less than utflen          return new String(chararr, 0, chararr_count);      }  } 
说明:

DataInputStream 的作用就是“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。”
DataInputStream 中比较难以理解的函数就只有 readUTF(DataInput in);下面,对这个函数进行详细的介绍,其它的函数请参考源码中的注释。

public final static String readUTF(DataInput in) throws IOException {      // 从“数据输入流”中读取“无符号的short类型”的值:      // 注意:UTF-8输入流的前2个字节是数据的长度      int utflen = in.readUnsignedShort();      byte[] bytearr = null;      char[] chararr = null;       // 如果in本身是“数据输入流”,      // 则,设置字节数组bytearr = "数据输入流"的成员bytearr      //     设置字符数组chararr = "数据输入流"的成员chararr      // 否则的话,新建数组bytearr和chararr      if (in instanceof DataInputStream) {          DataInputStream dis = (DataInputStream)in;          if (dis.bytearr.length < utflen){              dis.bytearr = new byte[utflen*2];              dis.chararr = new char[utflen*2];          }          chararr = dis.chararr;          bytearr = dis.bytearr;      } else {          bytearr = new byte[utflen];          chararr = new char[utflen];      }       int c, char2, char3;      int count = 0;      int chararr_count=0;       // 从“数据输入流”中读取数据并存储到字节数组bytearr中;从bytearr的位置0开始存储,存储长度为utflen。      // 注意,这里是存储到字节数组!而且读取的是全部的数据。      in.readFully(bytearr, 0, utflen);       // 将“字节数组bytearr”中的数据 拷贝到 “字符数组chararr”中      // 注意:这里相当于“预处理的输入流中单字节的符号”,因为UTF-8是1-4个字节可变的。      while (count < utflen) {          // 将每个字节转换成int值          c = (int) bytearr[count] & 0xff;          // UTF-8的每个字节的值都不会超过127;所以,超过127,则退出。          if (c > 127) break;          count++;          // 将c保存到“字符数组chararr”中          chararr[chararr_count++]=(char)c;      }       // 处理完输入流中单字节的符号之后,接下来我们继续处理。      while (count < utflen) {          // 下面语句执行了2步操作。          // (01) 将字节由 “byte类型” 转换成 “int类型”。          //      例如, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”          // (02) 将 “int类型” 的数据左移4位          //      例如, “00000000 00000000 00000000 11001010” 左移4位之后,变成 “00000000 00000000 00000000 00001100”          c = (int) bytearr[count] & 0xff;          switch (c >> 4) {              // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;              // 则 bytearr[count] 对应的int类型的c的取值范围是 0-7。              case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:                  /* 0xxxxxxx*/                 count++;                  chararr[chararr_count++]=(char)c;                  break;               // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”              // 则 bytearr[count] 对应的int类型的c的取值范围是 12-13。              case 12: case 13:                  /* 110x xxxx   10xx xxxx*/                 count += 2;                  if (count > utflen)                      throw new UTFDataFormatException(                          "malformed input: partial character at end");                  char2 = (int) bytearr[count-1];                  if ((char2 & 0xC0) != 0x80)                      throw new UTFDataFormatException(                          "malformed input around byte " + count);                  chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |                                                  (char2 & 0x3F));                  break;               // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”              // 则 bytearr[count] 对应的int类型的c的取值是14 。              case 14:                  /* 1110 xxxx  10xx xxxx  10xx xxxx */                 count += 3;                  if (count > utflen)                      throw new UTFDataFormatException(                          "malformed input: partial character at end");                  char2 = (int) bytearr[count-2];                  char3 = (int) bytearr[count-1];                  if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))                      throw new UTFDataFormatException(                          "malformed input around byte " + (count-1));                  chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |                                                  ((char2 & 0x3F) << 6)  |                                                  ((char3 & 0x3F) << 0));                  break;               // 若 UTF-8 是四字节,即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“11110xxx”              // 则 bytearr[count] 对应的int类型的c的取值是15               default:                  /* 10xx xxxx,  1111 xxxx */                 throw new UTFDataFormatException(                      "malformed input around byte " + count);          }      }      // The number of chars produced may be less than utflen      return new String(chararr, 0, chararr_count);  } 

说明:

(01) readUTF()的作用,是从输入流中读取UTF-8编码的数据,并以String字符串的形式返回。
(02) 知道了readUTF()的作用之后,下面开始介绍readUTF()的流程:

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

  1. int utflen = in.readUnsignedShort(); 

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

第2步,创建2个数组:字节数组bytearr 和 字符数组chararr。代码如下:

  1. if (in instanceof DataInputStream) {  
  2.     DataInputStream dis = (DataInputStream)in;  
  3.     if (dis.bytearr.length < utflen){  
  4.         dis.bytearr = new byte[utflen*2];  
  5.         dis.chararr = new char[utflen*2];  
  6.     }  
  7.     chararr = dis.chararr;  
  8.     bytearr = dis.bytearr;  
  9. else {  
  10.     bytearr = new byte[utflen];  
  11.     chararr = new char[utflen];  

首先,判断该输入流本身是不是DataInputStream,即数据输入流;若是的话,
则,设置字节数组bytearr = "数据输入流"的成员bytearr
      设置字符数组chararr = "数据输入流"的成员chararr
否则的话,新建数组bytearr和chararr。

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

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

注意: 这里是存储到字节数组,而不是字符数组!而且读取的是全部的数据。

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

  1. while (count < utflen) {  
  2.     // 将每个字节转换成int值  
  3.     c = (int) bytearr[count] & 0xff;  
  4.     // UTF-8的单字节数据的值都不会超过127;所以,超过127,则退出。  
  5.     if (c > 127break;  
  6.     count++;  
  7.     // 将c保存到“字符数组chararr”中  
  8.     chararr[chararr_count++]=(char)c;  

UTF-8的数据是变长的,可以是1-4个字节;在readUTF()中,我们最终是将全部的UTF-8数据保存到“字符数组(而不是字节数组)”中,再将其转换为String字符串。
由于UTF-8的单字节和ASCII相同,所以这里就将它们进行预处理,直接保存到“字符数组chararr”中。对于其它的UTF-8数据,则在后面进行处理。


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

  1. // 处理完输入流中单字节的符号之后,接下来我们继续处理。  
  2. while (count < utflen) {  
  3.     // 下面语句执行了2步操作。  
  4.     // (01) 将字节由 “byte类型” 转换成 “int类型”。  
  5.     //      例如, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”  
  6.     // (02) 将 “int类型” 的数据左移4位  
  7.     //      例如, “00000000 00000000 00000000 11001010” 左移4位之后,变成 “00000000 00000000 00000000 00001100”  
  8.     c = (int) bytearr[count] & 0xff;  
  9.     switch (c >> 4) {  
  10.         // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;  
  11.         // 则 bytearr[count] 对应的int类型的c的取值范围是 0-7。  
  12.         case 0case 1case 2case 3case 4case 5case 6case 7:  
  13.             /* 0xxxxxxx*/ 
  14.             count++;  
  15.             chararr[chararr_count++]=(char)c;  
  16.             break;  
  17.  
  18.         // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”  
  19.         // 则 bytearr[count] 对应的int类型的c的取值范围是 12-13。  
  20.         case 12case 13:  
  21.             /* 110x xxxx   10xx xxxx*/ 
  22.             count += 2;  
  23.             if (count > utflen)  
  24.                 throw new UTFDataFormatException(  
  25.                     "malformed input: partial character at end");  
  26.             char2 = (int) bytearr[count-1];  
  27.             if ((char2 & 0xC0) != 0x80)  
  28.                 throw new UTFDataFormatException(  
  29.                     "malformed input around byte " + count);  
  30.             chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |  
  31.                                             (char2 & 0x3F));  
  32.             break;  
  33.  
  34.         // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”  
  35.         // 则 bytearr[count] 对应的int类型的c的取值是14 。  
  36.         case 14:  
  37.             /* 1110 xxxx  10xx xxxx  10xx xxxx */ 
  38.             count += 3;  
  39.             if (count > utflen)  
  40.                 throw new UTFDataFormatException(  
  41.                     "malformed input: partial character at end");  
  42.             char2 = (int) bytearr[count-2];  
  43.             char3 = (int) bytearr[count-1];  
  44.             if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))  
  45.                 throw new UTFDataFormatException(  
  46.                     "malformed input around byte " + (count-1));  
  47.             chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |  
  48.                                             ((char2 & 0x3F) << 6)  |  
  49.                                             ((char3 & 0x3F) << 0));  
  50.             break;  
  51.  
  52.         // 若 UTF-8 是四字节,即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“11110xxx”  
  53.         // 则 bytearr[count] 对应的int类型的c的取值是15   
  54.         default:  
  55.             /* 10xx xxxx,  1111 xxxx */ 
  56.             throw new UTFDataFormatException(  
  57.                 "malformed input around byte " + count);  
  58.     }  

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

  1. c = (int) bytearr[count] & 0xff;  
  2. switch (c >> 4) { ... }  

首先,我们必须要理解 为什么要这么做(执行上面2条语句)呢?
原因很简单,这么做的目的就是为了区分UTF-8数据是几位的;因为UTF-8的数据是1~4字节不等。

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

--------------------+---------------------------------------------1字节 UTF-8的通用格式  | 0xxxxxxx2字节 UTF-8的通用格式  | 110xxxxx 10xxxxxx3字节 UTF-8的通用格式  | 1110xxxx 10xxxxxx 10xxxxxx4字节 UTF-8的通用格式  | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

执行 c = (int) bytearr[count] & 0xff; 和 c>>4 这2项操作之后,上面的数据变成

--------------------+---------------------------------------------1字节 UTF-8的变换后对应的int类型值  | 00000000 00000000 00000000 00000xxx    (范围是0~7) 2字节 UTF-8的变换后对应的int类型值  | 00000000 00000000 00000000 0000110x    (范围是12~13) 3字节 UTF-8的变换后对应的int类型值  | 00000000 00000000 00000000 00001110    (范围是14) 4字节 UTF-8的变换后对应的int类型值  | 00000000 00000000 00000000 00001111    (范围是15) 

为什么会是这样呢?
我们以“2字节 UTF-8的通用格式”来说明。
它的通用格式是 “110xxxxx 10xxxxxx”,我们在操作时,只会操作第1个字节,即只会操作“110xxxxx
(a.1) 在执行 c = (int) bytearr[count] & 0xff; 时,首先将 bytearr[count] 转换成int。

  1. “110xxxxx” 

转成int类型之后,变成

  1. “11111111 11111111 11111111 110xxxxx” 

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

(a.2) 接着 c = (int) bytearr[count] & 0xff; 中,会将 “转换成int类型后的bytearr[count]” 与 “0xff”进行 逻辑与(即&) 操作。结果如下:

  1. 00000000 00000000 00000000 110xxxxx” 

(a.3) 执行 c>>4 时,会将上面的结果左移4位。得到的结果如下:

  1. 00000000 00000000 00000000 0000110x” 

(b) 上面的理解之后,swicth (c>>4) { ... } 其中的省略号部分就相当容易理解了。
我们还是以“2字节 UTF-8的通用格式”来说明。
它会执行 case 12 和 case 13;源码如下:

  1. count += 2;  
  2. if (count > utflen)  
  3.     throw new UTFDataFormatException(  
  4.         "malformed input: partial character at end");  
  5. char2 = (int) bytearr[count-1];  
  6. if ((char2 & 0xC0) != 0x80)  
  7.     throw new UTFDataFormatException(  
  8.         "malformed input around byte " + count);  
  9. chararr[chararr_count++]=(char)(((c & 0x1F) << 6) | (char2 & 0x3F));  
(b.1) 由于这种情况对应的UTF-8数据是“2字节”的,因此,执行count+2;直接跳过2个字节。
(b.2) 由于chararr的元素是字符类型,而一个字符正好占2个字节;因为正好将(((c & 0x1F) << 6) | (char2 & 0x3F)); 的结果转换成char,然后保存在chararr数组中。

第6步,将字符数组转换成String字符串,并返回。代码如下:

  1. return new String(chararr, 0, chararr_count); 

示例:

public class DataInputStreamTest {       private static final int LEN = 5;       public static void main(String[] args) {          // 测试DataOutputStream,将数据写入到输出流中。          testDataOutputStream() ;          // 测试DataInputStream,从上面的输出流结果中读取数据。          testDataInputStream() ;      }       /**       * DataOutputStream的API测试函数       */     private static void testDataOutputStream() {           try {              File file = new File("file.txt");              DataOutputStream out =                    new DataOutputStream(                        new FileOutputStream(file));               out.writeBoolean(true);              out.writeByte((byte)0x41);              out.writeChar((char)0x4243);              out.writeShort((short)0x4445);              out.writeInt(0x12345678);              out.writeLong(0x0FEDCBA987654321L);               out.writeUTF("abcdefghijklmnopqrstuvwxyz严12");               out.close();         } catch (FileNotFoundException e) {             e.printStackTrace();         } catch (SecurityException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }      }      /**       * DataInputStream的API测试函数       */     private static void testDataInputStream() {           try {              File file = new File("file.txt");              DataInputStream in =                    new DataInputStream(                        new FileInputStream(file));               System.out.printf("byteToHexString(0x8F):0x%s\n", byteToHexString((byte)0x8F));              System.out.printf("charToHexString(0x8FCF):0x%s\n", charToHexString((char)0x8FCF));               System.out.printf("readBoolean():%s\n", in.readBoolean());              System.out.printf("readByte():0x%s\n", byteToHexString(in.readByte()));              System.out.printf("readChar():0x%s\n", charToHexString(in.readChar()));              System.out.printf("readShort():0x%s\n", shortToHexString(in.readShort()));              System.out.printf("readInt():0x%s\n", Integer.toHexString(in.readInt()));              System.out.printf("readLong():0x%s\n", Long.toHexString(in.readLong()));              System.out.printf("readUTF():%s\n", in.readUTF());               in.close();         } catch (FileNotFoundException e) {             e.printStackTrace();         } catch (SecurityException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }      }       // 打印byte对应的16进制的字符串      private static String byteToHexString(byte val) {          return Integer.toHexString(val & 0xff);      }       // 打印char对应的16进制的字符串      private static String charToHexString(char val) {          return Integer.toHexString(val);      }       // 打印short对应的16进制的字符串      private static String shortToHexString(short val) {          return Integer.toHexString(val & 0xffff);      }  } 


运行结果

byteToHexString(0x8F):0x8f
charToHexString(0x8FCF):0x8fcf
readBoolean():true
readByte():0x41
readChar():0x4243
readShort():0x4445
readInt():0x12345678
readLong():0xfedcba987654321
readUTF():abcdefghijklmnopqrstuvwxyz严12

结果说明
(01) 查看file.txt文本。16进制的数据显示如下:

Java io 入门(十四)数据输入流DataInputStream源码分析及介绍使用(4)_www.fengfly.com
001f 对应的int值是31。它表示的含义是后面的UTF-8数据的长度。字符串“abcdefghijklmnopqrstuvwxyz严12”中字母“ab...xyz”的长度是26,“严”对应的UTF-8数据长度是3;“12”长度是2。总的长度=26+3+2=31。

(02) 返回byte对应的16进制的字符串
源码如下:

  1. private static String byteToHexString(byte val) {  
  2.     return Integer.toHexString(val & 0xff);  

想想为什么代码是:

  1. return Integer.toHexString(val & 0xff); 

而不是

  1. return Integer.toHexString(val); 

我们先看看 byteToHexString((byte)0x8F); 在上面两种情况下的输出结果。
return Integer.toHexString(val & 0xff); 对应的输出是“0xffffff8f
return Integer.toHexString(val); 对应的输出是“0x8f
为什么会这样呢?
原因其实很简单,就是“byte类型转换成int类型”导致的问题。
byte类型的0x8F是一个负数,它对应的2进制是10001111;将一个负数的byte转换成int类型时,执行的是有符号转型(新增位都填充符号位的数字)。0x8F的符号位是1,因为将它转换成int时,填充“1”;转型后的结果(2进制)是11111111 11111111 11111111 10001111,对应的16进制为0xffffff8f。
因为当我们执行Integer.toHexString(val);时,返回的就是0xffffff8f。
在Integer.toHexString(val & 0xff)中,相当于0xffffff8f & 0xff,得到的结果是0x8f。

(03) 返回char和short对应的16进制的字符串
“返回char对应的16进制的字符串”对应的源码如下:

  1. private static String charToHexString(char val) {  
  2.     return Integer.toHexString(val);  

“返回short对应的16进制的字符串”对应源码如下:

  1. private static String shortToHexString(short val) {  
  2.     return Integer.toHexString(val & 0xffff);  
  3. }  

比较上面的两个函数,为什么一个是 “val” ,而另一个是 “val & 0xffff”?
通过(02)的分析,我们类似的推出为什么 “返回short对应的16进制的字符串” 要执行“val & 0xffff”。
但是,为什么 “返回char对应的16进制的字符串” 要执行 “val” 即可。原因也很简单,java中char是无符号类型,占两个字节。将char转换为int类型,执行的是无符号转型,新增为都填充0。



0 0
原创粉丝点击