亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java 中的 DataInputStream 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年05月18日 09:25:07   投稿:mrr  
DataInputStream 是數(shù)據(jù)輸入流。它繼承于FilterInputStream。接下來(lái)通過(guò)本文給大家介紹Java 中的 DataInputStream的相關(guān)知識(shí),需要的朋友參考下吧

DataInputStream 介紹

DataInputStream 是數(shù)據(jù)輸入流。它繼承于FilterInputStream。

DataInputStream 是用來(lái)裝飾其它輸入流,它“允許應(yīng)用程序以與機(jī)器無(wú)關(guān)方式從底層輸入流中讀取基本 Java 數(shù)據(jù)類型”。應(yīng)用程序可以使用DataOutputStream(數(shù)據(jù)輸出流)寫入由DataInputStream(數(shù)據(jù)輸入流)讀取的數(shù)據(jù)。

DataInputStream 函數(shù)列表 

DataInputStream(InputStream in)
final int  read(byte[] buffer, int offset, int length)
final int  read(byte[] buffer)
final boolean  readBoolean()
final byte  readByte()
final char  readChar()
final double  readDouble()
final float  readFloat()
final void  readFully(byte[] dst)
final void  readFully(byte[] dst, int offset, int byteCount)
final int  readInt()
final String  readLine()
final long  readLong()
final short  readShort()
final static String  readUTF(DataInput in)
final String  readUTF()
final int  readUnsignedByte()
final int  readUnsignedShort()
final int  skipBytes(int count)

DataInputStream.java源碼分析(基于jdk1.7.40) 

