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(){
  class1.putDataOnOutputStream(out);
  }
  }
  ).start();
  class2.processDataFromInputStream(in);|||
  方法三:使用循环缓存区
  方法二中的两个管道流,实际上管理着一个隐藏的循环缓存区。使用一个显式的循环缓存区更易于理解。CircularBuffers 有如下优点
  一个CircularBuffers类而不是两个管道类。
  较于缓存所有数据和额外线程的方法更容易使用。
  你可以更改缓存大小而不必受限于管道缓存区1K的固定缓存大小。
  多线程情形:
  CircularByteBuffer cbb = new CircularByteBuffer();
  new Thread(
  new Runnable(){
  public void run(){
  class1.putDataOnOutputStream(cbb.getOutputStream());
  }
  }
  ).start();
  class2.processDataFromInputStream(cbb.getInputStream());
  单线程情形
  // buffer all data in a circular buffer of infinite size
  CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
  class1.putDataOnOutputStream(cbb.getOutputStream());
  class2.processDataFromInputStream(cbb.getInputStream());
作者“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]);  
          }  
        }
      }
 
二:
 
        package test.io;  
        import java.io.IOException;  
        import java.io.PipedInputStream;  
        import java.io.PipedOutputStream;  
        /**
         * 用于把OutputStream 转化为 InputStream。 适合于数据量大的情况,一个类专门负责产生数据,另一个类负责读取数据。
         * 
         * @author 赵学庆 www.java2000.net
         */ 
      public class Test2 {  
        /**
         * @param args
         * @throws IOException
         */ 
        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;  
         /**
         * 用于把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 Test3 {  
        /**
         * @param args
         * @throws IOException
         */ 
        public static void main(String[] args) throws IOException {  
          // 使用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) {  
          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();  
          }  
        }  
      } 
 
此方法使用了一个类处理,代码更简洁,可以很方便的在缓冲处理全部数据的小数据量情况和多线程处理大数据量的不同情况切换
 
     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]);  
       }  
     }  
   } 

相关文章
|
3月前
|
Java 数据处理 开发者
Java IO流专家级教程:深入理解InputStream/OutputStream和Reader/Writer的内部机制
【6月更文挑战第26天】Java IO流涉及字节流(InputStream/OutputStream)和字符流(Reader/Writer),用于高效处理数据输入输出。InputStream/OutputStream处理二进制数据,常使用缓冲提升性能;Reader/Writer处理文本,关注字符编码转换。两者都有阻塞IO操作,但Java NIO支持非阻塞。示例代码展示了如何使用FileInputStream/FileOutputStream和FileReader/FileWriter读写文件。理解这些流的内部机制有助于优化代码性能。
88 0
|
3月前
|
Java 开发者
Java IO流实战技巧:如何优化InputStream/OutputStream和Reader/Writer的使用?
【6月更文挑战第26天】Java IO流优化涉及缓冲、资源管理、字符编码和流式处理。使用Buffered流提高读写效率,如`BufferedInputStream`和`BufferedReader`。确保资源关闭使用try-with-resources,如`try (InputStream is = ...) {...}`。处理文本时指定编码,如`InputStreamReader(is, StandardCharsets.UTF_8)`防止乱码。流式处理大文件,分块读写避免内存溢出,以减少内存占用。这些技巧能提升程序性能和健壮性。
144 0
|
3月前
|
Java
Java IO流终极指南:从InputStream/OutputStream到Reader/Writer的全面解读
【6月更文挑战第26天】Java IO流涵盖字节流(InputStream/OutputStream)和字符流(Reader/Writer),前者处理二进制数据,后者专司文本。例如,FileInputStream/FileOutputStream用于文件的字节级读写,而FileReader/FileWriter处理字符级文本。Buffered流提供缓冲功能,提升效率。选择合适的流类取决于数据类型和性能需求。
54 0
|
3月前
|
存储 设计模式 Java
Java IO流大揭秘:如何高效使用InputStream/OutputStream和Reader/Writer?
【6月更文挑战第26天】Java IO流核心基础,涉及InputStream/OutputStream(字节流)和Reader/Writer(字符流)。高效使用的关键包括:使用Buffered流提升性能,如BufferedInputStream和BufferedOutputStream;处理编码,通过InputStreamReader和OutputStreamWriter指定如UTF-8编码;应用装饰器模式,如DataOutputStream增强功能。理解并巧妙运用这些技巧能优化数据读写操作。
44 0
|
3月前
|
Java
深入探索Java IO流:InputStream/OutputStream与Reader/Writer的奥秘!
【6月更文挑战第26天】Java IO流用于输入输出操作,包括字节流(InputStream/OutputStream)和字符流(Reader/Writer)。InputStream和OutputStream处理字节数据,是所有字节流的基类,可被继承以自定义读写行为。
41 0
|
3月前
|
Java API
Java中使用InputStream读入Jar/zip内容
Java中使用InputStream读入Jar/zip内容
25 0
|
4月前
|
Java 对象存储
Java解决InputStream流重复使用问题【100%解决】
Java解决InputStream流重复使用问题【100%解决】
|
4月前
|
XML Java 数据格式
Java OutputStream写入文件与文件复制
本文目录 1. 知识点 2. 写入文件示例 3. 文件复制示例
687 0
Java OutputStream写入文件与文件复制
|
5天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)