首页 > 其他分享 >InputStream和OutputStream

InputStream和OutputStream

时间:2023-06-24 20:56:11浏览次数:41  
标签:OutputStream int InputStream read input byte

(一)说明

InputStreamOutputStream是Java标准库中最基本的IO流,它们都位于java.io包中,该包提供了所有同步IO的功能。

  • java.io.InputStream 、 java.io.OutputStream

(二)用法

1.read&write

InputStream和OutputStream都不是接口,而是抽象类,它们分别是所有输入流和输出流的超类。这两个抽象类定义了两个最重要的方法:

  • int read():读取输入流的下一个byte,返回该byte表示的int值(0~255)。读到末尾,返回-1表示不能继续读了。
  • void write( int b ):写一个byte到输出流。虽然传入的是int,但只会写入1 byte,即该int的最低8位表示字节的部分( b & 0xff )
public abstract int read() throws IOException;
public abstract void write(int b) throws IOException;

2.实现类

(1)FileInputStream:从文件流中读取数据

下面的代码演示了如何完整地读取一个FileInputStream的所有字节:

public void readFile throws IOException{
    //创建一个FileInputStream对象
    InputStream input = new FileInputStream("src/readme.txt");
    for(;;){
        int n = input.read(); //反复调用read(),直到返回-1
        if(n==-1){
            break;
        }
        System.out.println(n);//打印byte值
    }
    input.close();
}

在计算机中,应用程序如果打开了有一个文件进行读写,完成后要及时关闭,以便OS把资源释放。

(2)FileOutputStream:将若干字节写入文件流

下面代码演示了如何将多个bytes写入文件流:

public void writeFile() throws IOException{
    OutputStream output = new FileOutputStream("out/readme.txt");
    output.write(72);//H
    ...
    output.write(111);//o
    output.close();
}

每次写入1byte太麻烦,更常见的是一次性写入多个bytes。可以通过OutputStream提供的重载方法void write( byte[ ] )来实现:

public void writeFile() throws IOException{
    OutputStream output = new FileOutputStream("out/readme.txt");
    output.write("Hello".getBytes("UTF-8"));
    output.close();
}

3.close

在操作完之后,InputStream和OutputStream都需要通过close()来关闭流,之后OS会释放底层资源。

4.flush

只用于OutputStream,目的是将buffer内容真正输出到目的地

因为写的时候,出于效率考虑,OS不是每次直接把1 byte写入文件或发送到网络,而是先放到内存buffer(本质上是byte [ ]数组),等到buffer写满,再一次性写入文件或网络。

对所有IO设备来说,一次写1B或1000B,花费的时间几乎相同,所以OutputStream有flush()方法能强制把buffer内容输出

(1)调用时机

通常情况下,我们不需要调用这个flush(),因为

  1. buffer写满了OutputStream会自动调用它;
  2. 调用close()关闭OutputStream之前,也会自动调用flush()方法。

但是某些时机我们需要手动调用flush(),比如在实现一个即时通讯软件时,用户发一句就要flush一句,而不能等待buffer满。

(2)InputStream buffer

InputStream也有buffer。当从FileInputStream读取1 byte时,OS往往会一次性读取多个 bytes到buffer,read时直接返回buffer中的byte,而不是每次都IO 1 byte。

4.IOException

读写IO流时,可能发生错误,例如文件不存在、权限异常,它们由JVM封装为IOException抛出。

因此,所有与IO相关的代码都必须处理IOException

实际使用时,为了避免读取时发生IO错误,IO流无法正确关闭,资源也无法及时释放,所以我们要用try...finally来保证IO流正确关闭:

public void readFile() throws IOException {
        InputStream input = null;
        try {
            input = new FileInputStream("src/readme.txt");
            int n;
            while ((n = input.read()) != -1) {
                System.out.println(n);
            }
        } finally {
           if (input != null) {
                input.close();
            }
        }
    }

用try...finally来编写会感觉复杂,更好的写法是利用Java 7引入新的try(resource)语法,只需要编写try语法,就能让编译器自动为我们关闭资源。推荐写法如下:

//InputStream
public void readFile() throws IOException{
    try(InputStream input = new FileInputStream("src/readme.txt")){
        int n;
        while((n=input.read())!=-1)
            System.out.println(n);
    }//编译器在此自动为我们写入finally并调用close()
}

//OutputStream
public void writeFile() throws IOException{
    try(OutputStream output = new FileOutputStream("out/readme.txt")){
      output.write("Hello".getBytes("UTF-8"));//Hello
    }
}

同时操作多个资源时,在try(resource){ ... }中可以同时写出多个资源,用;隔开。例如同时读写两个文件:

        //读取input.txt,写入output.txt
        try(InputStream input = new FileInputStream("input.txt");
        OutputStream output = new FileOutputStream("output.txt")){
            input.transferTo(output);
        }

不过实际上,编译器并不会特别为InputStream加上自动关闭。只看resource是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally并调用close()方法。InputStream、OutputStream都实现了这个接口,因此都可以用在try( resoucrce )中。

(三)缓冲

IO流中,每次用read()、write()读写1 byte未免太麻烦了。IO流各提供了两个重载方法来支持读写多个字节:

  • read( byte[ ] b ):从输入流中读取一定数量的bytes,并将之存入缓冲数组b中;
  • read( byte[ ] b , int off , int len ):从输出流中off byte处开始读取len bytes到缓冲数组b中;
  • write( byte[ ] b ):将b中的所有byte写入输出流中;
  • write( byte[ ] b , int off , int len ):从b中的off处开始,写入len bytes到输出流中。

利用read方法一次读取多个bytes时,需要先定义一个byte[ ]作为buffer,read会尽可能多的读取byte到buffer,但不会超过buffer大小。read返回实际读取的byte数,如果返回-1,表示没有更多的数据了

read

用buffer一次读取多个bytes的代码如下:

public void readFile() throws IOException{
    try(InputStream input = new FileInputStream("src/readme.txt")){
        byte[] buffer = new byte[1000];
        int n;
        while((n=input.read(buffer))!=-1)//读取到buffer
            System.out.println("read "+n+" bytes.");
    }
}

(四)阻塞

之前我们说过java.io是同步io在进行IO时,会中断程序运行,直到数据IO完毕——此之谓阻塞

(五)其他InputStream实现类

用FileInputStream可以从文件获取输入流,这是InputStream常用的一个实现类。

1.ByteArrayInputStream

在内存中模拟一个InputStream:

public class Main {
    public static void main(String[] args) throws IOException {
        byte [] data ={ 72, 101, 108, 108, 111, 33 };
        try(InputStream input = new ByteArrayInputStream(data)){
            int n;
            while((n=input.read())!=-1)
                System.out.println((char)n);
        }
    }
}

ByteArrayInputStream实际上是把一个byte[ ]数组在内存中变成一个InputStream,虽然应用不多,但测试时可以用来构造一个InputStream。

(六)其他OutputStream实现类

1.ByteArrayOutputStream

在内存中模拟一个OutputStream:

public class Main {
    public static void main(String[] args) throws IOException {
        byte[] data;
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            output.write("Hello".getBytes("UTF-8"));
            output.write("world!".getBytes("UTF-8"));
            data = output.toByteArray();
        }
        System.out.println(new String(data, "UTF-8"));
    }
}

(七)总结

1、InputStream、OutputStream是最基本的IO流,它传输的数据基本单位是byte

常用的方法有:

  • int read():读取输入流的下一个byte,返回该byte表示的int值(0~255)。读到末尾,返回-1表示不能继续读了。
  • read( byte[ ] b ):从输入流中读取多个bytes,并将之存入缓冲数组b[ ]中;
  • read( byte[ ] b , int off , int len ):从输出流中off byte处开始读取len bytes到缓冲数组b中;
  • void write( int b ):写一个byte到输出流。虽然传入的是int,但只会写入1 byte,即该int的最低8位表示字节的部分( b & 0xff )
  • write( byte[ ] b ):将b中的所有byte写入输出流中;
  • write( byte[ ] b , int off , int len ):从b中的off处开始,写入len bytes到输出流中。

常见实现类有:

  • FileXXXStream:文件读写;
  • ByteArrayXXXStream:在内存中模拟IO流。

