IO:字节字符流等

File

概述

java.io.File 类是⽂件和⽬录路径名的抽象表示,主要⽤于⽂件和⽬录的创建、查找和删除等操作。

构造方法

  • public File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
  • public File(String parent, String child) 从⽗路径名字符串和⼦路径名字符串创建新的File实例。
  • public File(File parent, String child) 从⽗抽象路径名和⼦路径名字符串创建新的 File实例。
        //根据字符串形式的路径创建⼀个File对象
        File file = new File("d:\\common");
        
        //根据⼀个字符串形式的⽗路径和⼦路径拼接成⼀个新路径,然后创建⼀个File对象
        File file2 = new File("d:", "common");
        
        //根据⼀个File类型的⽗路径和⼀个字符串类型的⼦路径拼接成⼀个新路径,然后创建⼀个File对象
        File file3 = new File(file, "tim");
        
        // ⽂件路径名
        String pathname = "D:\\aaa.txt";
        File file1 = new File(pathname);
        
        // ⽂件路径名
        String pathname2 = "D:\\aaa\\bbb.txt";
        File file2 = new File(pathname2);
        
        // 通过⽗路径和⼦路径字符串
        String parent = "d:\\aaa";
        String child = "bbb.txt";
        File file3 = new File(parent, child);
        
        // 通过⽗级File对象和⼦路径字符串
        File parentDir = new File("d:\\aaa");
        String child = "bbb.txt";
        File file4 = new File(parentDir, child);

常用方法

	    File file = new File("d:\\text\\11");
        file.mkdirs();//创建多层文件夹
        File file1 = new File("d:\\text\\12");
        boolean b = file.renameTo(file1);//重命名
        System.out.println(b);
        System.out.println(file);
        boolean delete = file.delete();//删除文件夹
        System.out.println(delete);
        boolean delete1 = file1.delete();
        System.out.println(delete1);*/

        //常用功能
        File file = new File("D:\\text");
        file.mkdirs();

        boolean directory = file.isDirectory();
        System.out.println("判断是否是文件夹:" + directory);

        boolean file1 = file.isFile();
        System.out.println("判断是否是文件:" + file1);

        boolean exists = file.exists();
        System.out.println("判断是否存在:" + exists);

        boolean b = file.canRead();
        System.out.println("判断是否可读:" + b);

        boolean write = file.canWrite();
        System.out.println("判断是否可写:" + write);

        boolean b1 = file.canExecute();
        System.out.println("判断是否可执行:" + b1);

        boolean hidden = file.isHidden();
        System.out.println("判断是否隐藏:" + hidden);

        //相对路径创建的File对象需要转化成为绝对对象来获取真实的父级目录--getAbsoluteFile
        //或者 new File(f2.getAbsolutePath)1
        System.out.println(file.getAbsolutePath()); //绝对路径
        System.out.println(file.getPath()); //获取路径
        System.out.println(file.getName()); //获取名称
        System.out.println(file.length());  //获取长度:字节数
        System.out.println(new Date(file.lastModified()));  //获取最后一次修改时间

        System.out.println(file.list().length); //获取指定⽬录下的所有⽂件或者⽂件夹的名称数组
        File[] files = file.listFiles();    //获取指定⽬录下的所有⽂件或者⽂件夹的File数组

案例

​ ⼩明同学在D盘下建⽴了⼀个"personalfilms"⽂件夹, 但是觉得名字不好听,就改成了"personalmovies".之后⼩明在⽂件夹内建⽴了⼀个名为"TokyoHot.txt"的⽂件,准备⽤来储存⼀些学习信息, 就在这时, 突然发现爸爸就站在身后, ⼩明以多年练习的⼿速瞬间删除了整个⽂件夹

        File file = new File("D:\\personalfilms");
        boolean mkdirs = file.mkdirs();
        System.out.println("创建D:\\personalfilms文件夹:"+mkdirs);

        File file1 = new File("D:\\personalmovies");
        boolean b = file.renameTo(file1);
        System.out.println("修改文件夹名称D:\\personalmovies:"+b);

        File file2 = new File(file1, "TokyoHot.txt");
        boolean newFile = file2.createNewFile();
        System.out.println("创建文件:"+newFile);

        boolean delete = file2.delete();
        System.out.println("删除文件:"+delete);

        boolean delete1 = file1.delete();
        System.out.println("删除文件夹:"+delete1);*/

