Bootstrap

JAVA IO流的原理介绍和流的分类

  • IO流的原理

I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

输入input:读取外部数据(磁 盘、光盘等存储设备的数据)到 程序(内存)中。

输出output:将程序(内存) 数据输出到磁盘、光盘等存储设 备中。

  • 流(stream)的分类

概括

按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)


按数据流的流向不同分为:输入流,输出流

按流的角色的不同分为:节点流,处理流

节点流:直接从数据源或目的地读写数据

处理流:不直接连接到数据源或目的地,而是“连接”在已存 在的流(节点流或处理流)之上,通过对数据的处理为程序提 供更为强大的读写功能。

流的分类图例

IO流体系

  •  流的基础类

输入流基础类

前言

InputStream 和 Reader 是所有输入流的基类。 

程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资 源,所以应该显式关闭文件 IO 资源。

FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream 用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader 

InputStream

int read() 从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因 为已经到达流末尾而没有可用的字节,则返回值 -1。

int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。如果因为已 经到达流末尾而没有可用的字节,则返回值 -1。否则以整数形式返回实际读取 的字节数。

int read(byte[] b, int off,int len) 将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取 的字节也可能小于该值。以整数形式返回实际读取的字节数。如果因为流位于 文件末尾而没有可用的字节,则返回值 -1。

public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。

Reader

int read() 读取单个字符。作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff)(2个 字节的Unicode码),如果已到达流的末尾,则返回 -1 

int read(char[] cbuf) 将字符读入数组。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。

int read(char[] cbuf,int off,int len) 将字符读入数组的某一部分。存到数组cbuf中,从off处开始存储,最多读len个字 符。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。

public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。

 输出流基础类

前言

outputStream 和 writer 是所有输入流的基类。 

因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组, 即以 String 对象作为参数 :void write(String str); / void write(String str, int off, int len);

FileOutputStream 从文件系统中的某个文件中获得输出字节。FileOutputStream 用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter

OutputStream

void write(int b) 将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写 入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 即写入0~255范围的。

void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。write(b) 的常规协定是:应该 与调用 write(b, 0, b.length) 的效果完全相同。

void write(byte[] b,int off,int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

public void flush()throws IOException 刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立 即写入它们预期的目标。

public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。

Writer

void write(int c) 写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。 即 写入0 到 65535 之间的Unicode码。 

void write(char[] cbuf) 写入字符数组。

void write(char[] cbuf,int off,int len) 写入字符数组的某一部分。从off开始,写入len个字符

void write(String str) 写入字符串。

void write(String str,int off,int len) 写入字符串的某一部分。

void flush() 刷新该流的缓冲,则立即将它们写入预期目标。

public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。

  • 节点流(文件流)

注:以下代码演示均为字符流 (FileReader、FileWriter)的操作,处理字节流文件请更换为字节流(FileInputStream、FileOutputStream)

读取文件

步骤

//1.建立一个流对象,将已存在的一个文件加载进流。
FileReader fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));

//2.创建一个临时存放数据的数组。
char[] c = new char[1024];

//3.调用流对象的读取方法将流中的数据读入到数组中。
fr.read(c);

//4.关闭流的资源
fr.close();

 代码演示

读取的时候使用:int read()方法

FileReader fr = null;
try {
    //1.建立一个流对象,将已存在的一个文件加载进流。
    fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));

    //2.调用流对象的读取方法将流中的数据读入到数组中。
    int len;
    while ((len = fr.read()) != -1){
        System.out.print((char) len);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //3.关闭流的资源
    try {
        if (fr != null)
        fr.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

读取的时候使用:int read(char[] cbuf)方法

FileReader fr = null;
try {
    //1.建立一个流对象,将已存在的一个文件加载进流。
    fr = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));

    //2.创建一个临时存放数据的数组。
    char[] cfr = new char[1024];

    //3.调用流对象的读取方法将流中的数据读入到数组中。
    int len;
    while ((len = fr.read(cfr)) != -1){
        //方式1:
        for (int i = 0; i < len; i++) {
            System.out.print(cfr[i]);
        }
        
        //方式2:
        String str = new String(cfr,0,len);
        System.out.print(str);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //4.关闭流的资源
    try {
        if (fr != null)
        fr.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

写入文件

步骤

//1.创建流对象,建立数据存放文件
 FileWriter fw = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
//2.调用流对象的写入方法,将数据写入流
 fw.write("写入的数据。。。");
//3.关闭流资源,并将流中的数据清空到文件中。
 fw.close();

代码演示

FileWriter fw = null;
try {
    //1.创建流对象,建立数据存放文件
    fw = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\helloCopy.png"));

    //2.调用流对象的写入方法,将数据写入流
    fw.write("I am a superman\n");
    fw.write("you are a superman too");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //3.关闭流资源,并将流中的数据清空到文件中。
    if (fw != null){
        try {
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

读入文件和写入文件组合

FileReader srcFile = null;
FileWriter destFile = null;
try {
    //1.创建输入输出流的对象,指明读入和写出的文件
    srcFile = new FileReader(new File("E:\\JAVA\\java2\\src\\day8\\hello.png"));
    destFile = new FileWriter(new File("E:\\JAVA\\java2\\src\\day8\\hello1.png"));

    //2.数据的读入和写出操作
    char[] cbuf = new char[1024];
    //记录每次读入到cbuf数组中的字符的个数
    int len;
    while ((len = srcFile.read(cbuf)) != -1){
        //每次写出len个字符
        destFile.write(cbuf,0,len);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //3.关闭流资源
    /*//方式1:
    try {
        if (destFile != null)
        destFile.close();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            if (srcFile != null)
            srcFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/

    //方式2:
    try {
        if (destFile != null)
        destFile.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        if (srcFile != null)
        srcFile.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

节点流(或文件流):注意点</

;