黑馬程序員:Java基礎總結----字節流&InputStream &OutputStream

黑馬程序員:Java基礎總結



字節流&InputStream &OutputStream

 ASP.Net+Android+IO開發.Net培訓、期待與您交流!



字節流

字節流兩個基類:
InputStream , OutputStream

類 OutputStream方法

輸出流接受輸出字節並將這些字節發送到某個接收器。 

 void write(byte[] b)
          將 b.length 個字節從指定的 byte 數組寫入此輸出流。
 void write(byte[] b, int off, int len)
          將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。
abstract void write(int b)
          將指定的字節寫入此輸出流。

類 FileOutputStream

FileOutputStream(String name, boolean append)
          創建一個向具有指定 name 的文件中寫入數據的輸出文件流。

複製一個圖片
            FileOutputStream fos = null;
            FileInputStream fis = null;
             try
            {
                  fos = new FileOutputStream("c:\\2.bmp" );
                  fis = new FileInputStream("c:\\1.bmp" );

                   byte[] buf = new byte[1024];

                   int len = 0;

                   while((len=fis.read(buf))!=-1)
                  {
                        fos.write(buf,0,len);
                  }
             }

類 BufferedOutputStream

BufferedOutputStream(OutputStream out)
          創建一個新的緩衝輸出流,以將數據寫入指定的底層輸出流。

通過字節流的緩衝區完成複製mp3

            BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3" ));
            BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3" ));
            
             int by = 0;

             while((by=bufis.read())!=-1)
            {
                  bufos.write(by);
            }

            bufos.close();
            bufis.close();

類 ObjectOutputStream

ObjectOutputStream 將 Java 對象的基本數據類型和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)對象。通過在流中使用文件可以實現對象的持久存儲。如果流是網絡套接字流,則可以在另一臺主機上或另一個進程中重構對象。

       public static void writeObj()throws IOException
      {
            ObjectOutputStream oos =
                   new ObjectOutputStream(new FileOutputStream("obj.txt" ));

            oos.writeObject( new Person("lisi0" ,399,"kr"));

            oos.close();
      }

類 PipedOutputStream

可以將管道輸出流連接到管道輸入流來創建通信管道。管道輸出流是管道的發送端。通常,數據由某個線程寫入 PipedOutputStream 對象,並由其他線程從連接的 PipedInputStream 讀取。不建議對這兩個對象嘗試使用單個線程,因爲這樣可能會造成該線程死鎖。如果某個線程正從連接的管道輸入流中讀取數據字節,但該線程不再處於活動狀態,則該管道被視爲處於 毀壞 狀態。

PipedOutputStream()
          創建尚未連接到管道輸入流的管道輸出流。
PipedOutputStream(PipedInputStream snk)
          創建連接到指定管道輸入流的管道輸出流。
必須使用多線程:
            PipedInputStream in = new PipedInputStream();
            PipedOutputStream out = new PipedOutputStream();
            in.connect(out);

             Read r = new Read(in);
             Write w = new Write(out);
             new Thread(r).start();
             new Thread(w).start();

類 DataOutputStream

可以用於操作基本數據類型的數據的流對象
void writeInt(int v)
          將一個 int 值以 4-byte 值形式寫入基礎輸出流中,先寫入高字節。

       public static void readData()throws IOException
      {
            DataInputStream dis = new DataInputStream(new FileInputStream("data.txt" ));

             int num = dis.readInt();
             boolean b = dis.readBoolean();
             double d = dis.readDouble();

            System. out.println("num=" +num);
            System. out.println("b=" +b);
            System. out.println("d=" +d);

            dis.close();
      }
       public static void writeData()throws IOException
      {
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt" ));

            dos.writeInt(234);
            dos.writeBoolean( true);
            dos.writeDouble(9887.543);

            dos.close();

            ObjectOutputStream oos = null;
            oos.writeObject( new O());

            
      }


類 ByteArrayOutputStream

用於操作字節數組的流對象
ByteArrayInputStream :在構造的時候,需要接收數據源,。而且數據源是一個字節數組。
ByteArrayOutputStream: 在構造的時候,不用定義數據目的,因爲該對象中已經內部封裝了可變長度的字節數組。
這就是數據目的地。
因爲這兩個流對象都操作的數組,並沒有使用系統資源。
所以,不用進行close關閉

源設備,
     鍵盤 System.in,硬盤 FileStream,內存 ArrayStream。
目的設備:
     控制檯 System.out,硬盤FileStream,內存 ArrayStream

byte[] toByteArray()
          創建一個新分配的 byte 數組。
 String toString()
          使用平臺默認的字符集,通過解碼字節將緩衝區內容轉換爲字符串。

       //數據源。
      ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD" .getBytes());

       //數據目的
      ByteArrayOutputStream bos = new ByteArrayOutputStream();

       int by = 0;

       while((by=bis.read())!=-1)
      {
             bos.write(by );
      }



      System.out.println(bos.size());
      System.out.println(bos.toString());