​ 计算所有d盘下所有后缀名为.jpg的直系⽂件的⼤⼩

    File dir = new File("F:\\");
    printDir(dir);
        
    public static void printDir(File dir) {
        // 获取⼦⽂件和⽬录
        File[] files = dir.listFiles();
        //循环打印
        for (File file : files) {
            //System.out.println(file);
            if (file.isFile()) {
                //是⽂件,判断⽂件名并输出⽂件绝对路径
                if (file.getName().endsWith(".java")) {
                    System.out.println("⽂件名:" + file);
                }
            } else {
                // 是⽬录,继续遍历,形成递归
                printDir(file);
            }
        }
    }

⽂件名称过滤器

方法

  • public String[] list(FilenameFilter filter)
  • public File[] listFiles(FileFilter filter)

分析:

  1. 接⼝作为参数,需要传递⼦类对象,重写其中⽅法。我们选择匿名内部类⽅式,⽐较简单。
  2. accept ⽅法,参数为File,表示当前File下所有的⼦⽂件和⼦⽬录。保留住则返回true,过滤掉则
    返回false。保留规则:
  3. 通过过滤器的作⽤, listFiles(FileFilter) 返回的数组元素中,⼦⽂件对象都是符合条件的,
    可以直接打印。

案例

⽂件过滤器:计算所有d盘下所有后缀名为.jpg的直系⽂件的⼤⼩

 File file1 = new File("D:\\");
 File[] list = file1.listFiles(new FilenameFilter() {
     @Override
     public boolean accept(File dir, String name) {
         if (name.endsWith(".jpg")) {
             return true;
         }
         return false;
     }
 });

 for (File s : list) {
     System.out.println(s);
 }

从键盘录⼊⼀⽂件夹路径,计算这个⽂件夹中所有⽂件的体积之和

        static Long count = 0l;
        
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        File file = new File(s);
        printLength2(file);
        System.out.println(count);
    
    public static void printLength2(File file) {
        String[] list = file.list(new FilenameFilter() {
            @Override
            //dir文件路径  name文件名
            public boolean accept(File dir, String name) {
                if (name.endsWith("zip")) {
                    File file1 = new File(dir, name);
                    count = count + file1.length();
                }
                return false;
            }
        });
    }

IO概述

分类

  1. 数据的流向

    • 输入流:把数据从其他设备上读取到内存中的流
    • 输出流:把数据从内存中写出到其他设备上的流

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8J3OWMj5-1645536684737)(F:\笔记文件\JavaSE\15、io\IO.assets\image-20211008152554751.png)]

  2. 数据类型

    • 字节流:字节单位,可以操作任何数据
    • 字符流:字符单位,只能操作纯字符数据

常用分类

输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter

字节流

字节输出流 OutputStream

java.io.OutputStream `抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到⽬的地。它定义了字
节输出流的基本共性功能⽅法。

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
  • public void write(byte[] b) :将 b.length字节从指定的字节数组写⼊此输出流。
  • public void write(byte[] b, int off, int len) :从指定的字节数组写⼊ len字节,从偏移量 off开始输出到此输出流。
  • public abstract void write(int b)` :将指定的字节输出流。

close⽅法,当完成流的操作时,必须调⽤此⽅法,释放系统资源。 有开就有关

文件字节输出流 FileOuputStream

定义

  • 以字节的形式将数据写⼊到⽂件中
  • OutputStream抽象类的⼦类, 已经重写了write()⽅法

构造⽅法

  • FileOuputStream(String name) : 根据字符串地址来连接到⼀个本地⽂件,创建⽂件输出流以指定的名称写⼊⽂件。
  • FileOuputStream(File file): 根据⼀个File类对象连接到⼀个本地⽂件,创建⽂件输出流以写⼊由指定的File对象表示的⽂件。
  • public FileOutputStream(File file, boolean append): 创建⽂件输出流以写⼊由指定的 File对象表示的⽂件。
  • public FileOutputStream(String name, boolean append) : 创建⽂件输出流以指定的名称写⼊⽂件。

常用方法

  • write(int b) : 将指定字节写⼊此⽂件输出流
  • write(byte[] b): 将b.length个字节从指定byte数组写⼊此⽂件输出流中
  • write(byte[] b,int off, int len) : 将指定byte数组中从偏移量off开始的len个字节写⼊此⽂件输出量
  • close(): 关闭输出流并释放与此流有关的所有系统资源
public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //FileOutputStream stream = new FileOutputStream("D:\\123.txt");覆盖源文件
        FileOutputStream stream = new FileOutputStream("D:\\123.txt", true);

        stream.write(65);//对应Ascll
        //写入数据中的数据 byte[] bytes = "你好李焕英".getBytes();
        stream.write("你好李焕英".getBytes());
        //写⼊指定⻓度中的数据
        stream.write("jdsahudfduasdn".getBytes(), 1, 6);
        stream.write("\r\t".getBytes());//换行

        //防止stream为null,但是此处不存在这样的情况,try catch里面有,先声明、后赋值
        Objects.requireNonNull(stream);
        stream.close();
    }
}

