JavaSE进阶笔记:09(IO流、缓冲流、序列化对象、打印流、IO框架)

128 阅读17分钟

一、IO流

IO流称为输入输出流,专门用来读写数据;

Iintput数据从硬盘文件读入到内存的过程,输入,负责读;
Ooutput内存程序数据从内存写到硬盘的过程,输出,负责写

1.IO流分类

1.1 按流方向分

  • 输入流
  • 输出流

1.2 按流中数据最小单位分(都是抽象类)

1.2.1字节流(适合音视频文件)

类名子类
InputStream字节输入流以内存为基准,来自磁盘、网络的数据以字节的形式读入到内存中的流;FileInputStream
OutputStream字节输出流把内存中数据以字节形式写出到磁盘、网络中的流FileOutputStream

1.2.2 字符流(适合文本内容)

类名
Reader字符输入流(以字符形式)
Writer字符输出流

2.字节流使用

2.1每次读取一个字节

/**
 * 字节流输入:
 * 每次读取一个字节:
 *  性能较慢
 *  读取中文无法避免乱码
 */
public class FileInputStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //1.创建一个文件字节输入流管道与源文件接触
        //FileInputStream is = new FileInputStream(new File("day08_file_io_app\\src\\data.txt"));
        
        //简化写法
        FileInputStream is = new FileInputStream("day08_file_io_app\\src\\data.txt");
        //读取一个字节返回;连续读取,读取不到后返回-1
        int read = is.read();//a 编号97
        System.out.println((char)read);//a

        //循环读取所有
        //中文三个字节会被截断,生成乱码,无法解决
        int b;
        while ((b = is.read()) != -1){
            System.out.print((char) b);
        }
    }
}

2.2每次读取一个字节数组

/**
 * 字节流输入:
 * 每次读取一个字节数组:
 * 读取性能得到提升
 * 中文无法避免乱码
 */
public class FileInputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //1.创建一个文件字节输入流管道与源文件接触
        FileInputStream is = new FileInputStream("day08_file_io_app\\src\\data.txt");
        //2.定义一个字节数组,用来接取
        byte[] bytes = new byte[3];
        int read = is.read(bytes);// 3
        String s = new String(bytes);//abc
        System.out.println(s);
        //从0开始,读取字节数组范围内个字节
        String s2 = new String(bytes,0,1);//abc
        System.out.println(s2);
        //读取完毕返回-1

        //循环读取所有字节数组
        //中文三个字节会被截断,生成乱码,无法避免乱码
        byte[] buffer = new byte[3];
        int len;
        while ((len= is.read(buffer))!=-1){
            System.out.println(new String(buffer,0,len));
        }
    }
}

2.3 一次读完全部字节

  • 解决字节流中文乱码,定义与文件一样大的数组,一次取出;
  • 如果文件过大,字节数组可能引起内存溢出

2.4写字节数据到文件

作用
public FileOutputStream(String name, boolean append)创建一个文件字节输出流管道,true表示可以追加数据
public FileOutputStream(String name)创建一个文件字节输出流管道,管道一创建,清空以前数据,写新的
public abstract void write(int b) throws IOException;写一个字节
public void write(byte b[]) throws IOException写一个字节数组
public void write(byte b[], int off, int len) throws IOException写字节数组一部分
flush();写数据必须刷新,数据从缓存中,写入文件,之后可以继续写
close();关闭流,不可以再使用流;里面包含了flush(),输出结束后必须释放资源
/**
 * 文件字节流输出数据:
 * (与目标文件联通,既可以用文件地址,也可以创建文件对象)
 * 创建一个文件字节输出流管道,true表示可以追加数据  public FileOutputStream(String name, boolean append)
 * 创建一个文件字节输出流管道,管道一创建,清空以前数据,写新的  public FileOutputStream(String name)
 *
 * 写一个字节  public abstract void write(int b) throws IOException;
 * 写一个字节数组    public void write(byte b[]) throws IOException
 * 写字节数组一部分   public void write(byte b[], int off, int len) throws IOException
 *
 * 写数据必须刷新,数据从缓存中,写入文件,之后可以继续写
 * flush();
 * 关闭流,不可以再使用流;里面包含了flush(),输出结束后必须释放资源
 * close();
 *
 */
