Day12 JavaSE IO原理及流的引入(上)

JavaSE IO原理及流的引入(上)

  • IO流用来处理设备之间的数据传输。

  • Java中,对于数据的输入/输出操作以“流(Stream)”的方式进行。

  • java.io包下提供了各种“流”类和接口,用来获取不同种类的数据,并通过标准的方法输入或输出数据。

Java IO原理

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

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

流的分类

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

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

按照流的角色不同分为:结点流、处理流

抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

1 文件流

1.1 文件字节流

  • 文件字节输入流

    FileInputStream in = new FileInputStream("file");

    重点关注int read(byte[] b)的使用

  • 文件字节输出流

    FileOutputStream out = new FileOutputStream("file")

    重点关注out.write(str.getBytes())out.flush()的使用

注意:字节流使用完毕后一定要关闭

文件输入输出流案例:

package com.io;

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

public class Demo02 {
    public static void main(String[] args) {
        testFileInputStream();
        testFileOutputStream();

    }
    //文件字节输入流
    public static void testFileInputStream(){
        try {
            FileInputStream in = new FileInputStream("/Users/demut/Documents/File/aaa.txt");

            byte[] b = new byte[100]; //设置一个byte数组接受读取的文件内容
            int len = 0;//设置一个读取数据的长度

//            in.read(b);//读取字符到b数组,返回读取到的字符个数,如果是文件结尾返回-1
            while((len = in.read(b)) != -1){
                System.out.println(new String(b,0,len));
                //new String(b,0,len)表示从0开始读取,总共转换len个字节
            }
            in.close();//流在使用完毕之后一定要关闭
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //文件字节输出流
    public static void testFileOutputStream(){
        try {
            FileOutputStream out = new FileOutputStream("/Users/demut/Documents/File/aaa.txt");
            String str = "aaaaaabbbbbbbccc";
            out.write(str.getBytes());//把数据写入内存
            out.flush(); //将内存中的数据刷写到硬盘上

            out.close();//关闭流
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

复制文件到指定文件/文件夹案例:

package com.io;

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

//复制文件到指定文件夹下
public class Demo03 {
    public static void main(String[] args) {
        //将aaa.txt中内容写入到tt1.txt文件中
        copyFile("/Users/demut/Documents/File/aaa.txt","/Users/demut/Documents/File/tt1.txt");
    }

    public static void copyFile(String inPath, String outPath){
        try {
            FileInputStream in = new FileInputStream(inPath);
            FileOutputStream out = new FileOutputStream(outPath);

            byte[] b = new byte[100];

            int len = 0;
            while ((len = in.read(b)) != -1){
                out.write(b, 0, len); //b表示缓冲数组,0表示从数组的位置开始写,len表示获取的数组总长度
            }
            out.flush();
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

结果展示:(写入成功!)

运行前:
运行前
运行后:
运行前

注意: 文件字节流非常通用,可以用来操作字符的文档,还可以操作任何的其他类型文件(图片,压缩包等),因为字节流直接使用二进制。

1.2 文件字符流

  • 文件字符输入流

    读取文件操作步骤:

    1. 建立一个流对象,将已存在的一个文件加载进流。

      FileReader fr = FileReader("Test.txt");

    2. 创建一个临时存放数据的数组。

      char[] ch = new char[1024];

    3. 调用流对象的读取方法将流中的数据读入到数组中。

      fr.read(ch)

  • 文件字符输出流

    数据写入文件操作步骤:

    1. 建立一个流对象,将已存在/不存在的一个文件加载进流。

      FileWriter fw = FileWriter("Test.txt");

    2. 将读取到的字符数组/字符串/数字写入内存中。

      fw.write(text);

    3. 把内存中数据刷到硬盘中,即写入文件。

      fw.flush();

注意: 无论是输入流/输出流,使用完毕一定要关闭流

文件字符输入&&输出流案例:

package com.io;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test4 {
    public static void main(String[] args) {
        File file = new File("/Users/demut/Documents/File/ttt.txt");
        testFileReader(file.toString()); //读取原文件中字符串
        testFileWriter("HelloWorld",file.toString()); //写入新的字符串到文件中
        testFileReader(file.toString()); //读取更改后文件内部的字符串
    }

    /**
     * 文件字符输入流
     * @param inPath 读取的文件
     */
    public static void testFileReader(String inPath){
        try {
            FileReader fr = new FileReader(inPath);//创建文件字符输入流的对象

            char[] c = new char[10]; //创建临时存放数据的数组-->一次最多存放10个

            int len = 0; //定义一个输入流的读取长度
            while ((len = fr.read(c)) != -1){
                System.out.println(new String(c, 0, len));
            }
            fr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  
    /**
     * 文件字符输出流FileWriter
     * @param text 输出的内容
     * @param outPath   输出的文件
     */
    public static void testFileWriter(String text, String outPath){
        try {
            FileWriter fw = new FileWriter(outPath);

            fw.write(text); //写到内存中
            fw.flush(); //把内存数据刷到硬盘中
            fw.close(); //关闭流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

更改前:
更改前
更改后:
更改后

使用字符流拷贝文件到指定文件案例:

package com.io;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test4 {
    public static void main(String[] args) {
              copyFile("/Users/demut/Documents/File/ttt.txt",
                       "/Users/demut/Documents/File/aaa/ttt1.txt");
    }
  
    /**
     *  字符流完成拷贝文件,字符流只适合操作内容是字符的文件
     * @param inPath
     * @param outPath
     */
    public static void copyFile(String inPath, String outPath){
        try {
            FileReader fr = new FileReader(inPath);
            FileWriter fw = new FileWriter(outPath);

            char[] c = new char[1024];

            int len = 0;

            while ((len = fr.read(c)) != -1){ //读取数据
                fw.write(c,0,len); //写入数据到内存中
            }
            fw.flush(); //内存数据刷新到硬盘

            fw.close();
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

运行前:
文件复制前
运行后:
文件复制后

注意:

  • 字符流只适合操作内容是字符的文件!
  • 在写入一个文件时,如果目录下有同名文件将被覆盖。
  • 在读取文件时,必须保证文件存在,否则会异常。

2 缓冲流(基于内存的操作)

我们之前提到的文件流:FileInputStream, FileOutputStream,FileReader, FileWrite

这些都是计算机与硬盘之间发生的io操作,基于硬盘的读写相对不较慢,这个操作的速度收到硬盘的读写速度制约,为了能够提高读写速度,一定程度上绕过硬盘的限制,java提供了缓冲流来实现。

为了提高数据读写的速度,JavaAPI提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组。

缓冲流就是先把数据缓冲到内存中,在内存中去做io操作,基于内存的io操作比基于硬盘的io操作快75000多倍。

2.1 缓冲字节流

使用与文件字符流使用相像,但是声明过程为以下:

  • 缓冲字节输入流:

    FileInputStream in = new FileInputStream("...");

    BufferedInputStream br = new BufferedInputStream(in);

  • 缓冲字节输出流

    FileOutputStream out = new FileOutputStream("...");

    BufferedOutputStream bo = new BufferedOutputStream(out)

案例展示:(本案例展示缓冲字节输入、输出流及拷贝文件的操作)

package com.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Test5 {
    public static void main(String[] args) throws Exception {
        testBufferedInputStream();
        testBufferedOutputStream();
        copyFile();
    }

    /**
     * 缓冲字节输入流
     * @throws Exception
     */
    public static void testBufferedInputStream() throws Exception{

        //文件字节输入流对象
        FileInputStream in = new FileInputStream("/Users/demut/JAVASE Project" +
                                                    "/JavaSE/基础语法/src/com/io/aaa.txt");

        //把文件字节输入流放到缓冲字节输入流对象
        BufferedInputStream br = new BufferedInputStream(in);

        byte[] b = new byte[10];

        int len = 0;

        while ((len = br.read(b)) != -1){
            System.out.println(new String(b,0,len));//将比特数组转换为字符串
        }

        //关闭流的时候顺序要求:后开的流先关闭
        br.close();
        in.close();
    }

    /**
     * 缓冲字节输出流
     * @throws Exception
     */
    public static void testBufferedOutputStream() throws Exception{

        //创建字节输出流对象
        FileOutputStream out = new FileOutputStream("/Users/demut/JAVASE Project" +
                                                    "/JavaSE/基础语法/src/com/io/aaa.txt");

        //把字节输出流对象放到缓冲字节输出流中
        BufferedOutputStream bo = new BufferedOutputStream(out);

        String str = "Hello World";

        bo.write(str.getBytes()); //写入内存中

        bo.flush(); //内存中数据刷到硬盘上

        bo.close(); //关闭流
        out.close(); //关闭流
    }

    /**
     * 拷贝文件
     * @throws Exception
     */
    public static void copyFile() throws Exception{

        //缓冲输入流
        BufferedInputStream br = new BufferedInputStream(new FileInputStream("/Users/demut/JAVASE Project" +
                                                                    "/JavaSE/基础语法/src/com/io/aaa.txt"));
        //缓冲输出流
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("/Users/demut/JAVASE Project" +
                                                                    "/JavaSE/基础语法/src/com/io/bbb.txt"));
        byte[] b = new byte[1024];

        int len = 0; //len接受读取到的数据的长度,直到读取到最后(返回-1)

        while ((len = br.read(b)) != -1){
            bo.write(b,0,len); //数据写入内存中
        }
        bo.flush(); //数据从内存刷新到硬盘中

        bo.close();
        br.close();
    }
}

结果展示:(仅展示拷贝文件结果)

程序运行前:
拷贝前
程序运行后:
拷贝后

2.2 缓冲字符流

同样与上述使用十分相似,注意声明语句如下:

  • 缓冲字符输入流:

    FileReader fr = new FileReader("...");

    BufferedReader br = new BufferedReader(fr);

  • 缓冲字节输出流

    FileWriter fw = new FileWriter("...");

    BufferedWriter bw = new BufferedWriter(fw)

案例展示:(本案例展示缓冲字符输入、输出流及拷贝文件的操作)

package com.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

/**
 * 缓冲字符流
 */
public class Test6 {
    public static void main(String[] args) throws Exception{
        //testBufferedReader();
        //testBufferedWriter();
        copyFile();
    }

    /**
     * 缓冲字符输入流
     * BufferedReader
     * @throws Exception
     */
    public static void testBufferedReader() throws Exception{
        FileReader fr = new FileReader("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/aaa.txt");

        BufferedReader br = new BufferedReader(fr);

        char[] c = new char[100];

        int len = 0;
        while ((len = br.read(c))!=-1){
            System.out.println(new String(c,0,len));
        }
        br.close();
        fr.close();
    }

    /**
     * 缓冲字符输出流
     * BufferedWriter
     * @throws Exception
     */
    public static void testBufferedWriter() throws Exception{
        FileWriter fw = new FileWriter("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/bbb.txt");

        BufferedWriter bw = new BufferedWriter(fw);
        String str = "JeverDemut";

        bw.write(str); //写入内存
        bw.flush(); //刷入硬盘

        bw.close();
        fw.close();
    }

    /**
     * 使用缓冲字符流拷贝文件
     * @throws Exception
     */
    public static void copyFile() throws Exception{
        BufferedReader br = new BufferedReader(new FileReader("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/bbb.txt"));

        BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ccc.txt"));

        char[] c = new char[100];
        int len  = 0;
        while ((len = br.read(c))!=-1){
            bw.write(c,0,len);
        }
        bw.flush();

        bw.close();
        br.close();
    }
}

结果展示:(仅展示拷贝文件结果)

程序运行前:
复制前
程序运行后:
复制后

注意:缓冲流是把数据缓冲到内存中。

**JavaSE IO原理及流的引入(下)**重点介绍以下流:

转换流、打印流(了解)、数据流(了解)、对象流 —涉及序列化、反序列化、随机存取文件流

写在最后

My darling,我和FF99FF时刻在想你!

To Dottie!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章