package java.io;
 public class DataInputStream extends FilterInputStream implements DataInput {
  // 構(gòu)造函數(shù)。
  public DataInputStream(InputStream in) {
   super(in);
  }
  private byte bytearr[] = new byte[80];
  private char chararr[] = new char[80];
  // 從“數(shù)據(jù)輸入流”中讀取一個(gè)字節(jié)
  public final int read(byte b[]) throws IOException {
  return in.read(b, 0, b.length);
  }
  // 從“數(shù)據(jù)輸入流”中讀取數(shù)據(jù)并存儲(chǔ)到字節(jié)數(shù)組b中。
  // off是字節(jié)數(shù)組b中開(kāi)始存儲(chǔ)元素的起始位置。
  // len是讀取字節(jié)的個(gè)數(shù)。
  public final int read(byte b[], int off, int len) throws IOException {
   return in.read(b, off, len);
  }
  // 從“數(shù)據(jù)輸入流”中讀取數(shù)據(jù)并填滿字節(jié)數(shù)組b中;沒(méi)有填滿數(shù)組b則一直讀取,直到填滿位置。
  // 從字節(jié)數(shù)組b的位置0開(kāi)始存儲(chǔ),并且讀取的字節(jié)個(gè)數(shù)等于b的長(zhǎng)度。
  public final void readFully(byte b[]) throws IOException {
   readFully(b, 0, b.length);
  }
  // 從“數(shù)據(jù)輸入流”中讀取數(shù)據(jù)并存儲(chǔ)到字節(jié)數(shù)組b中;若沒(méi)讀取len個(gè)字節(jié),直到一直讀取直到讀取完len個(gè)字節(jié)為止。
  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;
   }
  }
  // 跳過(guò)n個(gè)字節(jié)
  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;
  }
  // 從“數(shù)據(jù)輸入流”中讀取boolean類型的值
  public final boolean readBoolean() throws IOException {
   int ch = in.read();
  if (ch < 0)
    throw new EOFException();
   return (ch != 0);
  }
  // 從“數(shù)據(jù)輸入流”中讀取Byte類型的值
  public final byte readByte() throws IOException {
   int ch = in.read();
   if (ch < 0)
    throw new EOFException();
   return (byte)(ch);
  }
  // 從“數(shù)據(jù)輸入流”中讀取“無(wú)符號(hào)的Byte類型”的值,即讀取值為正數(shù)的byte值
  public final int readUnsignedByte() throws IOException {
   int ch = in.read();
   if (ch < 0)
    throw new EOFException();
   return ch;
  }
  // 從“數(shù)據(jù)輸入流”中讀取“short類型”的值
  public final short readShort() throws IOException {
   int ch = in.read();
   int ch = in.read();
  if ((ch1 | ch2) < 0)
    throw new EOFException();
  return (short)((ch1 << 8) + (ch2 << 0));
  }
  // 從“數(shù)據(jù)輸入流”中讀取“無(wú)符號(hào)的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);
  }
  // 從“數(shù)據(jù)輸入流”中讀取“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));
  }
  // 從“數(shù)據(jù)輸入流”中讀取“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];
  // 從“數(shù)據(jù)輸入流”中讀取“l(fā)ong類型”的值
  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));
  }
  // 從“數(shù)據(jù)輸入流”中讀取“float類型”的值
  public final float readFloat() throws IOException {
   return Float.intBitsToFloat(readInt());
  }
  // 從“數(shù)據(jù)輸入流”中讀取“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[];
   }
   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, , offset);
  }
  // 從“數(shù)據(jù)輸入流”中讀取“UTF類型”的值
  public final String readUTF() throws IOException {
   return readUTF(this);
  }
  public final static String readUTF(DataInput in) throws IOException {
   // 從“數(shù)據(jù)輸入流”中讀取“無(wú)符號(hào)的short類型”的值:
   // 注意:UTF-8輸入流的前2個(gè)字節(jié)是數(shù)據(jù)的長(zhǎng)度
   int utflen = in.readUnsignedShort();
   byte[] bytearr = null;
   char[] chararr = null;
   // 如果in本身是“數(shù)據(jù)輸入流”,
   // 則,設(shè)置字節(jié)數(shù)組bytearr = "數(shù)據(jù)輸入流"的成員bytearr
   //  設(shè)置字符數(shù)組chararr = "數(shù)據(jù)輸入流"的成員chararr
   // 否則的話,新建數(shù)組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;
   // 從“數(shù)據(jù)輸入流”中讀取數(shù)據(jù)并存儲(chǔ)到字節(jié)數(shù)組bytearr中;從bytearr的位置0開(kāi)始存儲(chǔ),存儲(chǔ)長(zhǎng)度為utflen。
   // 注意,這里是存儲(chǔ)到字節(jié)數(shù)組!而且讀取的是全部的數(shù)據(jù)。
   in.readFully(bytearr, 0, utflen);
   // 將“字節(jié)數(shù)組bytearr”中的數(shù)據(jù) 拷貝到 “字符數(shù)組chararr”中
   // 注意:這里相當(dāng)于“預(yù)處理的輸入流中單字節(jié)的符號(hào)”,因?yàn)閁TF-8是1-4個(gè)字節(jié)可變的。
   while (count < utflen) {
    // 將每個(gè)字節(jié)轉(zhuǎn)換成int值
    c = (int) bytearr[count] & xff;
    // UTF-8的單字節(jié)數(shù)據(jù)的值都不會(huì)超過(guò)127;所以,超過(guò)127,則退出。
    if (c > 127) break;
    count++;
    // 將c保存到“字符數(shù)組chararr”中
   chararr[chararr_count++]=(char)c;
   }
   // 處理完輸入流中單字節(jié)的符號(hào)之后,接下來(lái)我們繼續(xù)處理。
  while (count < utflen) {
    // 下面語(yǔ)句執(zhí)行了2步操作。
    // (01) 將字節(jié)由 “byte類型” 轉(zhuǎn)換成 “int類型”。
    //  例如, “11001010” 轉(zhuǎn)換成int之后,是 “00000000 00000000 00000000 11001010”
    // (02) 將 “int類型” 的數(shù)據(jù)左移4位
   //  例如, “00000000 00000000 00000000 11001010” 左移4位之后,變成 “00000000 00000000 00000000 00001100”
    c = (int) bytearr[count] & 0xff;
   switch (c >> 4) {
     // 若 UTF-8 是單字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “0xxxxxxx” 形式;
    // 則 bytearr[count] 對(duì)應(yīng)的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 是雙字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “110xxxxx 10xxxxxx” 形式中的第一個(gè),即“110xxxxx”
     // 則 bytearr[count] 對(duì)應(yīng)的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 是三字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “1110xxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“1110xxxx”
     // 則 bytearr[count] 對(duì)應(yīng)的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 是四字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “11110xxx 10xxxxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“11110xxx”
    // 則 bytearr[count] 對(duì)應(yīng)的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);
 }
 }

   說(shuō)明:

DataInputStream 的作用就是“允許應(yīng)用程序以與機(jī)器無(wú)關(guān)方式從底層輸入流中讀取基本 Java 數(shù)據(jù)類型。應(yīng)用程序可以使用數(shù)據(jù)輸出流寫入稍后由數(shù)據(jù)輸入流讀取的數(shù)據(jù)?!?br />

DataInputStream 中比較難以理解的函數(shù)就只有 readUTF(DataInput in);下面,對(duì)這個(gè)函數(shù)進(jìn)行詳細(xì)的介紹,其它的函數(shù)請(qǐng)參考源碼中的注釋。

readUTF(DataInput in)源碼如下:

public final static String readUTF(DataInput in) throws IOException {
  // 從“數(shù)據(jù)輸入流”中讀取“無(wú)符號(hào)的short類型”的值:
  // 注意:UTF-8輸入流的前2個(gè)字節(jié)是數(shù)據(jù)的長(zhǎng)度
  int utflen = in.readUnsignedShort();
  byte[] bytearr = null;
  char[] chararr = null;
  // 如果in本身是“數(shù)據(jù)輸入流”,
  // 則,設(shè)置字節(jié)數(shù)組bytearr = "數(shù)據(jù)輸入流"的成員bytearr
  //  設(shè)置字符數(shù)組chararr = "數(shù)據(jù)輸入流"的成員chararr
  // 否則的話,新建數(shù)組bytearr和chararr
  if (in instanceof DataInputStream) {
   DataInputStream dis = (DataInputStream)in;
   if (dis.bytearr.length < utflen){
    dis.bytearr = new byte[utflen*];
    dis.chararr = new char[utflen*];
   }
   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;
  // 從“數(shù)據(jù)輸入流”中讀取數(shù)據(jù)并存儲(chǔ)到字節(jié)數(shù)組bytearr中;從bytearr的位置開(kāi)始存儲(chǔ),存儲(chǔ)長(zhǎng)度為utflen。
  // 注意,這里是存儲(chǔ)到字節(jié)數(shù)組!而且讀取的是全部的數(shù)據(jù)。
  in.readFully(bytearr, 0, utflen);
  // 將“字節(jié)數(shù)組bytearr”中的數(shù)據(jù) 拷貝到 “字符數(shù)組chararr”中
  // 注意:這里相當(dāng)于“預(yù)處理的輸入流中單字節(jié)的符號(hào)”,因?yàn)閁TF-是-個(gè)字節(jié)可變的。
  while (count < utflen) {
   // 將每個(gè)字節(jié)轉(zhuǎn)換成int值
   c = (int) bytearr[count] & xff;
   // UTF-8的每個(gè)字節(jié)的值都不會(huì)超過(guò)127;所以,超過(guò)127,則退出。
   if (c > 127) break;
   count++;
   // 將c保存到“字符數(shù)組chararr”中
   chararr[chararr_count++]=(char)c;
  }
  // 處理完輸入流中單字節(jié)的符號(hào)之后,接下來(lái)我們繼續(xù)處理。
  while (count < utflen) {
   // 下面語(yǔ)句執(zhí)行了2步操作。
   // () 將字節(jié)由 “byte類型” 轉(zhuǎn)換成 “int類型”。
   //  例如, “11001010” 轉(zhuǎn)換成int之后,是 “00000000 00000000 00000000 11001010”
   // (02) 將 “int類型” 的數(shù)據(jù)左移4位
   //  例如, “00000000 00000000 00000000 11001010” 左移4位之后,變成 “00000000 00000000 00000000 00001100”
   c = (int) bytearr[count] & 0xff;
   switch (c >> 4) {
    // 若 UTF-8 是單字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “0xxxxxxx” 形式;
    // 則 bytearr[count] 對(duì)應(yīng)的int類型的c的取值范圍是 0-7。
    case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
     /* xxxxxxx*/
     count++;
     chararr[chararr_count++]=(char)c;
     break;
    // 若 UTF-8 是雙字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “110xxxxx 10xxxxxx” 形式中的第一個(gè),即“110xxxxx”
    // 則 bytearr[count] 對(duì)應(yīng)的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 是三字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “1110xxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“1110xxxx”
   // 則 bytearr[count] 對(duì)應(yīng)的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 是四字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “11110xxx 10xxxxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“11110xxx”
    // 則 bytearr[count] 對(duì)應(yīng)的int類型的c的取值是 
    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);
 }

說(shuō)明:

(01) readUTF()的作用,是從輸入流中讀取UTF-8編碼的數(shù)據(jù),并以String字符串的形式返回。

(02) 知道了readUTF()的作用之后,下面開(kāi)始介紹readUTF()的流程:

第1步,讀取出輸入流中的UTF-8數(shù)據(jù)的長(zhǎng)度。代碼如下:

int utflen = in.readUnsignedShort();

UTF-8數(shù)據(jù)的長(zhǎng)度包含在它的前兩個(gè)字節(jié)當(dāng)中;我們通過(guò)readUnsignedShort()讀取出前兩個(gè)字節(jié)對(duì)應(yīng)的正整數(shù)就是UTF-8數(shù)據(jù)的長(zhǎng)度。

第2步,創(chuàng)建2個(gè)數(shù)組:字節(jié)數(shù)組bytearr 和 字符數(shù)組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];
 }

首先,判斷該輸入流本身是不是DataInputStream,即數(shù)據(jù)輸入流;若是的話,

則,設(shè)置字節(jié)數(shù)組bytearr = "數(shù)據(jù)輸入流"的成員bytearr

      設(shè)置字符數(shù)組chararr = "數(shù)據(jù)輸入流"的成員chararr

否則的話,新建數(shù)組bytearr和chararr。

第3步,將UTF-8數(shù)據(jù)全部讀取到“字節(jié)數(shù)組bytearr”中。代碼如下:

in.readFully(bytearr, 0, utflen);

注意: 這里是存儲(chǔ)到字節(jié)數(shù)組,而不是字符數(shù)組!而且讀取的是全部的數(shù)據(jù)。

第4步,對(duì)UTF-8中的單字節(jié)數(shù)據(jù)進(jìn)行預(yù)處理。代碼如下: 

 while (count < utflen) {
  // 將每個(gè)字節(jié)轉(zhuǎn)換成int值
  c = (int) bytearr[count] & xff;
  // UTF-8的單字節(jié)數(shù)據(jù)的值都不會(huì)超過(guò)127;所以,超過(guò)127,則退出。
  if (c > 127) break;
  count++;
  // 將c保存到“字符數(shù)組chararr”中
  chararr[chararr_count++]=(char)c;
 }

UTF-8的數(shù)據(jù)是變長(zhǎng)的,可以是1-4個(gè)字節(jié);在readUTF()中,我們最終是將全部的UTF-8數(shù)據(jù)保存到“字符數(shù)組(而不是字節(jié)數(shù)組)”中,再將其轉(zhuǎn)換為String字符串。

由于UTF-8的單字節(jié)和ASCII相同,所以這里就將它們進(jìn)行預(yù)處理,直接保存到“字符數(shù)組chararr”中。對(duì)于其它的UTF-8數(shù)據(jù),則在后面進(jìn)行處理。

第5步,對(duì)“第4步 預(yù)處理”之后的數(shù)據(jù),接著進(jìn)行處理。代碼如下: 

// 處理完輸入流中單字節(jié)的符號(hào)之后,接下來(lái)我們繼續(xù)處理。
while (count < utflen) {
 // 下面語(yǔ)句執(zhí)行了2步操作。
 // (01) 將字節(jié)由 “byte類型” 轉(zhuǎn)換成 “int類型”。
 //  例如, “11001010” 轉(zhuǎn)換成int之后,是 “00000000 00000000 00000000 11001010”
 // (02) 將 “int類型” 的數(shù)據(jù)左移4位
 //  例如, “00000000 00000000 00000000 11001010” 左移4位之后,變成 “00000000 00000000 00000000 00001100”
 c = (int) bytearr[count] & 0xff;
 switch (c >> 4) {
  // 若 UTF-8 是單字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “0xxxxxxx” 形式;
  // 則 bytearr[count] 對(duì)應(yīng)的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 是雙字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “110xxxxx 10xxxxxx” 形式中的第一個(gè),即“110xxxxx”
  // 則 bytearr[count] 對(duì)應(yīng)的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 是三字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “1110xxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“1110xxxx”
  // 則 bytearr[count] 對(duì)應(yīng)的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 是四字節(jié),即 bytearr[count] 對(duì)應(yīng)是 “11110xxx 10xxxxxx 10xxxxxx 10xxxxxx” 形式中的第一個(gè),即“11110xxx”
  // 則 bytearr[count] 對(duì)應(yīng)的int類型的c的取值是15 
  default:
   /* 10xx xxxx, 1111 xxxx */
   throw new UTFDataFormatException(
    "malformed input around byte " + count);
 }
}

(a) 我們將下面的兩條語(yǔ)句一起進(jìn)行說(shuō)明

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

首先,我們必須要理解 為什么要這么做(執(zhí)行上面2條語(yǔ)句)呢?

原因很簡(jiǎn)單,這么做的目的就是為了區(qū)分UTF-8數(shù)據(jù)是幾位的;因?yàn)閁TF-8的數(shù)據(jù)是1~4字節(jié)不等。

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