字节输入流 InputStream

java.io.InputStream 抽象类是表示字节输⼊流的所有类的超类,可以读取字节信息到内存中。它定义了字节输⼊流的基本共性功能⽅法。

  • public void close() :关闭此输⼊流并释放与此流相关联的任何系统资源。
  • public abstract int read() : 从输⼊流读取数据的下⼀个字节。
  • public int read(byte[] b) : 从输⼊流中读取⼀些字节数,并将它们存储到字节数组 b中 。

文件字节输入流 FileInputStream

定义

  • 以字节的形式来读取⽂件内容
  • InputStream抽象类的⼦类, 已经重写了read()⽅法

构造方法

  • FileInputStream(String name) : 根据字符串地址来连接到⼀个本地⽂件,通过打开与实际⽂件的连接来创建⼀个 FileInputStream ,该⽂件由⽂件系统中的路径名 name命名。
  • FileInputStream(File file): 根据⼀个File类对象连接到⼀个本地⽂件,通过打开与实际⽂件的连接来创建⼀个 FileInputStream ,该⽂件由⽂件系统中的 File对象 file命名。

常用方法

  • read() : 从此输⼊流中读取⼀个数据字节,每次可以读取⼀个字节的数据,提升为int类型,读取到⽂件末尾,返回 -1
  • read(byte[] b) : 从此输⼊流中将最多b.length个字节的数据读⼊⼀个byte数组中
  • read(byte[] b,int off,int len) : 从此输⼊流中读取最多 len个字节的数据读⼊到⼀个byte[] 数组中
  • close(): 关闭此输⼊流并释放与此流有关的所有系统资源
    public static void main(String[] args) throws IOException {
        FileInputStream stream = new FileInputStream("D:\\123.txt");

        //System.out.println(stream.read());//读取一个字节,读取到末尾:-1
        int count = 0;
        while ((count = stream.read()) != -1) {
            System.out.print(count + "\t");
        }
        // 定义变量,作为有效个数
        int len ;
        // 定义字节数组,作为装字节数据的容器
        byte[] b = new byte[2];
        while (( len= stream.read(b))!=-1) {
            // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
        
        Objects.requireNonNull(stream);
        stream.close();
    }

思考

read()⽅法读取的是⼀个字节,为什么返回是int,⽽不是byte ?

​ 因为字节输⼊流可以操作任意类型的⽂件,⽐如图⽚⾳频等,这些⽂件底层都是以⼆进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111,那么11111111是byte类型的-1,我们的程序是遇到-1就会停⽌不读了,后⾯的数据就读不到了,所以在读取的时候⽤int类型接收,如果11111111会在其前⾯补上24个0凑⾜4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,⽽结束标记的-1就是int类型

小数组读写

    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("d:\\123.txt");
        FileOutputStream outputStream = new FileOutputStream("d:\\1.txt");
       /* int count = 0;
        while ((count = inputStream.read()) != -1) {
            outputStream.write(count);
        }*/
        //小数组读写
        byte[] bytes = new byte[1024];
        int len;
        while ((len = inputStream.read(bytes)) != -1) {
            //bytes 数据  off 数据中的起始偏移量 len 要写入的字节数
            outputStream.write(bytes, 0, len);
        }
        outputStream.close();
        inputStream.close();
    }

字符流

  1. 定义
    • 字符流是可以直接读写字符的IO流
    • 字符流读取字符,就要先读取到字节数据, 然后转为字符,如果要写出字符,需要把字符转为字节在写出
  2. 实⽤性
    • 如果是我们来对读取的字节进⾏转换的话,⾮常麻烦, 因为在储存的时候, 不同的⽂字占⽤的字节数是不同的, 就好像英⽂⽤1个字节,⽽中⽂⽤2个字节,对读取的内容解析就是⾮常痛苦的⼀键事情
    • 不会出现读取到半个中⽂的情况
    • ⼀次读取⽂本的⼀⾏写出的时候可以将⽂本直接写⼊到本地⽂件,不需要转化为字节数组
  3. 使⽤
    • 当程序需要跟⽂本进⾏交互的时候,推荐使⽤
    • 当我们进⾏copy操作的时候, ⽆论是拷⻉纯⽂本还是⾮⽂本极不推荐,⾮常有可以能出现乱码, ⽽且, 读取时字符流会有将字节转换成字符的动作,写⼊是会有讲字符转换成字节的动作,会降低性能

