JAVA - IO 流

字节流

FileOutputStream

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

public class FileOutPutStreamDemo {

    /*
    FileOutputStream 使用细节:
    1.write方法 写出的数字: 是ASCCI表中字符对应的数字,因此97 =>a
    2.创建FileOutputStream 对象时 “E:\javaProject\myio\a.txt”,a.txt 可以不存在,但是父级路径一定要存在
    3.如果a.txt 已经存在会产生覆盖的效果
     */
    public static void main(String[] args) throws IOException {

        FileOutputStream fos = new FileOutputStream("E:\\javaProject\\myio\\a.txt");

        byte[] b = {97,98,99,100};  //文件中是 abcd
 
        fos.write(b);

        fos.close();
    }
}

重载的write方法:

思考: write 方法传入一个 char类型'a' 为什么也可以写入到文件中?

续写功能:

FileInputStream

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

public class FileInputStreamDemo {
    /*
      读取的文件内容: abc
    */
    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("E:\\javaProject\\myio\\a.txt");

        int read = fis.read();
        System.out.println(read);  //97
        int read1 = fis.read();
        System.out.println(read1);  // 98
        int read2 = fis.read();
        System.out.println(read2);   //99
        int read3 = fis.read(); //
        System.out.println(read3); //-1:代表结束
    }
}

细节:

1.创建字节输入流对象

  • 如果文件不存在,就直接报错

2.读取数据

  • 一次读一个字节,读出来得数据是在ASCCI上对应得数字
  • 读到文件末尾了,read方法返回 -1

3.释放资源

  • 每次使用完流必须要释放资源

文件copy

FileInputStream:一次读取一个字节

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

public class FileInputStreamDemo2 {
    
    //读取文件的大小:25.8 MB (27,096,467 字节)
    public static void main(String[] args) throws IOException {

        long start = System.currentTimeMillis();

        // 文件拷贝
        FileInputStream fis = new FileInputStream("F:\\葵花宝典\\书籍\\HTML5权威指南.pdf");
        FileOutputStream fos = new FileOutputStream("E:\\javaProject\\myio\\COPY_HTML5权威指南.pdf");


        int b;
        while ((b = fis.read()) != -1) {
            fos.write(b);
        }
        //释放资源,规则:先打开的流后释放
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();
        System.out.println("copy 耗时:" + ( end - start));  //copy 耗时:192676ms
    }
}

一个字节一个字节读取数据很慢,25.6M = 27096467 字节, 相当于要读取27096467 次,如何优化?

FileInputStream:一次读取多个字节

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

public class FileInputeDemoStream3 {


    /*
    FileInputStream:一次读取多个字节
     */
    public static void main(String[] args) throws IOException {

        byte[] bytes = new byte[2];  //数组的大小定义了一次读取数据的多少

        FileInputStream fis = new FileInputStream("E:\\javaProject\\myio\\a.txt");

        //len:读取到的字节个数
        int len = fis.read(bytes);  //将数据读取到字节数组当中
        System.out.println(len);  //2
        System.out.println(new String(bytes)); //ab

        int len2 = fis.read(bytes);  //覆盖数组当中的ab,此时装入数组的数据是cd
        System.out.println(len2); //2
        System.out.println(new String(bytes)); //cd

        int len3 = fis.read(bytes);  //读取到e,覆盖数组中的c,此时数组中的数据是ed
        System.out.println(len3);  //1
        System.out.println(new String(bytes)); //ed
 
        int len4 = fis.read(bytes);  // 没有读到数据,因此数组中还是ed
        System.out.println(len4); //-1 
        System.out.println(new String(bytes)); //ed
    }
}

一次读取多个字节copy 文件:

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

public class FileCopyDemo {


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

        long start  = System.currentTimeMillis();

        FileInputStream fis = new FileInputStream("F:\\葵花宝典\\书籍\\HTML5权威指南.pdf");
        FileOutputStream fos = new FileOutputStream("E:\\javaProject\\myio\\COPY_HTML5权威指南.pdf");

        int len;