--------------------+---------------------------------------------
1字節(jié) UTF-8的通用格式  | 0xxxxxxx
2字節(jié) UTF-8的通用格式  | 110xxxxx 10xxxxxx
3字節(jié) UTF-8的通用格式  | 1110xxxx 10xxxxxx 10xxxxxx
4字節(jié) UTF-8的通用格式  | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
執(zhí)行 c = (int) bytearr[count] & 0xff; 和 c>>4 這2項(xiàng)操作之后,上面的數(shù)據(jù)變成
--------------------+---------------------------------------------
1字節(jié) UTF-8的變換后對(duì)應(yīng)的int類型值  | 00000000 00000000 00000000 00000xxx    (范圍是0~7)
2字節(jié) UTF-8的變換后對(duì)應(yīng)的int類型值  | 00000000 00000000 00000000 0000110x    (范圍是12~13)
3字節(jié) UTF-8的變換后對(duì)應(yīng)的int類型值  | 00000000 00000000 00000000 00001110    (范圍是14)
4字節(jié) UTF-8的變換后對(duì)應(yīng)的int類型值  | 00000000 00000000 00000000 00001111    (范圍是15)

為什么會(huì)是這樣呢?

我們以“2字節(jié) UTF-8的通用格式”來(lái)說(shuō)明。

