I/O流-输入输出流

418 阅读5分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

根据数据流向不同分为:输入流和输出流。

输入流--InputStream

java.io.InputStream类是所有Java IO输入流的基类,它是以字节为单位的输出流。

类图展示

  •  ByteArrayInputStream:字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中

  • FileInputStream:从文件读取数据

  • ObjectInputStream:反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象,以流的方式读取对象。

  • PipedInputStream管道读取流

  • FilterInputStream]是过滤输出流

  • BufferedInputStream: 提供了缓冲功能。

  • DataInputStream: 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。

  • PipedInputStream: 允许以管道的方式来处理流。当连接到一个PipedOutputStream后,它会读取后者输出到管道的数据。

  • PushbackInputStream: 允许放回已经读取的数据。

  • SequenceInputStream: 能对多个inputstream进行顺序处理。

inputStream主要api方法

  • read:读取数据流字节,存储到缓冲区数组

    public abstract int read() public int read(byte[] b) public int read(byte[] b,int off,int len)

available():获取数据流字节长度大小close():关闭并且释放流资源mark(int readlimit):设置输入流的当前位置reset():重新定位输入流的位置skip(long n):跳过并丢弃输入流的n个字节

FileInputStream。

FileInputStream读取文件。

/**
* 读取filePath的文件,将文件中的数据按照行读取到String数组中
* @param filePath    文件的路径
* @return         文件中一行一行的数据
*/
public static String[] readToString(String filePath) {
    File file = new File(filePath);
    Long filelength = file.length(); // 获取文件长度
    byte[] filecontent = new byte[filelength.intValue()];
    try {
        FileInputStream in =new FileInputStream(file); in .read(filecontent); in .close();
    } catch(FileNotFoundException e) {
        e.printStackTrace();
    } catch(IOException e) {
        e.printStackTrace();
    }

    String[] fileContentArr = new String(filecontent).split("\r\n");

    return fileContentArr; // 返回文件内容,默认编码
}

输入流--outputStream

  • OutputStream类是Java IO API中所有输出流的基类。子类包括BufferedOutputStream,FileOutputStream等等。

  • OutputStream是一个典型的装饰者模式,使用的时候直接new子类。

  • utputStream可以输出到console,文件,磁盘等目标媒介中。

类图展示

  • OutputStream是以字节为单位的输出流的超类,提供了write()函数从输出流中读取字节数据。

  • ByteArrayOutputStream是字节数组输出流,写入ByteArrayOutputStream的数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()获取数据。

  • PipedOutputStream是管道输出流,和PipedInputStream一起使用,能实现多线程间的管道通信。

  • FilterOutputStream是过滤输出流,是DataOutputStream,BufferedOutputStream和PrintStream的超类

  • DataOutputStream是数据输出流,用来装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。

  • BufferedOutputStream是缓冲输出流,它的作用是为另一个输出流添加缓冲功能。

  • PrintStream是打印输出流,用来装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值

  • FileOutputStream是文件输出流,通常用于向文件进行写入操作。

  • ObjectOutputStream是对象输出流,它和ObjectInputStream一起对基本数据或者对象的持久存储

outputStream主要api方法

  • write():将数据写入输出流

  •   public abstract void write(int b)
      public void write(byte[] b)
      public void write(byte[] b,int off,int len)
    
  • close():关闭并且释放流资源

  • flush():刷新此输出流并强制写出所有缓冲的输出字节

代码示例:

// 模拟浏览器,给tomcat服务端发送符合http协议的请求消息  
public static void main(String[] args) throws IOException
{
    Socket s = new Socket("127.0.0.1", 80);
    PrintWriter out = new PrintWriter(s.getOutputStream()); //这里的ture表示流会自动刷新,在后面可以不用使用flush()方法  
    out.println("GET /myweb/test.jsp HTTP/1.1");
    out.println("Accept: */*");
    out.println("Accept-Language: zh-CN");
    out.println("Accept-Encoding: gzip, deflate");
    out.println();
    out.flush(); // 清空缓存并输出流
    InputStream in = s.getInputStream();
    byte b[] = new byte[1024];
    int leng = 0;
    while((leng = in .read(b)) != -1)
    {
        String str = new String(b, 0, leng);
        System.out.println(str);
    }
    s.close();
}

