天天看點

Java中如何将OutputStream轉換為InputStream

如果你曾經使用java IO程式設計,你會很快碰到這種情況,某個類在OutputStream上建立資料而你需要将它發送給某個需要從輸入流讀取資料的類。

  你很快會被問道,“java中如何将OutputStream轉換為InputStream?”

  方法一:使用位元組數組緩存資料

  最簡單的方法是用位元組數組緩存資料。代碼

  ByteArrayOutputStream out = new ByteArrayOutputStream();

  class1.putDataOnOutputStream(out);

  class2.processDataFromInputStream(

  new ByteArrayInputStream(out.toByteArray())

  );

  于是,OutputStream就被轉換為InputStream了。

  方法二:使用管道

  第一種方法的問題是你必須有足夠的記憶體緩存所有資料。你可以使用檔案系統緩存更多資料,但無論如何可處理資料的大小還是受到限制。

  解決方法是建立一個線程産生資料到PipedOutputStream。目前線程可從中讀取資料。

  PipedInputStream in = new PipedInputStream();

  PipedOUtputStream out = new PipedOutputStream(in);

  new Thread(

  new Runnable(){

  public void run(){

  }

  ).start();

  class2.processDataFromInputStream(in);|||

  方法三:使用循環緩存區

  方法二中的兩個管道流,實際上管理着一個隐藏的循環緩存區。使用一個顯式的循環緩存區更易于了解。CircularBuffers 有如下優點

  一個CircularBuffers類而不是兩個管道類。

  較于緩存所有資料和額外線程的方法更容易使用。

  你可以更改緩存大小而不必受限于管道緩存區1K的固定緩存大小。

  多線程情形:

  CircularByteBuffer cbb = new CircularByteBuffer();

  class1.putDataOnOutputStream(cbb.getOutputStream());

  class2.processDataFromInputStream(cbb.getInputStream());

  單線程情形

  // buffer all data in a circular buffer of infinite size

  CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);

作者“zhujianjia”

================================================

将輸出流OutputStream轉化為輸入流InputStream的方法

一:

        package test.io;  

        import java.io.ByteArrayInputStream;  

        import java.io.ByteArrayOutputStream;  

        import java.io.IOException;  

        /**

         * 用于把OutputStream 轉化為 InputStream。

         * 适合于資料量不大,且記憶體足夠全部容納這些資料的情況。

         * @author 趙學慶 www.java2000.net

         *

       */ 

      public class Test1 {  

         * @param args

         * @throws IOException

         */ 

        public static void main(String[] args) throws IOException {

          ByteArrayOutputStream out = new ByteArrayOutputStream();

          byte[] bs = new byte[] { 1, 2, 3, 4, 5 }; 

          out.write(bs);

          ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())

          byte[] bs = new byte[1024];  

          int len = in.read(bs);  

          for (int i = 0; i < len; i++) {  

            System.out.println(bs[i]);  

          }  

        }

      }