它的通用格式是 “110xxxxx 10xxxxxx”,我們?cè)诓僮鲿r(shí),只會(huì)操作第1個(gè)字節(jié),即只會(huì)操作“110xxxxx”

(a.1) 在執(zhí)行 c = (int) bytearr[count] & 0xff; 時(shí),首先將 bytearr[count] 轉(zhuǎn)換成int。

“110xxxxx”

轉(zhuǎn)成int類型之后,變成

“11111111 11111111 11111111 110xxxxx”

因?yàn)椤?10xxxxx”是負(fù)數(shù)(第1為是1),所以轉(zhuǎn)換成int類型時(shí)多出來(lái)的位補(bǔ)1。

(a.2) 接著 c = (int) bytearr[count] & 0xff; 中,會(huì)將 “轉(zhuǎn)換成int類型后的bytearr[count]” 與 “0xff”進(jìn)行 邏輯與(即&) 操作。結(jié)果如下:

“00000000 00000000 00000000 110xxxxx”

(a.3) 執(zhí)行 c>>4 時(shí),會(huì)將上面的結(jié)果左移4位。得到的結(jié)果如下:

“00000000 00000000 00000000 0000110x”

(b) 上面的理解之后,swicth (c>>4) { ... } 其中的省略號(hào)部分就相當(dāng)容易理解了。