2、用法

//InputStreampublic 
void readFile() throws IOException{
    try(InputStream input = new FileInputStream("src/readme.txt")){
        byte[] buffer = new byte[1000];
        int n;
        while((n=input.read(buffer))!=-1)//读取到buffer
            System.out.println("read "+n+" bytes.");
    }
}
//OutputStream
public void writeFile() throws IOException{
    try(OutputStream output = new FileOutputStream("out/readme.txt")){
      output.write("Hello".getBytes("UTF-8"));//Hello
    }
}

也可以把InputStream和OutputStream资源的创建放在一起:

//读取input.txt,写入output.txt
try(InputStream input = new FileInputStream("input.txt");
OutputStream output = new FileOutputStream("output.txt")){
    input.transferTo(output);
}

 

标签:OutputStream,int,InputStream,read,input,byte
From: https://www.cnblogs.com/imreW/p/17501670.html

相关文章

  • InputStream和Reader区别
    InputStream,OutputStream  前者为字节输入流,后者为字节输出流。Reader   Writer  前者为字符输入流,后者为字符输出流。四个均为抽象类。fileInputStream 是InputStream 的实现类  fileReader 是Reader 的实现类字节流读取单位为一个字节,字符流读取单位为一个字符......
  • IO流 p9 转换流-InputStreamReader 和 OutputStreamWriter
    转换流-InputStreamReader和OutputStreamWriter介绍InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流);OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流);当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文......
  • p6 BufferedInputStream 和 BufferedOutputStream
    BufferedInputStream和BufferedOutputStreamBufferedInputStreamBufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组。构造方法摘要ConstructorandDescriptionBufferedInputStream(InputStreamin)创建一个BufferedInputStr......
  • Java-Day-25( 字节输入流 + FileInputStream 和 FileOutputStream + FileReader 和 Fi
    Java-Day-25InputStream(字节输入流)InputStream抽象类是所有类字节输入流的超类InputStream常用的子类FileInputStream:文件输入流BufferedInputStream:缓冲字节输入流ObjectInputStream:对象字节输入流FileInputStream和FileOutputStreamFileInputStream(文......
  • inputstream转json
    inputstream是一个Java中的输入流,它允许从源读取数据。如果要将inputstream转换为JSON,需要使用相应的解析器,例如GSON或Jackson。以下是使用GSON的示例代码:InputStreaminputStream=...;Gsongson=newGson();JsonReaderreader=newJsonReader(newInputStreamReader(in......
  • 将字节数组输入流拷贝成字节数组输出流,将ByteArrayInputStream转成ByteArrayOutputStr
    /**将ByteArrayInputStream拷贝成ByteArrayOutputStream*将字节数组输入流拷贝成字节数组输出流*/publicstaticByteArrayOutputStreamgetByteArrayOutputStream(ByteArrayInputStreaminputStream)throwsIOException{ByteArrayOutpu......
  • java.lang.NoClassDefFoundError: org/apache/commons/io/output/UnsynchronizedByteA
    java.lang.NoClassDefFoundError:org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream  一、问题现象在导出Excel过程中,程序报错如下:Exceptioninthread"main"java.lang.NoClassDefFoundError:org/apache/commons/io/output/UnsynchronizedByteArra......
  • java:文件写入BufferedOutputStream写入字节和PrintWriter写入字符
    BufferedOutputStream和FileOutputStream写入二进制字节方法定义publicBufferedOutputStream(OutputStreamout){示例BufferedOutputStreamwriter=newBufferedOutputStream(newFileOutputStream("demo.txt"));writer.write("helloworld".getBytes());w......
  • convert InputStream to String
      publicStringgetContent(finalURLurl){try{InputStreaminputStream=url.openStream();returnnewScanner(inputStream).useDelimiter("\\A").next();}catch(finalExceptione){......
  • getOutputStream() has already been called for this response
    java.lang.IllegalStateException:getOutputStream()hasalreadybeencalledforthisresponse getOutputStream()hasalreadybeencalledforthisresponse问题的解决在jsp向页面输出图片的时候,使用response.getOutputStream()会有这样的提示:java.lang.IllegalStateExcep......