IO图解及Java中InputStream,OutputStream,FileReader,FileWriter用法

目录

一、IO(输入输出流)图例

二、字节流和字符流:

三、InputStream输入流(把数据从文件读取到内存中):

InputStream代码示例:

 四、OutputStream输出流(把数据从内存写入到目标文件中):

OutputStream代码示例:

 五、注意事项:


一、IO(输入输出流)图例

输入还是输出是相对内存(缓冲区)而言的,而InputStream和OutputStream读取的是二进制文件


二、字节流和字符流:

字节流字符流
读取方式基于二进制的读取方式基于字符的读取方式
Java中对应抽象类InputStream/OutputStreamReader/Writer
Java中对应实现类FileInputStream/FileOutputStreamFileReader/FileWriter

三、InputStream输入流(把数据从文件读取到内存中):

修饰符及 返回值类
方法名
说明
int
read()
读取一个字节的数据,返回 -1 代表已经完全读取完成
int
read(byte[]b)
最多读取 b.length 字节的数据到 b 中并返回实际读到的数
量; -1 代表以及读取完成
int
read(byte[] b,
int off, int len)
最多读取 len - off 字节的数据到 中,放在从 off 开始,返
回实际读到的数量; -1 代表读取完成
void
close()
关闭字节流(基于二进制的读取方式)

InputStream代码示例:


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

public class IO_InputStream {
    public static void main(String[] args) throws IOException {
        //创建输入流读取文件内容
        FileInputStream fileInputStream = new FileInputStream("E:\\temp\\test.txt");
        System.out.println("=======read()方法=======");
        //循环读取
        while(true){
            //每次只读一个字节
            int data = fileInputStream.read();
            if( data == -1) break;//读取完毕会返回-1
            //返回值为ASCII码值,转换成字符显示
            System.out.print((char)data);
        }
        System.out.println();

        System.out.println("=======read(byte[]b)方法=======");
        fileInputStream = new FileInputStream("E:\\temp\\test1.txt");
        byte[] data = new byte[2];//一次最多读取两个字节长度
        while (true){
            int len = fileInputStream.read(data);
            if(len == -1)  break;
            for(int i = 0; i < len; i++){
                System.out.print((char)data[i]);
            }

        }
        System.out.println();

        System.out.println("=======read(byte[] b,int off, int len)方法=======");
        fileInputStream = new FileInputStream("E:\\temp\\test2.txt");
        data = new byte[4];
        int off = 1;//从data[1]开始写入
        int length = 2;//每次读取两个字节长度
        while (true){
            int len = fileInputStream.read(data,off,length);
            if(len == -1)  break;//读取完成
            for(int i = off; i < len+1; i++){
                System.out.print((char)data[i]);
            }
        }


        fileInputStream.close();//关闭字节流(关闭水龙头)

    }
}

运行结果:

文件内容:


 四、OutputStream输出流(把数据从内存写入到目标文件中):

修饰符及 返回值类
方法名
说明
void
write(int b)
写入要给字节的数据
void
write(byte[] b)
b 这个字符数组中的数据全部写入 os
int
write(byte[] b, int off, int len)
b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len
void
close()
关闭字节流
void
flush()
重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为 了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写
入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的 数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置, 调用 flush (刷新)操作,将数据刷到设备中。

OutputStream代码示例:

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

public class IO_OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\temp\\OutputStream.txt");

        //============write(int b)方法============
        fileOutputStream.write(97);//字符a

        //============write(byte[] b)方法============
        byte[] data1 = {98,98,98};//写入三个a
        fileOutputStream.write(data1);
        //============write(byte[] b, int off, int len)方法============
        byte[] data2 = {97, 98, 99, 99, 99, 98, 97};
        //写入data2中的三个c即data[2]~data[4]
        int off = 2;
        int len = 3;
        fileOutputStream.write(data2, off, len);

        // 刷新一下缓冲区
        fileOutputStream.flush();
        //关闭字节流
        fileOutputStream.close();
        System.out.println("完成");
    }
}

程序运行前文件内容为空:

 程序运行后:

 五、FileReader

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

public class IO_FileReader {
    public static void main(String[] args) throws IOException {
        // 创建一个读取的字符流
        FileReader reader = new FileReader("E:/temp/FileReader.txt");
        // 循环读取
        while (true) {
            int data = reader.read();
            // 返回-1表示读取结束
            if (data == -1) {
                break;
            }
            // 打印结果
            System.out.print((char)data);
        }
        // 关闭流
        reader.close();
    }
}

文件内容:

 运行结果:

 六、FileWriter:

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

public class IO_FileWriter {
        public static void main(String[] args) throws IOException {
            // 创建一个基于字符的输出流
            FileWriter writer = new FileWriter("E:/temp/FileWriter.txt");
            // 写数据
            writer.write("hello world!!!");
            writer.write("\n");
            writer.write("你好世界!!!");
            // 清空缓冲区
            writer.flush();
            // 关闭流
            writer.close();
        }
    
}

运行前文件内容(空文件):

 运行后文件内容:

 

七、注意事项:

①使用flush()刷新的原因(详见上述表格),可以随地调用,但不建议频繁使用,没必要。

②关闭流的原因:进程启动时会在系统中申请资源,包括文件描述符表(就是一个数组)程序打开的每个文件都是一个文件描述符,会被写入到文件描述符表中,每个数据都有大小,如果不关闭字节流,数组始终会被写满,再打开其他文件的时候,数组没有多余空间,程序会卡住,而关闭字节流就是为了把当前文件从文件描述附表中删除。