我們還是以“2字節(jié) UTF-8的通用格式”來(lái)說(shuō)明。

它會(huì)執(zhí)行 case 12 和 case 13;源碼如下: 

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));

(b.1) 由于這種情況對(duì)應(yīng)的UTF-8數(shù)據(jù)是“2字節(jié)”的,因此,執(zhí)行count+2;直接跳過(guò)2個(gè)字節(jié)。

(b.2) 由于chararr的元素是字符類型,而一個(gè)字符正好占2個(gè)字節(jié);因?yàn)檎脤?((c & 0x1F) << 6) | (char2 & 0x3F)); 的結(jié)果轉(zhuǎn)換成char,然后保存在chararr數(shù)組中。

第6步,將字符數(shù)組轉(zhuǎn)換成String字符串,并返回。代碼如下:

return new String(chararr, 0, chararr_count);

示例代碼

關(guān)于DataInputStream中API的詳細(xì)用法,參考示例代碼(DataInputStreamTest.java): 

import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.InputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.FileNotFoundException;
 import java.lang.SecurityException;
 /**
 * DataInputStream 和 DataOutputStream測(cè)試程序
 *
 * 
 */
 public class DataInputStreamTest {
 private static final int LEN = 5;
  public static void main(String[] args) {
   // 測(cè)試DataOutputStream,將數(shù)據(jù)寫入到輸出流中。
   testDataOutputStream() ;
   // 測(cè)試DataInputStream,從上面的輸出流結(jié)果中讀取數(shù)據(jù)。
   testDataInputStream() ;
  }
  /**
  * DataOutputStream的API測(cè)試函數(shù)
  */
  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嚴(yán)12");
    out.close();
   } catch (FileNotFoundException e) {
    e.printStackTrace();
   } catch (SecurityException e) {
    e.printStackTrace();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  /**
  * DataInputStream的API測(cè)試函數(shù)
  */
  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對(duì)應(yīng)的16進(jìn)制的字符串
  private static String byteToHexString(byte val) {
   return Integer.toHexString(val & xff);
  }
  // 打印char對(duì)應(yīng)的進(jìn)制的字符串
  private static String charToHexString(char val) {
   return Integer.toHexString(val);
  }
  // 打印short對(duì)應(yīng)的16進(jìn)制的字符串
  private static String shortToHexString(short val) {
   return Integer.toHexString(val & xffff);
  }
 }

   運(yùn)行結(jié)果:

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