字符输入流 Reader

java.io.Reader 抽象类是表示⽤于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输⼊流的基本共性功能⽅法。

  • public void close():关闭此流并释放与此流相关联的任何系统资源。
  • public int read() : 从输⼊流读取⼀个字符。
  • public int read(char[] cbuf): 从输⼊流中读取⼀些字符,并将它们存储到字符数组 cbuf中

文件字符输入流 FileReader

定义

字符输出流,但是底层还是字节流

构造方法

  • FileReader(String fileName): 根据字符串路径和⽂件获取连接
  • FileReader(File file) : 根据File对象和⽂件获取连接

常用方法

  • int read(): 读取单个字符 ,每次可以读取⼀个字符的数据,提升为int类型,读取到⽂件末尾,返回 -1 ,循环读取,
  • int read(char[] cbuf) : 将字符读⼊数组,每次读取b的⻓度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回 -1
  • void close(): 关闭该流并释放资源
    public static void main(String[] args) throws IOException {
        FileReader reader = new FileReader("D:\\123.txt");

        System.out.println(reader.read());//1、读取单个字符
        //2、读取到末尾是-1,使用while一直读取
        int len;
        while ((len = reader.read()) != -1) {
            System.out.print((char) len);
        }
        //3、小数组读取
        int num;
        char[] chars = new char[1024];
        while ((num = reader.read(chars)) != -1) {
            System.out.println(new String(chars, 0, num));
        }
        reader.close();
    }

字符输出流 Writer

java.io.Writer 抽象类是表示⽤于写出字符流的所有类的超类,将指定的字符信息写出到⽬的地。它定义了字节输出流的基本共性功能⽅法。

  • void write(int c)写⼊单个字符。
  • void write(char[] cbuf)写⼊字符数组。
  • abstract void write(char[] cbuf, int off, int len) 写⼊字符数组的某⼀部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写⼊字符串。
  • void write(String str, int off, int len) 写⼊字符串的某⼀部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
  • void close()关闭此流,但要先刷新它

文件字符输出流 FileWriter

java.io.FileWriter 类是写出字符到⽂件的便利类。构造时使⽤系统默认的字符编码和默认字节缓冲区。

定义

  • 字符输出流, 将字符写⼊到⽂件中,可以直接写⼊字符串
  • 字符输出流中是有缓冲区的

构造⽅法

  • FileWriter(String fileName) : 根据字符串路径和⽂件获取连接
  • FileWriter(File file): 根据File对象和⽂件获取连接
  • FileWriter(File file , boolean append) : 根据File对象和⽂件获取连接, 让流可以从尾部写⼊

常⽤⽅法

  • append(char c) : 将指定字符写⼊到此writer, 功能等同于write()
  • write(char c): 写⼊单个字符
  • write(char[] cbuf, int off, int len) : 写⼊字符数组的某⼀部分
  • write(String str): 写⼊字符串
  • write(String str, int off , int len) : 写⼊字符串的⼀部分
  • flush() : 刷新流 因为内置缓冲区的原因,如果不关闭输出流,⽆法写出字符到⽂件中
    public static void main(String[] args) throws IOException {
        FileWriter fileWriter1 = new FileWriter("D:\\123.txt");//覆盖源文件
        FileWriter fileWriter = new FileWriter("D:\\123.txt", true);
        fileWriter.write(97);//添加单个字符:对应ascll
        fileWriter.write('我');//添加单个字符
        fileWriter.append("你");//追加单个字符
        fileWriter.write(new char[]{'d', 'g'});//添加字符数组
        //添加数组中的某个部分
        fileWriter.write(new char[]{'d', 'g', 'j', 'r', 'o'}, 0, 3);
        fileWriter.write("agdyaj隔断柜");//添加字符串
        //添加字符串中某个部分
        fileWriter.write("agdyaj隔断柜", 0, 3);
        
        fileWriter.write("\n");//换行
        fileWriter.write("\r\t");
        fileWriter.flush();//刷新流
        fileWriter.close();//关闭流
    }

缓冲流

缓冲流,也叫⾼效流,是对4个基本的 字节流、字符流的增强,所以也是4个流,但是本质还是字节流、字符流按照数据类型分类:

字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建⼀个内置的默认⼤⼩的缓冲区数组,通过缓冲区读写,减少系统IO次数,从⽽提⾼读写的效率。

字节缓冲流

  • public BufferedInputStream(InputStream in):创建⼀个 新的缓冲输⼊流。
  • public BufferedOutputStream(OutputStream out): 创建⼀个新的缓冲输出流。

字节输入缓冲流