FilterOutputStream类

FileOutputStream写入文件中

public static String[] readToString(String filePath1,String filePath2) {
    InputStream is = new FileInputStream(filePath1);
    FileOutputStream fos = new FileOutputStream(filePath2);
    byte[] b = new byte[1024];
    while ((is.read(b)) != -1) {
        fos.write(b);// 写入数据
    }
    is.close();
    fos.close();// 保存数据
}

ByteArrayOutputStream类

ByteArrayOutputStream在内存中创建了一个字节数组,所有发送到输出流的数据都会保存到该字节数组的缓冲区中。数据写入缓冲区以后,然后使用toByteArray()和toString()输出。

public static void main(String[] args)
{
    ByteArrayOutputStream bos = null;
    FileInputStream fs = null;
    try
    {
        bos = new ByteArrayOutputStream();
        fs = new FileInputStream("c:\\51gjie.txt");
        int len;
        while((len = fs.read()) != -1)
        {
            // 把读取到的数据逐个写到ByteArrayOutputStream中
            bos.write(len);
        }
        byte[] array = bos.toByteArray();
        // 指定utf-8解码的字符集
        System.out.println(new String(array, "utf-8"));
        fs.close();
    }
    catch(IOException e)
    {}
    finally
    {
        fs.close();
    }
}

DataOutputStream类

DataOutputStream允许应用程序以与机器无关方式将Java基本数据类型(boolean,byte,int,long,string等)写到底层输出流。

public static void main(String[] args) throws IOException
{
    FileOutputStream in = new FileOutputStream("c\\51gjie.txt");
    DataOutputStream out = new DataOutputStream( in );
    String string = "欢迎来到www.51gjie.com";
    out.writeBytes(string);
    out.writeChars(string);
    out.writeUTF(string);
    out.close();
    System.out.println("写入成功!");
}

BufferedOutputStream类

1. 当创建BufferedOutputStream时,会创建一个内部缓冲区数组,应用程序可以向底层输出流写入字节数据,当写入数据时,可以不用每次都去调用底层方法,而是直接从缓存区获取数据。

2. BufferedOutputStream缓冲输出流在输出的时候,不是直接一个字节一个字节的操作,而是先写入内存的缓冲区内。直到缓冲区满了或者我们调用close方法或flush方法,该缓冲区的内容才会写入目标。才会从内存中转移到磁盘上,因此效率是非常高的。

public static void main(String[] args) throws IOException
{
    OutputStream os = new FileOutputStream("c:/51gjie.txt");
    OutputStream bs = new BufferedOutputStream(os);
    byte[] buffer = "欢迎来到www.51gjie.com".getBytes();
    bs.write(buffer);
    bs.close();//写入文件
    os.close();
}

如果文件太大,一次性读取这个大文件的所有数据,内存可能装不下,但是如果每次只读一个字节数据,会耗时太慢。因此用BufferedInputStream一次读取1024*8个字节数据,用BufferedOutputStream放入缓冲区,分批读写。代码如下:

public static void main(String[] args) throws IOException
{
    BufferedInputStream bufferInput = null;
    BufferedOutputStream bufferOutput = null;
    try
    {
        // 输入缓冲流
        InputStream input = new FileInputStream(new File("c:\\100MB.txt"));
        bufferInput = new BufferedInputStream(input);
        // 输出缓冲流
        OutputStream output = new FileOutputStream(new File("c:\\100MB_test.txt"));
        bufferOutput = new BufferedOutputStream(output);
        // 定义个8kb字节数组,作为缓冲区流
        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        while((len = bufferInput.read(bytes)) != -1)
        {
            bufferOutput.write(bytes, 0, len);
        }
    }
    catch(IOException e)
    {
    }
    finally
    {
        try
        {
            if(bufferInput != null)
            {
                bufferInput.close();
            }
            if(bufferOutput != null)
            {
                bufferOutput.close();
            }
        }
        catch(IOException e)
        {
        }
    }
}