結(jié)果說(shuō)明:

(01) 查看file.txt文本。16進(jìn)制的數(shù)據(jù)顯示如下: 

001f 對(duì)應(yīng)的int值是31。它表示的含義是后面的UTF-8數(shù)據(jù)的長(zhǎng)度。字符串“abcdefghijklmnopqrstuvwxyz嚴(yán)12”中字母“ab...xyz”的長(zhǎng)度是26,“嚴(yán)”對(duì)應(yīng)的UTF-8數(shù)據(jù)長(zhǎng)度是3;“12”長(zhǎng)度是2。總的長(zhǎng)度=26+3+2=31。

(02) 返回byte對(duì)應(yīng)的16進(jìn)制的字符串

源碼如下:

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

想想為什么代碼是:

return Integer.toHexString(val & 0xff);

而不是

return Integer.toHexString(val);

我們先看看 byteToHexString((byte)0x8F); 在上面兩種情況下的輸出結(jié)果。

return Integer.toHexString(val & 0xff); 對(duì)應(yīng)的輸出是“0xffffff8f”
return Integer.toHexString(val); 對(duì)應(yīng)的輸出是“0x8f”

為什么會(huì)這樣呢?

原因其實(shí)很簡(jiǎn)單,就是“byte類型轉(zhuǎn)換成int類型”導(dǎo)致的問(wèn)題。

byte類型的0x8F是一個(gè)負(fù)數(shù),它對(duì)應(yīng)的2進(jìn)制是10001111;將一個(gè)負(fù)數(shù)的byte轉(zhuǎn)換成int類型時(shí),執(zhí)行的是有符號(hào)轉(zhuǎn)型(新增位都填充符號(hào)位的數(shù)字)。0x8F的符號(hào)位是1,因?yàn)閷⑺D(zhuǎn)換成int時(shí),填充“1”;轉(zhuǎn)型后的結(jié)果(2進(jìn)制)是11111111 11111111 11111111 10001111,對(duì)應(yīng)的16進(jìn)制為0xffffff8f。
因?yàn)楫?dāng)我們執(zhí)行Integer.toHexString(val);時(shí),返回的就是0xffffff8f。