定义
  • 为了提交效率,使用小数组方式读取、写入(放到一个数组里面,一次读写)
  • 底层还是字节流
构造方法
  • BufferedInputStream(InputStream in) 创建⼀个BufferedInputStream 并保存其参数, 即输⼊in ,⼀遍将来使⽤
  • BuffferedInputStream(InputStream in , int size) 创建⼀个具有指定缓冲区⼤⼩的BufferedInputStream并保存其参数, 即输⼊流in,以便将来使⽤
常用方法
  • read() : ⼀次读取⼀个字节
  • read(byte[] b, int off, int len): 从此字节输⼊流中给定偏移量处开始各字节读取到指定的byte数组中
  • close(): 关闭并释放资源,实际关闭的是内部真正⼯作的字节流
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("D:\\123.txt");
        BufferedInputStream stream = new BufferedInputStream(fileInputStream);
        System.out.println(stream.read());
        int len;
        while ((len = stream.read()) != -1) {
            System.out.print(len + "\t");
        }
        stream.close();
    }

字节输出缓冲流

定义
  • 使用小数组写入,将数据放到数组,等数组满了再写入。
  • 流关闭前会有一次写入的操作,是避免最后一次读取时,缓冲区没有满不能写入的问题
构造方法
  • BufferedOutputStream(OutputStram out) 创建⼀个新的缓冲输出流,以将数据写⼊指定的底层输出流
  • BufferedOutputStream(OutputStream out, int size) 创建⼀个新的缓冲输出流,以将具有指定缓冲区⼤⼩的数据写⼊指定的底层输出流
常用方法
  • write(int b) : 将指定的字节写⼊此缓冲流的输出流
  • write(byte[] b, int off, int len): 将指定byte数组中从偏移量off开始的len个字节吸⼊此缓冲流的输⼊流
  • flush() : 刷新此缓冲流的输出流
  • close(): 关闭流,并释放资源
    public static void main(String[] args) throws IOException {
        FileOutputStream outputStream = new FileOutputStream("D:\\123.txt");
        BufferedOutputStream stream = new BufferedOutputStream(outputStream);
        stream.write(97);
        stream.write('u');
        stream.write("dasubd".getBytes());
        stream.write("\n".getBytes());
        stream.write(new byte[]{'3', 'd', 'h', 'j', 'k'});
        stream.write(new byte[]{'3', 'd', 'h', 'j', 'k'}, 0, 3);
        stream.flush();
        stream.close();
    }

字节缓冲流文件复制

        FileOutputStream fileOutputStream = new FileOutputStream("D:\\1.txt");
        FileInputStream fileInputStream = new FileInputStream("D:\\123.txt");
        BufferedInputStream inputStream = new BufferedInputStream(fileInputStream);
        BufferedOutputStream outputStream = new BufferedOutputStream(fileOutputStream);
        int len;
        while ((len = inputStream.read()) != -1) {
            outputStream.write(len);
        }
        outputStream.close();
        inputStream.close();

文件夹的复制

    public static void copy(String srcName, String target) throws IOException {
        File srcFile = new File(srcName);//起始文件
        File targetFile = new File(target, srcFile.getName());//目标文件
        targetFile.mkdirs();//创建目标文件,如果不创建,FileOutputStream会空指针异常

        File[] files = srcFile.listFiles();//获取起始文件信息
        if (files != null) {//遍历起始文件内容
            for (File file : files) {
                if (file.isFile()) {//如果是文件
                    FileInputStream fileInputStream = new FileInputStream(file);//读取起始文件内容
                    File file1 = new File(targetFile, file.getName());//目标文件的子文件
                    FileOutputStream fileOutputStream = new FileOutputStream(file1);//写入到目标文件
                    byte[] bytes = new byte[1024 * 8];//小数组读写
                    int len;
                    while ((len = fileInputStream.read()) != -1) {
                        fileOutputStream.write(bytes, 0, len);
                    }
                    fileInputStream.close();
                    fileOutputStream.close();
                } else {//如果是文件夹,使用递归
                    copy(file.getAbsolutePath(), targetFile.getAbsolutePath());
                }
            }
        }
    }

字符缓冲流

定义

  • 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
  • 可以指定缓冲区大小,或者可以接受默认大小

构造方法

  • BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流
  • BufferedReader(Reader in, int sz) 创建一个使用指定大小的输入缓冲区的缓冲字符输入流
  • BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流
  • BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,该流使用给定大小的输出缓冲区

常用方法

  • BufferedReader: public String readLine() : 读⼀⾏⽂字
  • BufferedWriter: public void newLine() : 写⼀⾏⾏分隔符,由系统属性定义符号