        byte[] bytes = new byte[1024 * 1024 * 5];  //数组的大小一般选择 1024 的整数倍,需要结合具体电脑的内存选择
        while((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len); //从数组中写出len个长度的字节
        }

        fos.close();
        fis.close();

        long end = System.currentTimeMillis();
        System.out.println("copy 消耗:" + (end - start));  //copy 消耗:29
    }
}

IO异常

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

public class IOExceptionDemo1 {


    /*
    JDK1.7: try 的写法
        try后面的小括号中写创建对象的对象,不同对象之间用分号隔开
        注意:只有实现了AutoCloseable接口的类,才能在小括号中创建对象。
     */
    public static void main(String[] args) throws IOException {
        try(FileInputStream fis = new FileInputStream("F:\\葵花宝典\\书籍\\HTML5权威指南.pdf");
            FileOutputStream fos = new FileOutputStream("E:\\javaProject\\myio\\COPY_HTML5权威指南.pdf")){

            int len;

            byte[] bytes = new byte[1024 * 1024 * 5];  //数组的大小一般选择 1024 的整数倍,需要结合具体电脑的内存选择
            while((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len); //从数组中写出len个长度的字节
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

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

public class IOExceptionDemo2 {

    /*
    JDK1.9: try 的写法
     */
    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("F:\\葵花宝典\\书籍\\HTML5权威指南.pdf");
        FileOutputStream fos = new FileOutputStream("E:\\javaProject\\myio\\COPY_HTML5权威指南.pdf");
        
        try (fis; fos) {
            int len;

            byte[] bytes = new byte[1024 * 1024 * 5];  //数组的大小一般选择 1024 的整数倍,需要结合具体电脑的内存选择
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len); //从数组中写出len个长度的字节
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字符流

字符流 = 字节流 + 编码表

FileReader

文件内容:

一次读取一个字符:

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

public class FileReaderDemo {


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

        FileReader fr = new FileReader("E:\\javaProject\\myio\\a.txt");

        int a;
        //read()细节:
        //1.默认也是一个字节一个字节读取的,如果遇到中文就会一次读取多个字节
        //2.在读取之后,方法的底层还会进行解码并转换成十进制.
        //  最终把这个十进制作为返回值,对应字符集上的数字
        //  中文:文件里面的二进制数据:11100110 10110001 1001001
        //      read 方法进行读取,解码并转换成十进制27721
        while ((a = fr.read()) != -1) {
            System.out.print((char) a);

            /*
            你好啊
            哈哈哈
            喜时之言多失信,
            怒时之言多失体。
             */
        }
    }
}

一次读取多个字符:

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

public class FileReaderDemo2 {


    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("E:\\\\javaProject\\\\myio\\\\a.txt");

        char[] chars = new char[2];

        int len;
        /*
        read(char[] chars) 细节:
            读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
            相当于空参的read() + 强制类型转换
         */
        while ((len = fr.read(chars)) != -1) {
            System.out.print(new String(chars, 0, len));
        }

        fr.close();
    }
}

FileWrite

构造方法:

成员方法:

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

public class FileWriterDemo1 {


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

        FileWriter fw = new FileWriter("E:\\javaProject\\myio\\a.txt",true);
        
        //写入一个int
        fw.write(25105);//按照UTF-8的方式进行编码,并写入到文件中去,25105 在UniCode码表中对应
                            //中文 ‘我’,因此写入的数据就是我
        //写入一个字符串
        fw.write("我");
        fw.close();
    }
}

写入结果:

字符流原理

字符输入流:

创建完FileReader对象后,会有一个8192长度的字节数组作为缓冲区:

第一次读取时会将文件中读取8192个a全部放入到字节数组,然后每次从缓冲求拿数据:

缓冲区数据读取完毕后,最后一次从硬盘取到最后一个字符b放入到缓冲区:

字符输出流: 内部同样维护的有一个8192个字节的缓冲区

posted @ 2023-04-02 21:07  chuangzhou  阅读(20)  评论(0)    收藏  举报