Java 常见的 IO流

Posted 杨 戬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 常见的 IO流相关的知识,希望对你有一定的参考价值。

文章目录

IO流

IO 流的概念

流是Java对不同输入源输出源的抽象,代表了从起源到接收的有序数据,有了它程序就可以采用统一的方式来访问不同的输入源和输出源了。

从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出

IO 流的分类

按照数据的流向,可以将流分为输入流和输出流。其中,输入流只能读取数据、不能写入数据,而输出流只能写入数据、不能读取数据。

按照数据的类型,可以将流分为字节流和字符流。其中,字节流操作的数据单元是byte(字节),而字符流操作的数据单元是char(16位的字符)。

按照使用的场景,可以将流分为节点流和处理流。其中,节点流可以直接从/向一个特定的IO设备读/写数据,也称为低级流。而处理流则是对节点流的连接或封装,用于简化数据读/写功能或提高效率,也成为高级流。

Java IO流

流实现类

Java中的IO流主要有4个基类:InputStream、OutputStream、Reader、Writer。

  • InputStream代表字节输入流
  • OutputStream代表字节输出流
  • Reader代表字符输入流
  • Writer代表字符输出流

其他的IO流都是从这4个基类派生而来的,并且子类的名字往往以基类的名字结尾,所以通过类名我们很容易识别某个流的作用。

Java为我们提供了大量的IO流实现,我们没办法逐个介绍,下面举一些较为常用的例子:

  1. 用于访问文件的FileInputStream、FileOutputStream、FileReader、FileWriter。
  2. 带有缓冲功能的BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter。
  3. 具有转换功能的InputStreamReader、OutputStreamWriter。
  4. 支持打印功能的PrintStream、PrintWriter。

功能说明

文件专属(字节字符流,需要定义数组存储读取/写,read/write 方法)
java.io.FileInputStream(字节输入流,需要byte数组存储,可以读取任何文件)
java.io.FileOutputStream(字节输出流,需要byte数组存储)

java.io.FileReader(文件字符输入流,读取普通文本,需要char数组存储)
java.io.FileWriter(文件字符输出流。只能输出普通文本,需要char数组存储)

缓冲流
java.io.BufferedReader(带有缓冲区的字符输入流,不需要定义数组,有特殊的readLine方法,可以一行一行读)
java.io.BufferedWriter(带有缓冲区的字符输出流,不需要定义数组)
java.io.BufferedInputStream(字节缓冲输入流,效率高,需要定义数组)
java.io.BufferedOutputStream(字节缓冲输出流,效率高,需要定义数组)

转换流(将字节流转换为字符流)
java.io.InputStreamReader (字符字节输入流,将字节输入流转换为字符输入流)
java.io.OutputStreamWriter (字符字节输出流,将字节输出流转换为字符输出流)

打印流

java.io.PrintStream
java.io.PrintWriter

IO流代码应用

FileInputStream

package com.interview.module.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest 
    public static void main(String[] args) throws FileNotFoundException 

        //FileInputStream   Stream都是字节流  FileInputStream是可以读取任何文件的
        FileInputStream fis = null;
        try 
            fis = new FileInputStream("StreamFile/test.txt");

            // 开始读,采用byte数组,一次读取多个字节。最多读取“数组.length”个字节。
            byte[] bytes=new byte[1024];// 准备一个1024个长度的byte数组,一次最多读取1024个字节。

            int readCount = 0;
            // 这个方法的返回值是:读取到的字节数量。(不是字节本身);1个字节都没有读取到返回-1(文件读到末尾)
            while((readCount = fis.read(bytes)) != -1) 
                // 不应该全部都转换,应该是读取了多少个字节,转换多少个。
                System.out.print(new String(bytes, 0, readCount));
            
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
          catch (Exception e) 
            e.printStackTrace();
         finally 
            // 在finally语句块当中确保流一定关闭。
            if (fis != null) // 避免空指针异常!
                // 关闭流的前提是:流不是空。流是null的时候没必要关闭。
                try 
                    fis.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        

    

文件中:

控制台:

FileOutputStream

package com.interview.module.io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest 
    public static void main(String[] args) 

        FileOutputStream fos = null;
        try 
            // myfile文件不存在的时候会自动新建!
            // 这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入。
            //fos = new FileOutputStream("myfile");

            // 以追加的方式在文件末尾写入。不会清空原文件内容。
            fos = new FileOutputStream("StreamFile/test.txt",true);
            // 开始写。
            byte[] bytes = 97, 98, 99, 100;
            // 将byte数组全部写出!
            fos.write(bytes); // abcd
            // 将byte数组的一部分写出!
            fos.write(bytes, 0, 2); // 再写出ab

            // 字符串
            String s = "我是中国人。";
            // 将字符串转换成byte数组。
            byte[] bs = s.getBytes();
            // 写
            fos.write(bs);

            // 写完之后,最后一定要刷新
            fos.flush();
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
        catch (Exception e) 
            e.printStackTrace();
         finally 
            if (fos != null) 
                try 
                    fos.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        

    

文件中:

FileReader

package com.interview.module.io;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest 
    public static void main(String[] args) throws FileNotFoundException 

        //FileReader 文件字符输入流,只能读取普通文本。读取文本内容时,比较方便,快捷
        FileReader reader = null;
        try 
            // 创建文件字符输入流
            reader = new FileReader("StreamFile/test.txt");

            // 开始读
            char[] chars = new char[4]; // 一次读取4个字符
            int readCount = 0;
            while((readCount = reader.read(chars)) != -1) 
                System.out.print(new String(chars,0,readCount));
            
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();

         catch (Exception e) 
            e.printStackTrace();
         finally 
            if (reader != null) 
                try 
                    reader.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
    

FileWriter

package com.interview.module.io;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest 
    public static void main(String[] args) 

        //FileWriter文件字符输出流。写。只能输出普通文本。
        FileWriter out = null;
        try 
            // 创建文件字符输出流对象
            //out = new FileWriter("file");
            out = new FileWriter("StreamFile/test.txt", true);

            // 开始写。
            char[] chars = '你','是','程','序','媛','吗';
            out.write(chars);
            out.write(chars, 2, 3);  // 中国人

            out.write("我是一名java程序媛!");
            // 写出一个换行符。
            out.write("\\n");
            out.write("hello girl!");

            // 刷新
            out.flush();

         catch (Exception e) 
            e.printStackTrace();
         finally 
            if (out != null) 
                try 
                    out.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
    

文件中:

BufferedReader&InputStreamReader

package com.interview.module.io;

import java.io.*;

public class BufferReaderTest 

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

        FileReader reader = new FileReader("StreamFile/test.txt");
        // 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
        // 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
        // 像当前这个程序来说:FileReader就是一个节点流。BufferedReader就是包装流/处理流。
        BufferedReader br = new BufferedReader(reader);

        //BufferedReader br = new BufferedReader(  new FileReader("StreamFile/test.txt") );
        // br.readLine()方法读取一个文本行,但不带换行符。
        String s = null;
        while ((s = br.readLine()) != null) 
            System.out.println(s);
        

        // 关闭流
        // 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。(可以看源代码。)
        br.close();

       /*
        // 字节流
        FileInputStream in = new FileInputStream("StreamFile/test.txt");

        // 通过转换流转换(InputStreamReader将字节流转换成字符流。)
        // in是节点流。reader01是包装流。
        InputStreamReader reader01 = new InputStreamReader(in);

        // 这个构造方法只能传一个字符流。不能传字节流。
        // reader是节点流。br是包装流。
        BufferedReader br01 = new BufferedReader(reader01);
        */

        // 合并
        // BufferedReader br01 = new BufferedReader(new InputStreamReader(new FileInputStream("StreamFile/test.txt")));
        //
        // String line = null;
        // while ((line = br.readLine()) != null) 
        //     System.out.println(line);
        // 
        //
        // // 关闭最外层
        // br.close();
    

BufferedWriter&OutputStreamWriter

package com.interview.module.io;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;

public class BufferWriterTest 
    public static void main(String[] args) throws Exception

        //BufferedWriter
        BufferedWriter bw=new BufferedWriter( new FileWriter("StreamFile/test.txt"));

        bw.write("111");
        bw.write("\\n");
        bw.write("00000000");
        bw.flush();
        bw.close();


        //OutputStreamWriter  字节流转换成字符流
        // 带有缓冲区的字符输出流
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/test01.txt", true)));
        // 开始写。
        out.write("hello world!");
        out.write("\\n");
        out.write("hello girl!");
        // 刷新
        out.flush();
        // 关闭最外层
        out.close();
    

文件中:

BufferedInputStream&BufferedOutputStream

package com.interview.module.io;

import java.io.*;

public class BufferedInOutputStreamTest 
    public static void main(String[] args) 

        String srcFilePath = "C:\\\\Users\\\\Yang\\\\Desktop\\\\test1.jpg";
        String destFilePath = "C:\\\\Users\\\\Yang\\\\Desktop\\\\imagestest\\\\test1.jpg";

        //创建BufferedInputStream和BufferedOutputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try 
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //循环的读取文件,并写入到
            byte[] buff = new byte[1024];

            int readLen = 0;
            //当返回 -1时,就表示文件读取完毕
            while((readLen = bis.read(buff)) != -1)
                bos.write(buff,0,readLen);
            
            System.out.println("文件拷贝完成~~~");
         catch (Exception e) 
            e.printStackTrace();
        finally 
            //关闭外层的处理流即可,底层去关闭节点流
            try 
                if (bis != null)
                    bis.close();
                
                if(bos != null)
                    bos.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
    

文件拷贝成功

以上是关于Java 常见的 IO流的主要内容,如果未能解决你的问题,请参考以下文章

Java IO流中先关闭输出流还是先关闭输入流?为啥?

Java IO流-合并流

Java学习之IO流(序列流--SequenceInputStream)

Java 常见的 IO流

Java 常见的 IO流

Java 学习笔记 - IO篇:常见的IO流Stream以及相互关系