public class BufferedReaderAndWriterDemo {
    public static void main(String[] args) throws IOException {
        writerDemo(new FileWriter("D:\\123.txt"));
        readDemo(new FileReader("D:\\123.txt"));
        copy(new FileReader("D:\\123.txt"), new FileWriter("D:\\1.txt"));
    }

    /**
     * 
     * @param fileReader    读取的文件
     * @throws IOException
     */
    public static void readDemo(FileReader fileReader) throws IOException {
        BufferedReader reader = new BufferedReader(fileReader);
        String context = "";
        while ((context = reader.readLine()) != null) {
            System.out.println(context);
        }
        reader.close();
    }

    /**
     * 
     * @param fileWriter    写入的文件
     * @throws IOException
     */
    public static void writerDemo(FileWriter fileWriter) throws IOException {
        BufferedWriter writer = new BufferedWriter(fileWriter);
        writer.write("数据");
        writer.newLine();//换行
        writer.write("换行数据");
        writer.flush();
        writer.close();
    }

    /**
     * 复制文件
     * @param fileReader    读取的文件
     * @param fileWriter    写入的文件
     * @throws IOException  可能抛出的异常
     */
    public static void copy(FileReader fileReader, FileWriter fileWriter) throws IOException {
        BufferedReader reader = new BufferedReader(fileReader);
        BufferedWriter writer = new BufferedWriter(fileWriter);
        String context = "";
        while ((context = reader.readLine()) != null) {
            writer.write(context);
            writer.newLine();
        }
        reader.close();
        writer.flush();
        writer.close();
    }
}

案例

将⼀个⽂本⽂档上的⽂本反转,第⼀⾏和倒数第⼀⾏交换,第⼆⾏和倒数第⼆⾏交换
注意: 所有⽂本类的操作, 都⽆法指定操作第⼏⾏

public class Resver {
    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader("D:\\123.txt"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("D:\\1.txt"));
        ArrayList<String> list = new ArrayList();
        String s;
        while ((s = reader.readLine()) != null) {
            list.add(s);
        }
        System.out.println(list);
        for (int i = list.size() - 1; i >= 0; i--) {
            writer.write(list.get(i));
            writer.newLine();
        }
        writer.flush();
    }
}

LineNumberReader

定义

和BufferedReader功能一样,就是多了行数,初始值0

常用方法
  • getLineNumber() ⽅法可以获取当前⾏号
  • setLineNumber() ⽅法可以设置当前⾏号
public static void main(String[] args) throws Exception {
	LineNumberReader lnr = new LineNumberReader(new FileReader("d:\\aaa.txt"));
    String str;
    System.out.println(lnr.getLineNumber());
    lnr.setLineNumber(2);
    while((str=lnr.readLine())!= null){
    	System.out.println(str+":"+lnr.getLineNumber());
    }
    lnr.close();
}

转换流

字符集

定义

  • 可以将字节流转成字符流
  • 是Reader和Writer的子类

分类

  • InputStreamReader 将字节输⼊流转换成字符输⼊流
  • OutputStreamWriter 将字符输出流转换成字节输出了流

构造方法

  • InputStreamReader(字节流)
  • InputStreamReader(字节流,编码表) : 使⽤指定码表读取⽂本
  • OutputStreamWriter(字节流)
  • OutputStreamWriter(字节流,编码表): 使⽤指定码表写⼊⽂本
    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader("D:\\123.txt"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("D:\\1.txt"));
        ArrayList<String> list = new ArrayList();
        String s;
        while ((s = reader.readLine()) != null) {
            list.add(s);
        }
        System.out.println(list);
        for (int i = list.size() - 1; i >= 0; i--) {
            writer.write(list.get(i));
            writer.newLine();
        }
        writer.flush();
    }

指定编码读取

    public static void main(String[] args) throws IOException {
        //定义⽂件路径,⽂件为gbk编码
        String FileName = "E:\\file_gbk.txt";
        //创建流对象,默认UTF8编码
        InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));
        //创建流对象,指定GBK编码
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName), "GBK");
        //定义变量,保存字符
        int read;
        //使⽤默认编码字符流读取,乱码
        while ((read = isr.read()) != -1) {
            System.out.print((char) read);
        }
        isr.close();
        //使⽤指定编码字符流读取,正常解析
        while ((read = isr2.read()) != -1) {
            System.out.print((char) read);// ⼤家好
        }
        isr2.close();
    }