二:

        import java.io.PipedInputStream;  

        import java.io.PipedOutputStream;  

         * 用于把OutputStream 轉化為 InputStream。 适合于資料量大的情況,一個類專門負責産生資料,另一個類負責讀取資料。

         * 

      public class Test2 {  

        public static void main(String[] args) throws IOException {  

          // 使用Piped 的輸入輸出流

          PipedInputStream in = new PipedInputStream();

          final PipedOutputStream out = new PipedOutputStream(in);

          // 啟動線程,讓資料産生者單獨運作

          new Thread(new Runnable() {

            public void run() {

              try {

                       byte[] bs = new byte[2];

                       for (int i = 0; i <= 100; i++) {

                              bs[0] = (byte) i;

                      bs[1] = (byte) (i + 1);

                      // 測試寫入位元組數組

                     out.write(bs);

                     out.flush();

                      // 等待0.1秒

                      Thread.sleep(100);

                      }

             } catch (IOException e) {

               e.printStackTrace();

             } catch (InterruptedException e) {

                     e.printStackTrace();

               }

           }

         }).start();

         // 資料使用者處理資料

         // 也可以使用線程來進行并行處理

         byte[] bs = new byte[1024];

         int len;

         // 讀取資料,并進行處理

         try {

           while ((len = in.read(bs)) != -1) {

             for (int i = 0; i < len; i++) {

               System.out.println(bs[i]);

             }

         } catch (IOException e) {

           e.printStackTrace();

         }

       }

     }

下面是關于 PipedOutputStream 的API介紹

傳送輸出流可以連接配接到傳送輸入流,以建立通信管道。傳送輸出流是管道的發送端。通常,資料由某個線程寫入 PipedOutputStream 對象,并由其他線程從連接配接的 PipedInputStream 讀取。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會死鎖該線程。

下面是關于 PipedInputStream的API介紹

傳送輸入流應該連接配接到傳送輸出流;傳送輸入流會提供要寫入傳送輸出流的所有資料位元組。通常,資料由某個線程從 PipedInputStream 對象讀取,并由其他線程将其寫入到相應的 PipedOutputStream。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會死鎖該線程。傳送輸入流包含一個緩沖區,可在緩沖區限定的範圍内将讀操作和寫操作分離開。

三:

         package test.io;

         import java.io.IOException;  

         import java.io.InputStream;  

         import java.io.OutputStream;  

         import com.Ostermiller.util.CircularByteBuffer;  

         /**

         * <p>

         * 使用CircilarBuffer 輔助類 <br>

       * 下載下傳位址為 <A href="http://ostermiller.org/utils/download.html

      http://ostermiller.org/utils/download.html<br>

       * 介紹位址為 http://ostermiller.org/utils/CircularBuffer.html

       * </p>

       * 

       * @author 趙學慶 www.java2000.net

      public class Test3 {  

          // 使用CircularByteBuffer 

          final CircularByteBuffer cbb = new CircularByteBuffer();  

          // 啟動線程,讓資料産生者單獨運作 

          new Thread(new Runnable() {  

            public void run() {  

              try {  

                OutputStreamClass3.putDataOnOutputStream(cbb.getOutputStream());  

              } catch (IOException e) {  

                e.printStackTrace();  

              }  

            }  

          }).start();  

          // 資料使用者處理資料 

          // 也可以使用線程來進行并行處理 

          InputStreamClass3.processDataFromInputStream(cbb.getInputStream());  

        }  

      }  

      class OutputStreamClass3 {  

        public static void putDataOnOutputStream(OutputStream out) throws IOException {  

          byte[] bs = new byte[2];  

          for (int i = 0; i <= 100; i++) {  

            bs[0] = (byte) i;  

            bs[1] = (byte) (i + 1);  

            // 測試寫入位元組數組 

            out.write(bs);  

            out.flush();  

            try {  

              // 等待0.1秒 

              Thread.sleep(100);  

            } catch (InterruptedException e) {  

              e.printStackTrace();   

      class InputStreamClass3 {  

        public static void processDataFromInputStream(InputStream in) {  

          int len;  

          // 讀取資料,并進行處理 

          try {  

            while ((len = in.read(bs)) != -1) {  

              for (int i = 0; i < len; i++) {  

                System.out.println(bs[i]);  

          } catch (IOException e) {  

            e.printStackTrace();  

      } 

此方法使用了一個類處理,代碼更簡潔,可以很友善的在緩沖處理全部資料的小資料量情況和多線程處理大資料量的不同情況切換

     package test.io;  

     import java.io.IOException;  

     import java.io.InputStream;  

     import java.io.OutputStream;  

     import com.Ostermiller.util.CircularByteBuffer;  

     /**

      * 用于把OutputStream 轉化為 InputStream。

      * <p>

      * 使用CircilarBuffer 輔助類 <br>

      * 下載下傳位址為 <A href="http://ostermiller.org/utils/download.html

     http://ostermiller.org/utils/download.html<br>

      * 介紹位址為 http://ostermiller.org/utils/CircularBuffer.html

      * </p>

      * 

      * @author 趙學慶 www.java2000.net

      */ 

     public class Test4 {  

       /**

        * @param args

        * @throws IOException

        */ 

       public static void main(String[] args) throws IOException {  

         // 緩沖所有資料的例子,不使用多線程 

         CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);  

         OutputStreamClass4.putDataOnOutputStream(cbb.getOutputStream());  

         InputStreamClass4.processDataFromInputStream(cbb.getInputStream());  

     }  

   }  

   class OutputStreamClass4 {  

     public static void putDataOnOutputStream(OutputStream out) throws IOException {  

       byte[] bs = new byte[] { 1, 2, 3, 4, 5 };  

       out.write(bs);  

   class InputStreamClass4 {  

     public static void processDataFromInputStream(InputStream in) throws IOException {  

       byte[] bs = new byte[1024];  

       int len = in.read(bs);  

       for (int i = 0; i < len; i++) {  

         System.out.println(bs[i]);  

       }  

   }