public class FileOutputStreamDemo04 {
    public static void main(String[] args) throws Exception {
        //1.创建一个文件字节输出流管道与目标文件接通
        //管道一创建,清空以前数据,写新的
        //OutputStream os = new FileOutputStream("day08_file_io_app/src/data04.txt");
        //设置true,表示可以追加数据
        OutputStream os = new FileOutputStream("day08_file_io_app/src/data04.txt",true);
        //2.写数据出去
        //a.写一个字节
        os.write('a');
        os.write(98);//b
        //os.write('安');//中文两个字节,只能写一个字节 ,乱码
        //回车换行符
        os.write("\r\n".getBytes());

        //b.写一个字节数组
        byte[] buffer01 = {'a',97,98,99};//aabc
        os.write(buffer01);
        os.write("\r\n".getBytes());
        byte[] buffer02 = "山河一统".getBytes();
        os.write(buffer02);
        os.write("\r\n".getBytes());
        //可以设置编码格式
        //byte[] buffer03 = "山河一统".getBytes("GBK");

        //c.写字节数组的一部分;从0开始,长度2
        os.write(buffer01,0,2);//aa
        os.write("\r\n".getBytes());

        //写数据必须刷新,数据从缓存中,写入文件,之后可以继续写
        os.flush();
        //关闭流,不可以再使用流;里面包含了flush(),输出结束后必须释放资源
        os.close();
    }
}

2.5 文件拷贝

/**
 * 复制文件(任何类型)
 * 
 */