指定方法写入

    public static void main(String[] args) throws IOException {
        //定义⽂件路径
        String FileName = "E:\\out.txt";
        //创建流对象,默认UTF8编码
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName));
        //写出数据
        osw.write("你好"); // 保存为6个字节
        osw.close();
        //定义⽂件路径
        String FileName2 = "E:\\out2.txt";
        //创建流对象,指定GBK编码
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK");
        //写出数据
        osw2.write("你好");// 保存为4个字节
        osw2.close();
    }

也可以在构造方法放常量值,具体如下(源码):

package java.nio.charset;

/**
 * Constant definitions for the standard {@link Charset Charsets}. These
 * charsets are guaranteed to be available on every implementation of the Java
 * platform.
 *
 * @see <a href="Charset#standard">Standard Charsets</a>
 * @since 1.7
 */
public final class StandardCharsets {

    private StandardCharsets() {
        throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!");
    }
    /**
     * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
     * Unicode character set
     */
    public static final Charset US_ASCII = Charset.forName("US-ASCII");
    /**
     * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
     */
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    /**
     * Eight-bit UCS Transformation Format
     */
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    /**
     * Sixteen-bit UCS Transformation Format, big-endian byte order
     */
    public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
    /**
     * Sixteen-bit UCS Transformation Format, little-endian byte order
     */
    public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
    /**
     * Sixteen-bit UCS Transformation Format, byte order identified by an
     * optional byte-order mark
     */
    public static final Charset UTF_16 = Charset.forName("UTF-16");
}

图解

序列化

定义

​ ⽤⼀个字节序列可以表示⼀个对象,该字节序列包含该 对象的数据 、 对象的类型 和 对象中存储的属性 等信息。字节序列写出到⽂件之后,相当于⽂件中持久保存了⼀个对象的信息。反之,该字节序列还可以从⽂件中读取回来,重构对象,对它进⾏反序列化。

分类

  • ObjecOutputStream 将对象写⼊到本地
  • ObjectInputStream 从本地读取⽂件⽣成对象

构造方法

  • public ObjectOutputStream(OutputStream out) : 创建⼀个指定OutputStream的ObjectOutputStream
  • public ObjectInputStream(InputStream in): 创建⼀个指定InputStream的ObjectInputStream

序列化操作操作

前提

必须实现 java.io.Serializable接口

transient

如果有⼀个属性不需要可序列化的,则该属性必须注明是瞬态的,使⽤ transient 关键字修饰

public transient int age; // transient瞬态修饰成员,不会被序列化
package com.qf.javase.day.day27;

import lombok.Data;

import java.io.*;

public class ObjectStreamDemo {
    public static void main(String[] args) throws Exception {
        writerObject();
        readerObject();
    }
	//序列化
    public static void writerObject() throws Exception {
        ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("D:\\123.txt"));
        Role1 role = new Role1("李白", "诗人");
        stream.writeObject(role);
        stream.close();
    }
	//反序列化
    public static void readerObject() throws Exception {
        ObjectInputStream stream = new ObjectInputStream(new FileInputStream("D:\\123.txt"));
        Object object = stream.readObject();
        System.out.println(object);
        stream.close();
    }
}

//实现Serializable
@Data
class Role implements Serializable {
    private String student1;
    private String type;

    public Role(String student1, String type) {
        this.student1 = student1;
        this.type = type;
    }
}

案例

从键盘输入五个对象数据,并且输出

package com.qf.javase.day.day27;

import lombok.Data;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

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

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\123.txt"));
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\123.txt"));
        ArrayList<Student> list = new ArrayList<>();
        int count = 0;
        Scanner scanner = new Scanner(System.in);
        while (count < 1) {
            System.out.println("请输入名称:");
            String name = scanner.next();
            System.out.println("请输入年龄:");
            int age = scanner.nextInt();
            Student student = new Student(name, age);
            list.add(student);
            count++;
        }
        outputStream.writeObject(list);
        Object object = inputStream.readObject();
        System.out.println(object);
        outputStream.close();
        inputStream.close();
    }
}

//实现Serializable接口
@Data
class Student implements Serializable接口 {
    private String string;
    private int age;

    public Student(String string, int age) {
        this.string = string;
        this.age = age;
    }
}

serialVersionUID

​ Serializable 接⼝给需要序列化的类,提供了⼀个序列版本号。 serialVersionUID 该版本号的⽬的在于验证序列化的对象和对应类是否版本匹配

    private static final long serialVersionUID = 9204481448871957268L;

Externalizable

和Serializable功能相同

package com.qf.javase.day.day27;

import lombok.Data;

import java.io.*;

