File、IO流,资源释放

目录

File

1.创建File类的对象

2.判断文件类型,获取文件信息

3.创建文件,删除文件

4.遍历文件夹(一级文件名称,对象)

​编辑

案例:改变某个文件夹下视频的序号,要求从19开始

前置知识:方法递归

递归的应用、执行流程、算法思想

递归算法三要素

应用:文件搜索

应用:删除非空文件夹

前置知识:字符集

 编码,解码

IO流

 FileInputStream(文件字节输入流)

1.读取一个字节

2.读取多个字节

3.一次性读取全部字节

读写文本内容更适合用字符流,字节流适合做数据的转移,如:文件复制等

FileOutputStream文件字节输出流

案例:文件复制(字节流)

释放资源的方式

文件字符输入流FileReader

文件字符输出流FileWriter

IO流-缓存流

字节缓存流

字符缓存流

BuffererReader字符缓存输入流

BufferedWriter字符缓存输出流 

案例:拷贝出师表到另一个文件,恢复顺序

 原始流、缓冲流的性能分析

IO流-打印流

 InputStreamReader字符输入转换流

OutputStreamWriter字符输出转换流

IO流-打印流

输出语句的重定向 

DataOutputStream(数据输出流)

 DataInputStream( 数据输入流 )

IO流-序列化流

​编辑

ObjectOutputStream对象字节输出流

ObjectInputStream对象字节输入流

IO框架