//    bos.writeTo(new FileOutputStream("a.txt"))





類 InputStream方法

 int available()
          返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數。
(!多線程時讀取或跳過的字節數可能小於該數,試圖使用此方法的返回值分配緩衝區來實現讀取和跳過是不正確的)
返回:可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數;如果到達輸入流末尾,則返回 0
abstract
  int
read()
          從輸入流中讀取數據的下一個字節。
 int read(byte[] b)
          從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中。

            FileInputStream fis = new FileInputStream("fos.txt" );
            
//           int num = fis.available();
             byte[] buf = new byte[fis.available()]; //定義一個剛剛好的緩衝區。不用在循環了。

            fis.read(buf);

            System. out.println(new String(buf));

            fis.close();

類 FileInputStream

和InputStream相似

類 BufferedInputStream

字段摘要
protected byte[] buf
          存儲數據的內部緩衝區數組。
protected int count
          比緩衝區中最後一個有效字節的索引大 1 的索引。 buf[0] 到 buf[count-1] 的元素包含從底層輸入流中獲取的緩衝輸入數據
protected int marklimit
          調用 mark 方法後,在後續調用 reset 方法失敗之前所允許的最大提前讀取量。
protected int markpos
          最後一次調用 mark 方法時 pos 字段的值。
protected int pos
          緩衝區中的當前位置。

以下是JDK讀取文件的過程

 private void fill() throws IOException {
     byte[] buffer = getBufIfOpen();
     if (markpos < 0)
         pos = 0;            /* no mark: throw away the buffer */
     else if (pos >= buffer.length)  /* no room left in buffer */
         if (markpos > 0) {  /* can throw away early part of the buffer */
             int sz = pos - markpos;
             System.arraycopy(buffer, markpos, buffer, 0, sz);
             pos = sz;
             markpos = 0;
         } else if (buffer.length >= marklimit) {
             markpos = -1;   /* buffer got too big, invalidate mark */
             pos = 0;        /* drop buffer contents */
         } else {            /* grow buffer */
             int nsz = pos * 2;
             if (nsz > marklimit)
                 nsz = marklimit;
             byte nbuf[] = new byte[nsz];
             System.arraycopy(buffer, 0, nbuf, 0, pos);
             if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                 // Can't replace buf if there was an async close.
                 // Note: This would need to be changed if fill()
                 // is ever made accessible to multiple threads.
                 // But for now, the only way CAS can fail is via close.
                 // assert buf == null;
                 throw new IOException("Stream closed");
             }
             buffer = nbuf;
         }
     count = pos;
     int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
     if (n > 0)
         count = n + pos;
 }
 public synchronized int read() throws IOException {
     if (pos >= count) {
         fill();
         if (pos >= count)
             return -1;
     }
     return getBufIfOpen()[pos++] & 0xff;
 }

結論:
字節流的讀一個字節的read方法爲什麼返回值類型不是byte,而是int。
因爲有可能會讀到連續8個二進制1的情況,8個二進制1對應的十進制是-1.
那麼就會數據還沒有讀完,就結束的情況。因爲我們判斷讀取結束是通過結尾標記-1來確定的。
所以,爲了避免這種情況將讀到的字節進行int類型的提升。
並在保留原字節數據的情況前面了補了24個0,變成了int類型的數值。

而在寫入數據時,只寫該int類型數據的最低8位。


類 ObjectInputStream

ObjectInputStream 對以前使用 ObjectOutputStream 寫入的基本數據和對象進行反序列化

ObjectOutputStream 和 ObjectInputStream 分別與 FileOutputStream 和 FileInputStream 一起使用時,可以爲應用程序提供對對象圖形的持久存儲。ObjectInputStream 用於恢復那些以前序列化的對象。其他用途包括使用套接字流在主機之間傳遞對象,或者用於編組和解組遠程通信系統中的實參和形參。

類 PipedInputStream

管道輸入流應該連接到管道輸出流;管道輸入流提供要寫入管道輸出流的所有數據字節。通常,數據由某個線程從 PipedInputStream 對象讀取,並由其他線程將其寫入到相應的 PipedOutputStream。不建議對這兩個對象嘗試使用單個線程,因爲這樣可能死鎖線程。管道輸入流包含一個緩衝區,可在緩衝區限定的範圍內將讀操作和寫操作分離開。如果向連接管道輸出流提供數據字節的線程不再存在,則認爲該管道已損壞
PipedInputStream(PipedOutputStream src)
          創建 PipedInputStream,使其連接到管道輸出流 src

類 DataInputStream

 int readInt()
          參見 DataInput 的 readInt 方法的常規協定。可見有兩個大接口DataInput,和DataOutput


類 ByteArrayOutputStream

參見ByteArraysInputStream相似







 ASP.Net+Android+IO開發.Net培訓、期待與您交流!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章