在Integer.toHexString(val & 0xff)中,相當(dāng)于0xffffff8f & 0xff,得到的結(jié)果是0x8f。

(03) 返回char和short對(duì)應(yīng)的16進(jìn)制的字符串

“返回char對(duì)應(yīng)的16進(jìn)制的字符串”對(duì)應(yīng)的源碼如下:

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

“返回short對(duì)應(yīng)的16進(jìn)制的字符串”對(duì)應(yīng)源碼如下:

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

比較上面的兩個(gè)函數(shù),為什么一個(gè)是 “val” ,而另一個(gè)是 “val & 0xffff”?

通過(guò)(02)的分析,我們類似的推出為什么 “返回short對(duì)應(yīng)的16進(jìn)制的字符串” 要執(zhí)行“val & 0xffff”。

但是,為什么 “返回char對(duì)應(yīng)的16進(jìn)制的字符串” 要執(zhí)行 “val” 即可。原因也很簡(jiǎn)單,java中char是無(wú)符號(hào)類型,占兩個(gè)字節(jié)。將char轉(zhuǎn)換為int類型,執(zhí)行的是無(wú)符號(hào)轉(zhuǎn)型,新增為都填充0。

以上所述是小編給大家介紹的Java 中的 DataInputStream的相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題

    解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題

    這篇文章主要介紹了解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2023-07-07
  • java利用java.net.URLConnection發(fā)送HTTP請(qǐng)求的方法詳解

    java利用java.net.URLConnection發(fā)送HTTP請(qǐng)求的方法詳解

    如何通過(guò)Java(模擬瀏覽器)發(fā)送HTTP請(qǐng)求是我們?cè)谌粘=?jīng)常會(huì)遇到的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于java利用java.net.URLConnection發(fā)送HTTP請(qǐng)求的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-05-05
  • 深入分析JAVA流程控制語(yǔ)句

    深入分析JAVA流程控制語(yǔ)句

    這篇文章主要介紹了JAVA流程控制語(yǔ)句的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • Java實(shí)現(xiàn)二維數(shù)組和稀疏數(shù)組之間的轉(zhuǎn)換

    Java實(shí)現(xiàn)二維數(shù)組和稀疏數(shù)組之間的轉(zhuǎn)換

    本文主要介紹了Java 二維數(shù)組和稀疏數(shù)組轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • SpringBoot接收各種各樣參數(shù)的示例詳解

    SpringBoot接收各種各樣參數(shù)的示例詳解

    參數(shù)映射準(zhǔn)確來(lái)說(shuō)是springmvc來(lái)幫我們干的活,但是由于springboot太過(guò)火爆,簡(jiǎn)化了springmvc相關(guān)配置文件,以至于很多人會(huì)誤認(rèn)為是springboot的功能,本文將給大家介紹SpringBoot接收各種各樣參數(shù),文中有詳細(xì)的代碼講解,需要的朋友可以參考下
    2024-04-04
  • Hibernate原理及應(yīng)用

    Hibernate原理及應(yīng)用

    本文主要介紹了Hibernate原理及應(yīng)用。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • SpringBoot Data JPA 關(guān)聯(lián)表查詢的方法

    SpringBoot Data JPA 關(guān)聯(lián)表查詢的方法

    這篇文章主要介紹了SpringBoot Data JPA 關(guān)聯(lián)表查詢的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 解決MyBatisPlus的updateBatchById()批量修改失效問(wèn)題

    解決MyBatisPlus的updateBatchById()批量修改失效問(wèn)題

    這篇文章主要介紹了解決MyBatisPlus的updateBatchById()批量修改失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • JProfiler11使用教程之JVM調(diào)優(yōu)問(wèn)題小結(jié)

    JProfiler11使用教程之JVM調(diào)優(yōu)問(wèn)題小結(jié)

    這篇文章主要介紹了JProfiler11使用教程之JVM調(diào)優(yōu),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • springboot中filter的用法詳解

    springboot中filter的用法詳解

    本篇文章主要介紹了springboot中filter的用法詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11

最新評(píng)論