File 是 java.io. 包下的类,File类的对象,用于代表当前操作系统的文件(文件,文件夹

注意:File类只能对文件本身进行操作,不能读写文件里面存储的数据

IO流用于读写数据的 (读写文件/网络中数据)

File:代表文本

File

1.创建File类的对象

// 1、创建一个File对象,指代某个具体的文件。
        // 路径分隔符
        File f1 = new File("D:/resource/ab.txt");
      //File f1 = new File("D:\\resource\\ab.txt");
        File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");
        System.out.println(f1.length()); // 文件大小

      //文件夹
        File f2 = new File("D:/resource");
        System.out.println(f2.length());  //本身大小

      // 注意:File对象可以指代一个不存在的文件路径
        File f3 = new File("D:/resource/aaaa.txt");
        System.out.println(f3.length());  //0
        System.out.println(f3.exists()); //  判断文件路径是否存在 false

      // 我现在要定位的文件是在模块中,应该怎么定位呢?
      // 绝对路径:带盘符的
        // File f4 = new File("D:\\code\\javasepromax\\file-io-app\\src\\itheima.txt");
     // 相对路径(重点):不带盘符,默认是直接去工程下寻找文件的。
        File f4 = new File("file-io-app\\src\\itheima.txt");
       
System.out.println(f4.length());

2.判断文件类型,获取文件信息

     // 1.创建文件对象,指代某个文件
        File f1 = new File("D:/resource/ab.txt");
        //File f1 = new File("D:/resource/");

     // 判断对应的文件路径是否存在,存在返回true.
        System.out.println(f1.exists());

     //  判断当前文件对象指代的是否是文件,是文件返回true,反之。
        System.out.println(f1.isFile());

     // 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。
        System.out.println(f1.isDirectory());

     // 获取文件的名称(包含后缀)
         System.out.println(f1.getName());
     //获取父路径
        System.out.println(vodio.getparent()); 

     // 获取文件的大小,返回字节个数
        System.out.println(f1.length());

     // 获取文件的最后修改时间。
        long time = f1.lastModified();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        System.out.println(sdf.format(time));

     // 获取创建文件对象时,使用的路径
        File f2 = new File("D:\\resource\\ab.txt");
        File f3 = new File("file-io-app\\src\\itheima.txt");  //相对路径
        System.out.println(f2.getPath()); //D:\resource\ab.txt
        System.out.println(f3.getPath()); //file-io-app\src\itheima.txt

     // 获取绝对路径
        System.out.println(f2.getAbsolutePath()); //D:\resource\ab.txt
        System.out.println(f3.getAbsolutePath())

3.创建文件,删除文件

 // 创建一个新文件(文件内容为空),创建成功返回true,反之。
        File f1 = new File("D:/resource/itheima2.txt");
        System.out.println(f1.createNewFile());   //alt+回车

     // 用于创建文件夹,注意:只能创建一级文件夹
        File f2 = new File("D:/resource/aaa");
        System.out.println(f2.mkdir());

     // 用于创建文件夹,注意:可以创建多级文件夹
        File f3 = new File("D:/resource/bbb/ccc/ddd/eee/fff/ggg");
        System.out.println(f3.mkdirs());

      // 删除文件,或者空文件,注意:不能删除非空文件夹。,删除文件不会进入回收站
        System.out.println(f1.delete());
        System.out.println(f2.delete());
        File f4 = new File("D:/resource");
        System.out.println(f4.delete());

4.遍历文件夹(一级文件名称,对象)

// 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回
        File f1 = new File("D:\\course\\待研发内容");
        String[] names = f1.list();
        for (String name : names) {
            System.out.println(name);
        }
// (重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
        File[] files = f1.listFiles();
        for (File file : files) {
            System.out.println(file.getAbsolutePath());  //绝对路径
        }


 

案例:改变某个文件夹下视频的序号,要求从19开始

前置知识:方法递归

递归是一种算法

直接递归:方法自己调用自己

间接递归:方法调用其他方法,其他方法又回调方法自己

注意:递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误。

public static void main(String[] args) {
        test1();
    }

    // 直接方法递归
    public static void test1(){
        System.out.println("----test1---");
        test1(); // 直接方法递归
    }

    // 间接方法递归
    public static void test2(){
        System.out.println("---test2---");
        test3();
    }

    public static void test3(){
        
        test2(); // 间接递归
    }
 

递归的应用、执行流程、算法思想

public class RecursionTest2 {
    public static void main(String[] args) {
        System.out.println("5的阶乘是:" + f(5));
    }

    public static int f(int n){
        // 终结点
        if(n == 1){
            return 1;
        }else {
            return f(n - 1) * n;
        }
    }
}

递归算法三要素

递归的公式: f(n) =  f(n-1) * n;

递归的终结点:f(1)

递归的方向必须走向终结点:

应用:文件搜索

需求:从D:盘中,搜索“QQ.exe” 这个文件,找到后直接输出其位置。

分析: 先找出D:盘下的所有一级文件对象

           遍历全部一级文件对象,判断是否是文件

           如果是文件,判断是否是自己想要的

           如果是文件夹,需要继续进入到该文件夹,重复上述过程

public static void main(String[] args) throws Exception {
          searchFile(new File("D:/") , "QQ.exe");
    }

    /**
     * 去目录下搜索某个文件
     *  dir  目录
     *  fileName 要搜索的文件名称
     */
    public static void searchFile(File dir, String fileName) throws Exception {
        // 1、把非法的情况都拦截住
        if(dir == null || !dir.exists() || dir.isFile()){
            return; // 代表无法搜索
        }

        // 2、dir不是null,存在,一定是目录对象。
        // 获取当前目录下的全部一级文件对象。
        File[] files = dir.listFiles();

        // 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象。
        if(files != null && files.length > 0){
            // 4、遍历全部一级文件对象。
            for (File f : files) {
                // 5、判断文件是否是文件,还是文件夹
                if(f.isFile()){
                    // 是文件,判断这个文件名是否是我们要找的
                    if(f.getName().contains(fileName)){
                        System.out.println("找到了:" + f.getAbsolutePath());  //绝对路径
                        //启动
                        Runtime runtime = Runtime.getRuntime();
                        runtime.exec(f.getAbsolutePath());
                    }
                }else {
                    // 是文件夹,继续重复这个过程(递归)
                     earchFile(f, fileName);
                }
            }
        }
    }

应用:删除非空文件夹

前置知识:字符集

标准ASCLL使用1个字节存储一个字符,首尾是0,总共可表示128个字符

GBK(汉字内码扩展规范,国标GBK中一个中文字符编码成两个字节的形式存储

汉字的第一个字节的第一位必须是1

GBK兼容了ASCLL字符集

Unicode字符集(统一码,也叫万国码)

UTF-8字符集:英文字符、数字等只占1个字节(兼容标准ASCII编码),汉字字符占用3个字节。

 ASCII字符集:只有英文、数字、符号等,占1个字节。

GBK字符集:汉字占2个字节,英文、数字占1个字节。

UTF-8字符集:汉字占3个字节,英文、数字占1个字节。

注意1:字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码

注意2:英文,数字一般不会乱码,因为很多字符集都兼容了ASCII编码。

 编码,解码

        // 1、编码
        String data = "a我b";
        byte[] bytes = data.getBytes(); // 默认是按照平台字符集(UTF-8)进行编码的。
        System.out.println(Arrays.toString(bytes)); //97,-26,120,-111 98

        // 按照指定字符集进行编码。
        byte[] bytes1 = data.getBytes("GBK");
        System.out.println(Arrays.toString(bytes1));

        // 2、解码
        String s1 = new String(bytes); // 按照平台默认编码(UTF-8)解码
        System.out.println(s1);

        String s2 = new String(bytes1, "GBK");
        System.out.println(s2);

IO流

按流的方向分为:

输入流 :负责把数据读到内存中

输出流:负责写数据出去

按流中数据的最小单位,分为

字节流{适合操作所用类型的文件}

字符流(只适合操作纯文本文件)

 FileInputStream(文件字节输入流)

作用:以内存为基准把磁盘文件中的数据以字节的形式读入到内存中去

1.读取一个字节

public static void main(String[] args) throws Exception {
        // 1、创建文件字节输入流管道,与源文件接通。
        // 简化写法:推荐使用。

        InputStream is = new FileInputStream(("file-io-app\\src\\itheima01.txt"));

        // 2、开始读取文件的字节数据。
        // public int read():每次读取一个字节返回,如果没有数据了,返回-1.

        // 3、使用循环改造上述代码
        int b; // 用于记住读取的字节。
        while ((b = is.read()) != -1){
            System.out.print((char) b);
        }

        // 读取数据的性能很差!
        // 读取汉字输出会乱码!!无法避免的!!
        // 流使用完毕之后,必须关闭!释放系统资源!
        is.close();
    }

2.读取多个字节

  public static void main(String[] args) throws Exception { //ali+回车
        // 1、创建一个字节输入流对象代表字节输入流管道与源文件接通。
        InputStream is = new FileInputStream("file-io-app\\src\\itheima02.txt");

        // 2、开始读取文件中的字节数据:每次读取多个字节。
        //  public int read(byte b[]) throws IOException

        //  每次读取多个字节到字节数组中去,返回读取的字节数量,读取完毕会返回-1.      

        // 3、使用循环改造。
        byte[] buffer = new byte[3];  //定义了一个字节数组,每次读3个字节
        int len; // 记住每次读取了多少个字节。  abc 66
        while ((len = is.read(buffer)) != -1){    //3!=-1
            // 注意:读取多少,倒出多少。
            String rs = new String(buffer, 0 , len);
            System.out.print(rs);
        }
        // 性能得到了明显的提升!!
        // 这种方案也不能避免读取汉字输出乱码的问题!!

        is.close(); // 关闭流
    }
}

3.一次性读取全部字节

public static void main(String[] args) throws Exception {
        // 1、一次性读取完文件的全部字节到一个字节数组中去。
        // 创建一个字节输入流管道与源文件接通
        
      InputStream is = new FileInputStream("file-io-app\\src\\itheima03.txt");

        // 2、准备一个字节数组,大小与文件的大小正好一样大。

        byte[] buffer = is.readAllBytes();
        System.out.println(new String(buffer));

        is.close(); // 关闭流
    }

读写文本内容更适合用字符流,字节流适合做数据的转移,如:文件复制等

FileOutputStream文件字节输出流

把内存中数据以字节的形式写出到文件中去

目标:掌握文件字节输出流FileOutputStream的使用。
public class FileOutputStreamTest4 {
    public static void main(String[] args) throws Exception {
        // 1、创建一个字节输出流管道与目标文件接通。
        // 覆盖管道:覆盖之前的数据
//        OutputStream os =
//                new FileOutputStream("file-io-app/src/itheima04out.txt");

        // 追加数据的管道
        OutputStream os =
                new FileOutputStream("file-io-app/src/itheima04out.txt",
true);

        // 2、开始写字节数据出去了
        os.write(97); // 97就是一个字节,代表a
        os.write('b'); // 'b'也是一个字节
        // os.write('磊'); // [ooo] 默认只能写出去一个字节

        byte[] bytes = "我爱你中国abc".getBytes();  //字符串转字节数
        os.write(bytes);

        os.write(bytes, 0, 15);   //我爱你中国  指定输出

        // 换行符
        os.write("\r\n".getBytes());

        os.close(); // 关闭流

案例:文件复制(字节流)

目标:使用字节流完成对文件的复制操作。
public class CopyTest5 {
    public static void main(String[] args) throws Exception {
        // 需求:复制照片。
        // 1、创建一个字节输入流管道与源文件接通(照片:D:/../..)
        InputStream is = new FileInputStream("file-io-app\\src\\itheima03.txt");
        // 2、创建一个字节输出流管道与目标文件接通。
        OutputStream os = new FileOutputStream("file-io-app\\src\\itheima03copy.txt");
        // 3、创建一个字节数组,负责转移字节数据
        byte[] buffer = new byte[1024]; // 1KB.
        // 4、从字节输入流 中读取字节数据,写出去到字节输出流中。读多少写出去多少。
        int len; // 记住每次读取了多少个字节。
        while ((len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
        }

        os.close();
        is.close();
        System.out.println("复制完成!!");
    }
}

释放资源的方式

try-catch-finally 

       

finally代码区的特点:进try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止,一般用于在程序执行完成后进行资源的释放操作

作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)。

try-with-resource 

该资源使用完毕后,会自动调用其close()方法,完成对资源的释放! 

() 中只能放置资源对象
  // 什么是资源呢?资源都是会实现AutoCloseable接口。资源都会有一个close方法,并且资源放到这里后
                // 用完之后,会被自动调用其close方法完成资源的释放操作。

  try (
                // 1、创建一个字节输入流管道与源文件接通
                InputStream is = new FileInputStream("file-io-app\\src\\itheima03.txt");
                // 2、创建一个字节输出流管道与目标文件接通。
                OutputStream os = new FileOutputStream("file-io-app\\src\\itheima03copy.txt");

                // 注意:这里只能放置资源对象。(流对象)
                // int age = 21;
                // 什么是资源呢?资源都是会实现AutoCloseable接口。资源都会有一个close方法,并且资源放到这里后
                // 用完之后,会被自动调用其close方法完成资源的释放操作。
            
                ){

            // 3、创建一个字节数组,负责转移字节数据。
            byte[] buffer = new byte[1024]; // 1KB.
            // 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。
            int len; // 记住每次读取了多少个字节。
            while ((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
      
            System.out.println("复制完成!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

文件字符输入流FileReader

作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。

public static void main(String[] args)  {
        try (
                // 1、创建一个文件字符输入流管道与源文件接通
             Reader fr = new FileReader("io-app2\\src\\itheima01.txt");//alt+回车——选择第二个
                ){
            // 2、读取文本文件的内容了。
//            int c; // 记住每次读取的字符编号。
//            while ((c = fr.read()) != -1){
//                System.out.print((char) c);
//            }
            // 每次读取一个字符的形式,性能肯定是比较差的。

            // 3、每次读取多个字符。
            char[] buffer = new char[3];
            int len; // 记住每次读取了多少个字符。
            while ((len = fr.read(buffer)) != -1){
                // 读取多少倒出多少
                System.out.print(new String(buffer, 0, len));
            }
            // 性能是比较不错的!
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

文件字符输出流FileWriter

以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。

写字符数据出去,必须刷新流,或者关闭流,写出去的数据才能生效

fw.close(); // 关闭流,关闭流包含刷新操作!

public static void main(String[] args) {
        try (
                // 0、创建一个文件字符输出流管道与目标文件接通。
                // 覆盖管道
                // Writer fw = new FileWriter("io-app2/src/itheima02out.txt");
                // 追加数据的管道
                Writer fw = new FileWriter("io-app2/src/itheima02out.txt", true);
                ){
            // 写一个字符出去
            fw.write('a');
            fw.write(97);
            //fw.write('磊'); // 写一个字符出去
            fw.write("\r\n"); // 换行

            // 写一个字符串出去
            fw.write("我爱你中国abc");
            fw.write("\r\n");

            // 写字符串的一部分出去
            fw.write("我爱你中国abc", 0, 5);  //我爱你中国
            fw.write("\r\n");

            // 写一个字符数组出去
            char[] buffer = {'黑', '马', 'a', 'b', 'c'};
            fw.write(buffer);
            fw.write("\r\n");

            // 写字符数组的一部分出去
            fw.write(buffer, 0, 2);
            fw.write("\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

IO流-缓存流

字节缓存流

作用:提高字节流读写数据的性能

原理:字节缓冲输入流自带了 8KB 缓冲池;字节缓冲输出流也自带了 8KB 缓冲池。

try (
                InputStream is = new FileInputStream("io-app2/src/itheima01.txt");
                // 1、定义一个字节缓冲输入流包装原始的字节输入流
                InputStream bis = new BufferedInputStream(is);

               

            OutputStream os = new FileOutputStream("io-app2/src/itheima01_bak.txt");
                // 2、定义一个字节缓冲输出流包装原始的字节输出流
                OutputStream bos = new BufferedOutputStream(os);
        ){

            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
            System.out.println("复制完成!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

字符缓存流

作用:自带 8K ( 8192 )的字符缓冲池,可以提高字符输入流读取字符数据的性能。

新增的功能:按照行读取字符

BuffererReader字符缓存输入流

try (
                Reader fr = new FileReader("io-app2\\src\\itheima04.txt");
                // 创建一个字符缓冲输入流包装原始的字符输入流
                BufferedReader br = new BufferedReader(fr);
        ){
            String line; // 记住每次读取的一行数据
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

BufferedWriter字符缓存输出流 

作用:作用:自带 8K 的字符缓冲池,可以提高字符输出流写字符数据的性能。

掌握字符缓冲输出流的用法。
public class BufferedWriterTest3 {
    public static void main(String[] args) {
        try (
                Writer fw = new FileWriter("io-app2/src/itheima05out.txt", true);
                // 创建一个字符缓冲输出流管道包装原始的字符输出流
                BufferedWriter bw = new BufferedWriter(fw);
        ){

            bw.write('a');
            bw.write(97);
            bw.write('磊');
            bw.newLine();  //换行

            bw.write("我爱你中国abc");
            bw.newLine();    //换行

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

案例:拷贝出师表到另一个文件,恢复顺序

 

 原始流、缓冲流的性能分析

建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,
目前来看是性能最优的组合。

public class TimeTest4 {
    // 复制的视频路径
    private static final String SRC_FILE = "D:\\resource\\线程池.avi";
    // 复制到哪个目的地
    private static final String DEST_FILE = "D:\\";

    public static void main(String[] args) {
        // copy01(); // 低级字节流一个一个字节的赋值,慢的简直让人无法忍受,直接淘汰!
        copy02();// 低级的字节流流按照一个一个字节数组的形式复制,速度较慢!
        // copy03(); // 缓冲流按照一个一个字节的形式复制,速度较慢,直接淘汰!
        copy04(); // 缓冲流按照一个一个字节数组的形式复制,速度极快,推荐使用!
    }

    private static void copy01() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                OutputStream os = new FileOutputStream(DEST_FILE + "1.avi");
        ){

            int b;
            while ((b = is.read()) != -1){
                os.write(b);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("低级字节流一个一个字节复制耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

    private static void copy02() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                OutputStream os = new FileOutputStream(DEST_FILE + "2.avi");
        ){
            byte[] buffer = new byte[1024*64];
            int len;
            while ((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("低级字节流使用字节数组复制耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

    private static void copy03() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                BufferedInputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream(DEST_FILE + "3.avi");
                BufferedOutputStream bos = new BufferedOutputStream(os);
        ){

            int b;
            while ((b = bis.read()) != -1){
                bos.write(b);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲流一个一个字节复制耗时:" + (endTime - startTime) / 1000.0 + "s");
    }

    private static void copy04() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                BufferedInputStream bis = new BufferedInputStream(is, 64 * 1024);
                OutputStream os = new FileOutputStream(DEST_FILE + "4.avi");
                BufferedOutputStream bos = new BufferedOutputStream(os, 64 * 1024);
        ){
            byte[] buffer = new byte[1024 * 64]; // 32KB
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲流使用字节数组复制耗时:" + (endTime - startTime) / 1000.0 + "s");
    }
}

IO流-打印流

如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!

 InputStreamReader字符输入转换流

作用:解决不同编码时,字符流读取文本内容乱码的问题。
 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码 

public class InputStreamReaderTest2 {
    public static void main(String[] args) {
        try (
                // 1、得到文件的原始字节流(GBK的字节流形式)
                InputStream is = new FileInputStream("io-app2/src/itheima06.txt");
                // 2、把原始的字节输入流按照指定的字符集编码转换成字符输入流
                Reader isr = new InputStreamReader(is, "GBK");
                // 3、把字符输入流包装成缓冲字符输入流
                BufferedReader br = new BufferedReader(isr);
                ){
            String line;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

OutputStreamWriter字符输出转换流

作用:可以控制写出去的字符使用什么字符集编码。

解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。

public class OutputStreamWriterTest3 {
    public static void main(String[] args) {
        // 指定写出去的字符编码。
        try (
                // 1、创建一个文件字节输出流
                OutputStream os = new FileOutputStream("io-app2/src/itheima07out.txt");
                // 2、把原始的字节输出流,按照指定的字符集编码转换成字符输出转换流。
                Writer osw = new OutputStreamWriter(os, "GBK"); 
                // 3、把字符输出流包装成缓冲字符输出流
                BufferedWriter bw = new BufferedWriter(osw);
                ){
            bw.write("我是中国人abc");
            bw.write("我爱你中国123");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IO流-打印流

PrintStream 和 PrintWriter 的区别
 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
 PrintStream 继承自字节输出流 OutputStream ,因此支持写字节数据的方法。
 PrintWriter 继承自字符输出流 Writer ,因此支持写字符数据出去。

作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。

public class PrintTest1 {
    public static void main(String[] args) {
        try (
                // 1、创建一个打印流管道
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt", Charset.forName("GBK"));
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt");
                PrintWriter ps =
                        new PrintWriter(new FileOutputStream("io-app2/src/itheima08.txt", true));
                ){
                ps.println(97);
                ps.println('a');
                ps.println("我爱你中国abc");
                ps.println(true);
                ps.println(99.5);

               

 // ps.write(97); // 'a'

       } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出语句的重定向 

可以把输出语句的打印位置改到某个文件中去。

public class PrintTest2 {
    public static void main(String[] args) {
        System.out.println("老骥伏枥");
        System.out.println("志在千里");

        try ( PrintStream ps = new PrintStream("io-app2/src/itheima09.txt"); ){

            // 把系统默认的打印流对象改成自己设置的打印流
            System.setOut(ps);

            System.out.println("烈士暮年");
            System.out.println("壮心不已");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

DataOutputStream(数据输出流)

作用:允许把数据和其类型一并写出去

public class DataOutputStreamTest1 {
    public static void main(String[] args) {
        try (
                // 1、创建一个数据输出流包装低级的字节输出流
                DataOutputStream dos =
                        new DataOutputStream(new FileOutputStream("io-app2/src/itheima10out.txt"));
                ){
            dos.writeInt(97);
            dos.writeDouble(99.5);
            dos.writeBoolean(true);
            dos.writeUTF("黑马程序员666!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

 DataInputStream( 数据输入流 )

作用:用于读取数据输出流写出去的数据。

public class DataInputStreamTest2 {
    public static void main(String[] args) {
        try (
                DataInputStream dis =
                        new DataInputStream(new FileInputStream("io-app2/src/itheima10out.txt"));
                ){

          //对应写
            int i = dis.readInt();
            System.out.println(i);

            double d = dis.readDouble();
            System.out.println(d);

            boolean b = dis.readBoolean();
            System.out.println(b);

            String rs = dis.readUTF();
            System.out.println(rs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IO流-序列化流


对象序列化:把 Java 对象写入到文件中去
对象反序列化:把文件里的 Java 对象读出来

ObjectOutputStream对象字节输出流

可以把 Java 对象进行序列化:把 Java 对象存入到文件中去。
注意:对象如果要参与序列化,必须实现序列化接口
( java.io.Serializable )

不想对密码进行序列化:

1.创建User类    public class User implements Serializable {

2.

public class Test1ObjectOutputStream {
    public static void main(String[] args) {
        try (
                // 2、创建一个对象字节输出流包装原始的字节 输出流。
                ObjectOutputStream oos =
                        new ObjectOutputStream(new FileOutputStream("io-app2/src/itheima11out.txt"));
                ){
            // 1、创建一个Java对象。
            User u = new User("admin", "张三", 32, "666888xyz");

            // 3、序列化对象到文件中去
            oos.writeObject(u);
            System.out.println("序列化对象成功!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ObjectInputStream对象字节输入流

可以把 Java 对象进行反序列化:把存储在文件中的 Java 对象读入到内存中来。

public class Test2ObjectInputStream {
    public static void main(String[] args) {
        try (
                // 1、创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io-app2/src/itheima11out.txt"));
                ){
            User u = (User) ois.readObject();
            System.out.println(u);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 

 如果要一次序列化多个对象:

用一个 ArrayList 集合存储多个对象,然后直接对集合进行序列化即可
注意: ArrayList 集合已经实现了序列化接口 

IO框架

框架:

  • 解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。
  • 好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率
  • 框架的形式:一般是把类、接口等编译成 class 形式,再压缩成一个 .jar 结尾的文件发行出去。

IO框架:封装了 Java 提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。

导入 commons-io-2.11.0.jar 框架到项目中去。
① 在项目中创建一个文件夹: lib
② 将 commons-io-2.6.jar 文件复制到 lib 文件夹
③ 在 jar 文件上点右键,选择 Add as Library -> 点击 OK
④ 在类中导包使用

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

//复制
//        FileUtils.copyFile(new File("io-app2\\src\\itheima01.txt"), new File("io-app2/src/a.txt"));

//拷贝文件夹

//        FileUtils.copyDirectory(new File("D:\\resource\\私人珍藏"), new File("D:\\resource\\私人珍藏3"));

//删除文件夹
//        FileUtils.deleteDirectory(new File("D:\\resource\\私人珍藏3"));

       

// Java提供的原生的一行代码搞定很多事情

//复制
        // Files.copy(Path.of("io-app2\\src\\itheima01.txt"), Path.of("io-app2\\src\\b.txt"));
//     读出内容

  System.out.println(Files.readString(Path.of("io-app2\\src\\itheima01.txt")));
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值