public class ObjectStreamDemo {
    public static void main(String[] args) throws Exception {
        writerObject1();
        readerObject1();
    }
    //序列化
    public static void writerObject1() throws Exception {
        ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("D:\\123.txt"));
        Role1 role = new Role1("李白", "酒鬼123");
        stream.writeObject(role);//读取对象数据
        stream.close();
    }
	//反序列化
    public static void readerObject1() throws Exception {
        ObjectInputStream stream = new ObjectInputStream(new FileInputStream("D:\\123.txt"));
        Role1 object1 = (Role1) stream.readObject();//写入数据
        System.out.println(object1);
        stream.close();
    }
}

//实现Externalizable
@Data
class Role1 implements Externalizable {
    private static final long serialVersionUID = 9204481448871957268L;
    private String name;
    private String type;

    public Role1(String name, String type) {
        this.name = name;
        this.type = type;
    }
	
    public Role1() {
    }
    
	//重写方法
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(this.name);
        out.writeObject(this.type);
    }
	//重写方法	属性的属性要相同,否则数据异常		不反序列化就不写
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.name = (String) in.readObject();
        this.type = (String) in.readObject();
    }
}

Properties

​ java.util.Properties 继承于 Hashtable ,来表示⼀个持久的属性集。它使⽤键值结构存储数据,每个键及其对应值都是⼀个字符串。该类也被许多Java类使⽤,⽐如获取系统属性时, System.getProperties ⽅法就是返回⼀个 Properties 对象。

构造方法

  • Properties() 创建一个没有默认值的空属性列表
  • Properties(Properties defaults) 用指定的默认值创建一个空属性列表

常用方法

  • public Object setProperty(String key, String value) : 保存⼀对属性
  • public String getProperty(String key):使⽤此属性列表中指定的键搜索属性值
  • public Set<String> stringPropertyNames() :所有键的名称的集合
public static void main(String[] args) throws FileNotFoundException {
    // 创建属性集对象
    Properties properties = new Properties();
    
    // 添加键值对元素
    properties.setProperty("filename", "a.txt");
    properties.setProperty("length", "209385038");
    properties.setProperty("location", "D:\\a.txt");
    
    // 打印属性集对象
    System.out.println(properties);
    
    // 通过键,获取属性值
    System.out.println(properties.getProperty("filename"));
    System.out.println(properties.getProperty("length"));
    System.out.println(properties.getProperty("location"));
    
    // 遍历属性集,获取所有键的集合
    Set<String> strings = properties.stringPropertyNames();
    // 打印键值对
    for (String key : strings ) {
    	System.out.println(key+" -- "+properties.getProperty(key));
    }
}

案例

package com.qf.javase.day27;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @author :  自己的名字
 * @version : 1.0
 * @date : 2021/10/11
 */
public class PropertiesDemo3 {

    public static void main(String[] args) {
        Student student = achieveStudent("/com/qf/javase/day27/properties/student.properties");
        Student student1 = achieveStudent("/com/qf/javase/day27/properties/student1.properties");
        Student student2 = achieveStudent("/com/qf/javase/day27/properties/student2.properties");

        System.out.println(student);
        System.out.println(student1);
        System.out.println(student2);
    }

    public static Student achieveStudent(String propertiesPath){
        Student student = null;

        InputStream in = PropertiesDemo2.class.getResourceAsStream(propertiesPath);
//        创建Properties对象
        Properties properties = new Properties();
//        加载流对象
        try {
            properties.load(in);

//            properties.list(System.out);

//            System.out.println(properties.getProperty("name"));
//            System.out.println(properties.getProperty("age"));

//            Properties的键和值都是String类型的数据
            String name = properties.getProperty("name");
            String age = properties.getProperty("age");
            String gender = properties.getProperty("gender");
            student = new Student(name,gender, Integer.parseInt(age));
//            System.out.println(properties.getProperty("gender"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return student;
    }
}

perties/student2.properties");

    System.out.println(student);
    System.out.println(student1);
    System.out.println(student2);
}

public static Student achieveStudent(String propertiesPath){
    Student student = null;

    InputStream in = PropertiesDemo2.class.getResourceAsStream(propertiesPath);

// 创建Properties对象
Properties properties = new Properties();
// 加载流对象
try {
properties.load(in);

// properties.list(System.out);

// System.out.println(properties.getProperty(“name”));
// System.out.println(properties.getProperty(“age”));

// Properties的键和值都是String类型的数据
String name = properties.getProperty(“name”);
String age = properties.getProperty(“age”);
String gender = properties.getProperty(“gender”);
student = new Student(name,gender, Integer.parseInt(age));
// System.out.println(properties.getProperty(“gender”));
} catch (IOException e) {
e.printStackTrace();
}
return student;
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值