public class CopyDemo05 {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            FileInputStream is = new FileInputStream("D:\\影视\\学习视频\\(P159. 字节输出流).flv");
            FileOutputStream os = new FileOutputStream("D:\\影视\\学习视频\\\\新建文件夹\\newCopy01.flv");
            //每次读取1kb的数据
            byte[] buffer = new byte[1024];
            int len;//记录每次读取长度,用来输出
            System.out.println("开始复制时间:"+sdf.format(new Date()));
            while ((len =is.read(buffer)) != -1){
                os.write(buffer,0,len);
            }
            os.close();
            is.close();
            System.out.println("完成复制时间:"+sdf.format(new Date()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.字符流使用

3.1单个字符读取文件

/**
 * 以单个字符读取文件:
 *  中文不会出现乱码(编码格式一致);
 *  性能较字节流稍慢
 */
public class FileReaderDemo01 {
    public static void main(String[] args) throws Exception {
        //1.创建一个字符输入流管道与源文件接通
        //File file = new File("day08_file_io_app\\src\\data.txt");
        //FileReader fr2 = new FileReader(file);
        Reader fr = new FileReader("day08_file_io_app\\src\\data.txt");
        //2.循环读取;读取一个字符返回,没有可读字符返回-1
        int code;
        while ((code = fr.read())!=-1){
            System.out.print((char)code);
        }
    }
}

3.2 字符数组读取文件

/**
 * 以字符数组读取文件:
 *  性能得到提升
 */
public class FileReaderDemo02 {
    public static void main(String[] args) throws Exception {
        //1.创建一个字符输入流管道与源文件接通
        Reader fr = new FileReader("day08_file_io_app\\src\\data.txt");
        //1k字符,大于1kb字节,大小不能确定
        char[] buffer = new char[1024];
        int len;
        while ((len = fr.read(buffer))!=-1){
            String s = new String(buffer, 0, len);
            System.out.print(s);
        }
    }
}

3.3 字符输出流

/**
 * 字符输出
 */
public class FileWriterDemo03 {
    public static void main(String[] args) throws IOException {
        //1.创建一个字符输出流管道与目标文件接通; true追加数据
        FileWriter fw = new FileWriter("day08_file_io_app\\src\\data08.txt",true);

        fw.write(99);
        fw.write('a');
        fw.write('张');//中文字符不会出问题
        fw.write("\r\n");//换行

        fw.write("好好");//字符串
        fw.write("\r\n");//换行

        char[] chars = "天动万象".toCharArray();
        fw.write(chars);
        fw.write("\r\n");//换行

        //public void write(String str, int off, int len) 写入部分字符串
        fw.write("荡涤四方",0,2);
        //public void write(char cbuf[], int off, int len)  写入部分字符数组
        fw.write(chars,0,2);
        fw.write("\r\n");//换行

        //fw.flush();
        fw.close();

    }
}

二、资源释放方式

1.try-catch-finally

  • fianlly:异常处理,在fianlly中执行所有清除操作,释放资源
  • 特点:fianlly中的语句最终一定执行,除非虚拟机提前终结
  • 异常处理标准格式:
/**
 * 资源释放方式
 *
 */
public class TryCatchFinallyDemo01 {
    public static void main(String[] args) {
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
             is = new FileInputStream("day08_file_io_app\\src\\data.txt");
             os = new FileOutputStream("day08_file_io_app\\src\\data000.txt");
            //每次读取1kb的数据
            byte[] buffer = new byte[1024];
            int len;//记录每次读取长度,用来输出
            while ((len =is.read(buffer)) != -1){
                os.write(buffer,0,len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                //防止在new对象失败,出现空指针异常
                if (os != null)
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //无论何种情况,最后返回值都是100
    public static int sum(int a,int b){
        try {
            //这里出异常,会跳过终止,执行返回-1
            int c = a/b;

            //终止虚拟机运行,执行不到finally
            //System.exit(0);
            
            return c;
        } catch (Exception e) {
            e.printStackTrace();
            //计算bug,返回-1
            return -1;
        } finally {
            //开发中不建议此处用return,返回结果固定,有问题
            return 100;
        }
    }
}

2.try-with-resource

  • 基本做法:finally,手动释放对象

  • JDK7改进做法:

    • try (
             //定义流对象,只能放置资源对象
             //资源用完自动释放
           ) {
                  //可能出现的异常代码
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
  • JDK9改进做法:

  • 注意:

    • 资源对象:实现了Closeable或者AutoCloseable接口的类对象
/**
 * JDK7资源自动释放方式
 *
 */
public class TryCatchResourceDemo02 {
    public static void main(String[] args) {
        try (
                FileInputStream is = new FileInputStream("day08_file_io_app\\src\\data.txt");
                FileOutputStream os = new FileOutputStream("day08_file_io_app\\src\\data00.txt");
                MyConnection connection = new MyConnection();
        ) {
            //每次读取1kb的数据
            byte[] buffer = new byte[1024];
            int len;//记录每次读取长度,用来输出
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


 static class MyConnection implements AutoCloseable{
    @Override
    public void close() throws Exception {
        //实现了AutoCloseable的对象可以被自动释放
        System.out.println("我的连接被释放了");
    }
}

}
/**
 * JDK9资源自动释放方式
 *
 */
public class TryCatchResourceDemo03 {
    public static void main(String[] args) throws Exception{
        //异常需要抛出
        FileInputStream is = new FileInputStream("day08_file_io_app\\src\\data.txt");
        FileOutputStream os = new FileOutputStream("day08_file_io_app\\src\\data00.txt");
        try (is;os) {
            //每次读取1kb的数据
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、缓冲流

1缓冲流概述

  • 缓冲流称为高效流或者高级流;字节流称为原始流
  • 作用:缓冲流自带缓冲区,可以** **;
    • 缓冲区默认大小8KB,长度8192
    • 缓冲区相当于水池,输入输出相当于进出水;
  • 分类
    • 字节缓冲流
    • 字符缓冲流

2.缓冲字节流

/**
 * 缓冲字节输入输出流
 * 原始字节流包装来
 * 提供了8kb的缓冲区
 */
public class ByteBufferDemo01 {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try (
                InputStream is = new FileInputStream("day08_file_io_app\\src\\data.txt");
                //原始字节输入流包装成高级缓冲字节输入流
                InputStream bis = new BufferedInputStream(is);
            
                OutputStream os = new FileOutputStream("day09_io22_app\\src\\data0.txt");
                //原始字节输出流包装成高级缓冲字节输出流
                OutputStream bos = new BufferedOutputStream(os)
        ) {
            //每次读取1kb的数据
            byte[] buffer = new byte[1024];
            int len;//记录每次读取长度,用来输出
            System.out.println("开始复制时间:" + sdf.format(new Date()));
            //bis.
            while ((len = bis.read(buffer)) != -1) {
                //bos
                bos.write(buffer, 0, len);
            }

            System.out.println("完成复制时间:" + sdf.format(new Date()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.字节缓冲流性能分析

/**
 * 测试缓冲流的性能
 */
public class ByteBufferTimeDemo01 {
    private static final String SRC_FILE = "D:\\测试文件\\测试视频01.mp4";
    private static final String DEST_FILE = "D:\\复制文件\\";

    public static void main(String[] args) {
        //低级字节流复制视频
        //copy01();
        //低级字符流复制视频
        //copy02();
        //高级缓冲字节流复制视频
        //copy03();
        //高级缓冲字符流复制视频
        //copy04();

    }

    /**
     * 549M电影
     * 04复制执行时间:1.64s
     */
    private static void copy04() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream(DEST_FILE+"video04.mp4");
                OutputStream bos = new BufferedOutputStream(os);
        ) {
            byte[] buffer = new byte[1024 * 8];
            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");
    }

    /**
     * 03复制执行时间:20.815s
     */
    private static void copy03() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream(DEST_FILE+"video03.mp4");
                OutputStream 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("03复制执行时间:"+(endTime-startTime)/1000.0+"s");
    }

    /**
     * 02复制执行时间:1.76s
     */
    private static void copy02() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                OutputStream os = new FileOutputStream(DEST_FILE+"video02.mp4");
        ) {
            byte[] buffer = new byte[1024 * 8];
            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("02复制执行时间:"+(endTime-startTime)/1000.0+"s");
    }

    /**
     * 复制执行时间:27.042s
     */
    private static void copy01() {
        long startTime = System.currentTimeMillis();
        try (
                InputStream is = new FileInputStream(SRC_FILE);
                OutputStream os = new FileOutputStream(DEST_FILE+"video01.mp4");
        ) {
            int b;
            while ((b = is.read()) != -1) {
                os.write(b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("01复制执行时间:"+(endTime-startTime)/1000.0+"s");
    }
}

4. 字符缓冲流

4.1 缓冲字符输入流

/**
 * 缓冲字符输入流,新增按行读取的方法(经典代码)
 * 读中文,最优秀方案
 */
public class BufferedReaderDemo01 {
    public static void main(String[] args) {
        //sout01();
        //sout02();
        sout03();
    }

    /**
     * BufferedReader增加按行读取的API,返回String
     * ,空格后面有内容,返回空格;没有,返回null
     */
    private static void sout03() {
        try (
                Reader fr = new FileReader("day09_io22_app/src/data0.txt");
                BufferedReader br = new BufferedReader(fr)
        ) {
            String Line;
            while ((Line = br.readLine()) != null) {
                System.out.println(Line);
            }

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

    private static void sout02() {
        try (
                Reader fr = new FileReader("day09_io22_app/src/data0.txt");
                BufferedReader br = new BufferedReader(fr)
        ) {
            //使用数组,消耗内存
            char[] buffer = new char[1024];
            int len;
            while ((len = br.read(buffer)) != -1) {
                String s = new String(buffer, 0, len);
                System.out.print(s);
            }

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

    private static void sout01() {
        try (
                Reader fr = new FileReader("day09_io22_app/src/data0.txt");
                BufferedReader br = new BufferedReader(fr)
        ) {
            int b;
            while ((b = br.read()) != -1) {
                System.out.print((char) b);
            }

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

4.2 缓冲字符输出流

/**
 * 缓冲字符输出流
 */
public class BufferedWriterDemo01 {
    public static void main(String[] args) {
        try (
                //1.创建一个字符输出流管道与目标文件接通; true追加数据(必须在原始管道设置)
                FileWriter fw = new FileWriter("day08_file_io_app\\src\\data08.txt",true);
                BufferedWriter bw = new BufferedWriter(fw)
        ){
            bw.write(99);
            bw.write('a');
            bw.write('张');//中文字符不会出问题
            bw.newLine();//换行API

            bw.write("好好");//字符串
            bw.newLine();

            char[] chars = "天动万象".toCharArray();
            bw.write(chars);
            bw.newLine();

            bw.write("荡涤四方",0,2);
            bw.write(chars,0,2);
            bw.newLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4.3 案例:给编号文本内容排序

/**
 * 根据编号,排序蜀道难,并存入另一个文件
 */
public class BufferedCharTest03 {
    public static void main(String[] args) {
        try (
                BufferedReader br = new BufferedReader(new FileReader("day09_io22_app\\src\\sdn.txt"));
                BufferedWriter bw = new BufferedWriter(new FileWriter("day09_io22_app\\src\\sdnSort.txt"))
        ) {
            ArrayList<String> data = new ArrayList<>();
            String Line;
            while ((Line = br.readLine())!=null){
                if (Line.equals("")){
                    continue;
                }
                data.add(Line);
            }
            //数字开头编号,可以直接排列
            //Collections.sort(data);

            ArrayList<String> sizes = new ArrayList<>();
            Collections.addAll(sizes,"一","二","三","四","五","六","七","八","九","十","十一","十二");
            //中文编号需要自行设置
            Collections.sort(data, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    //截取每行开头到‘.’的信息,匹配sizes索引进行排序
                    return sizes.indexOf(o1.substring(0,o1.indexOf(".")))
                            -sizes.indexOf(o2.substring(0,o2.indexOf(".")));
                }
            });
            for (String d : data) {
                bw.write(d);
                bw.newLine();
            }

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

四、转换流

1.作用:转换编码方式,解决乱码

2字符输入转换流:InputStreamReader

/**
 * 字符输入转换流:InputStreamReader
 *  提取原始文件字节流,根据指定编码转为字符流
 */
public class InputStreamReaderDemo01 {
    public static void main(String[] args) {
        try (
                //提取‘GBK文件’的原始字节流
                FileInputStream is = new FileInputStream("C:\\Users\\Wind\\Desktop\\蜀道难.txt");

                //原始字节流,转换成字符输入流
                //默认以UTF-8方式转换成字符流,乱码,和直接使用FileReader一样
                //Reader isr = new InputStreamReader(is);
                
                //后面加指定编码格式转换
                Reader isr = new InputStreamReader(is,"GBK");
                BufferedReader br = new BufferedReader(isr)
        ) {
            String line;
            while ((line=br.readLine())!=null){
                System.out.println(line);
            }

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

3.字符输出转换流:OutputStreamWriter

/**
 * 字符输出转换流:OutputStreamWriter
 * 指定输出文件的编码格式
 */
public class OutputStreamWriterDemo02 {
    public static void main(String[] args) {
        try (
                //提取‘GBK文件’的原始字节流
                OutputStream os = new FileOutputStream("C:\\Users\\Wind\\Desktop\\GBK蜀道难.txt");
                //原始字节流,转换成字符输出流
                //后面加指定编码格式转换
                Writer osw = new OutputStreamWriter(os,"GBK");
                BufferedWriter bw = new BufferedWriter(osw);

        ) {
            bw.write("锦城虽云乐,不如早还家。");
            bw.write("锦城虽云乐,不如早还家。");
            bw.write("锦城虽云乐,不如早还家。");

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

五、序列化对象

1.对象序列化

  • 作用:以内存为基准,把内存中对象存储到磁盘文件中,称为对象序列化;
  • 使用到的流是对象字节输出流:ObjectOutputStream
/**
 * 对象序列化
 */
public class ObjectOutputStreamDemo01 {
    public static void main(String[] args) throws Exception {
        Student student = new Student("风", "wind", "w123", 22);
        //对象序列化,使用对象字节输出流包装字节输出流管道
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day09_io22_app/src/obj.txt"));
        //直接调用序列化方法
        oos.writeObject(student);
        //关闭释放资源
        oos.close();
    }
}

2.对象反序列化

  • 作用:以内存为基准,把存储到磁盘文件中的对象数据恢复成内存中对象,称为对象序列化;
  • 使用到的流是对象字节输出流:ObjectInputStream
/**
 * 对象反序列化
 * 版本号变动,需要重新序列化以保证反序列化正确
 * local class incompatible:
 * stream classdesc serialVersionUID = 427608976520710683, local class serialVersionUID = 1
 */
public class ObjectInputStreamDemo02 {
    public static void main(String[] args) throws Exception {
        //对象反序列化,使用对象字节输出流包装字节输出流管道
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day09_io22_app/src/obj.txt"));
        //直接调用反序列化方法
        Student student = (Student) ois.readObject();
        System.out.println(student);
        //Student{name='风', loginName='wind', passWord='null', age=22}
    }
}

3. 序列化对象示例

/**
 * 对象要序列化,必须实现Serializable序列化接口
 * Serializable序列化接口:
 *      通知虚拟机需要序列化的信号,内部没有实际东西
 */
public class Student implements Serializable {
    //申明序列化版本号:该文件内容变动后,强制重新序列化;防止反序列化出错
    //序列化和反序列化版本号必须一致,才不会出错
    private static final long serialVersionUID = 1;
    private String name;
    private String loginName;
    //transient 修饰成员变量不参加序列化,剔除敏感信息
    private transient String passWord;
    private int age;
    
    /*
    略
    */
}

六、打印流

作用方便、高效的打印数据到文件中去。
打印流一般指PrintStream、PrintWriter两个类
效果打印什么数据就是什么数据;例如,97不会转为字符,打印boolean的true,就是true;
构造器打印流直接通向字节输出流管道
直接通文件对象
通文件地址
方法print() 打印任意类型数据出去
/**
 * 打印流:高效、方便数据到文件
 * PrintStream:继承字节输出流OutputStream,支持写字节
 * PrintWriter:继承字符输出流Writer,支持写字符
 */
public class PrintDemo01 {
    public static void main(String[] args) throws Exception {
        //可以指定输出文件编码格式
        //PrintStream ps = new PrintStream("day09_io22_app/src/print.txt","GBK");

        //打印功能上,PrintStream和PrintWriter基本没有区别
        //PrintWriter ps = new PrintWriter("day09_io22_app/src/print.txt");

        //指定追加内容,需要在低级管道设置,
        PrintWriter pw = new PrintWriter(new FileOutputStream("day09_io22_app/src/print.txt",true));
        //同时设置追加和编码格式
        PrintWriter ps = new PrintWriter(new OutputStreamWriter(new FileOutputStream("day09_io22_app/src/print.txt",true),"GBK"));

        ps.println(99);
        ps.println('a');
        ps.println(233.333);
        ps.println(true);
        ps.println("我是打印流,写啥输出啥!");

        ps.write("PrintStream,只能写字节");
        ps.println();
        ps.write("PrintWriter可以写字符");
        ps.println();

        //不换行
        ps.print('a');
        ps.print('b');
        ps.print('b');

        ps.close();
    }
}

1.输出语句重定向

改变输出语句位置到文件:简易日志

/**
 * 改变输出语句位置到文件:简易日志
 */
public class PrintDemo02 {
    public static void main(String[] args) throws Exception {
        System.out.println("君不见黄河之水天上来");
        System.out.println("奔流到海不复回");
        PrintStream ps = new PrintStream("day09_io22_app/src/log.txt");
        System.setOut(ps);
        //下面不再打印到控制台
        System.out.println("君不见高堂明镜悲白发");
        System.out.println("朝如青丝暮成雪");
    }
}

IO流抽象类实现类.png

七、ProPerties属性集对象

  • 是一个Map集合,但一般不会当集合用,HashMap更好用;
  • 核心作用:
    • Properties代表一个属性文件,可以把自己对象的键值对信息存入到一个属性文件中;
    • 属性文件:后缀是.properties的文件,里面内容都是key=value,做系统配置信息;

1. 属性对象存入文件

/**
 * 使用Properties把键值对信息存入属性文件中
 */
public class PropertiesDemo01 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.setProperty("id","wind");
        properties.setProperty("password","123456");
        properties.setProperty("tel","123xxxxxxxx");
        System.out.println(properties);
        //{tel=123xxxxxxxx, password=123456, id=wind}

        /**
         *通过字节或者字符输出流,设置管道位置
         * 可以写入属性文件注释信息文件(注释需要使用英文)
         */
        properties.store(new FileWriter("day09_io22_app/src/user.properties")
                ,"This is a property file that stores user information");
        /*properties.store(new FileOutputStream("day09_io22_app/src/user.properties") {
        }, "这是存储用户信息的属性文件");*/
    }
}

2. 从属性文件中读取信息

/**
 * 读取属性文件
 */
public class PropertiesDemo02 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileReader("day09_io22_app/src/user.properties"));

        System.out.println(properties);
        String id = properties.getProperty("id");
        String tel = properties.getProperty("tel");
        //wind的电话:123xxxxxxxx
        System.out.println(id+"的电话:"+tel);

        //返回所有键的集合,相当于keySet()
        Set<String> set = properties.stringPropertyNames();
    }
}

八、IO框架

1. commons-io概述

  • commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发效率;
  • commons-io工具包提供有关io操作的类,两个主要类FileUtils和IOUtilse
  • commons-io工具包
方法名效果
String readFileToString(File f,String encoding)读取文件,返回字符串
void copyFile(File srcF,File destF)复制文件
void copyDirectoryToDirectory(File srcDir,File destDir)复制文件夹
/**
 * IO框架API
 */
public class CommonIODemo01 {
    public static void main(String[] args) throws Exception {
        //1.复制文件
        IOUtils.copy(new FileInputStream("D:\\新建文件夹\\5dae4242a8761bce.jpg")
                ,new FileOutputStream("D:\\新建文件夹\\copy01.jpg"));
        //2.复制文件到某文件夹下
        FileUtils.copyFileToDirectory(new File("D:\\新建文件夹\\5dae4242a8761bce.jpg")
                ,new File("D:\\新建文件夹\\新建"));

        //3.文件夹复制到某文件夹下
        FileUtils.copyDirectoryToDirectory(new File("D:\\新建文件夹\\新建2")
                ,new File("D:\\新建文件夹\\新建"));

        //4.删除文件或文件夹,无论内部是否有内容
        FileUtils.deleteDirectory(new File("D:\\新建文件夹"));

        //Java1.7之后自己做的工具;
        // java11后添加了方法Path.of("D:\\新建文件夹\\5dae4242a8761bce.jpg")
        Files.copy(Paths.get("D:\\新建文件夹\\80d3797b81375fdfcdb0585e6722e13a.png")
                ,new FileOutputStream("D:\\新建文件夹\\copy02.jpg"));
        Files.copy(Paths.get("D:\\新建文件夹\\80d3797b81375fdfcdb0585e6722e13a.png")
        ,Paths.get("D:\\新建文件夹\\copy03.jpg"));
    }
}

RecordDate:2021/08/18