每日总结Day09

IO-字符流&其它流


目录

IO-字符流&其它流

文章目录

一、字符流

1.1FileReader

2.2FileWriter

二、缓冲流

2.1作用

2.2字节缓冲流

2.3字符缓冲流

2.4原始流和缓冲流的性能比较

三、转换流

四、打印流

五、数据流

六、序列化对象

6.1序列化与反序列化

6.2对象储存

七、释放资源

7.1try-catch-finally

7.2try-with-resource

7.3finally相关题目

八、commons-io工具包

总结


一、字符流

字符流
    字符输入流 Reader--FileReader
    字符输出流 Writer--FileWriter

1.1FileReader

FileReader
    创建对象
        public FileReader(File file);
        public FileReader(string pathname);
    读数据
        public int read() 一次读一个字符,返回字符对应的字,读到文件末尾返回-1
        public int read(char[] buffer) 一次读多个字符,返回本次读取的有效字节个数,读到文件末尾返回-1

代码如下(示例):

public static void main(String[] args) throws Exception {
        FileReader fileReader = new FileReader("day09-code/a-1.txt");
        int len;
        char [] chars = new char[2];
        while ((len = fileReader.read(chars)) != -1){
            System.out.println(new String(chars, 0, len));
        }
        fileReader.close();
    }

2.2FileWriter

FileWriter
    创建对象
        public FileWriter(File file)    创建字节输出流管道与源文件对象接通
        public FileWriter(String filepath)  创建字节输出流管道与源文件路径接通
        public FileWriter(File file,boolean append) 创建字节输出流管道与源文件对象接通,可追加数据
        public FileWriter(String filepath,boolean append)   创建字节输出流管道与源文件路径接通,可追加数据
    写数据
        void write(int c)   写一个字符
        void write(String str)  写一个字符串
        void write(String str, int off, int len)    写一个字符串的一部分
        void write(char[] cbuf) 写入一个字符数组
        void write(char[] cbuf, int off, int len)   写入字符数组的一部分
注意:
    字符输出流写出数据后,必须刷新流(flush)或者关闭流(close),写出的数据才会生效,原因是有缓存区
    如果要换行, 需要输出"\r\n"字符串

代码如下(示例):

public static void main(String[] args) throws Exception {
        FileWriter fileWriter = new FileWriter("day09-code/a-2.txt");
        fileWriter.write(97);
        fileWriter.write("\r\n");
        fileWriter.write("黑马程序员");
        fileWriter.write("\r\n");
        fileWriter.write("黑马程序员",0,3);
        fileWriter.write("\r\n");
        char[] chars = {'a','b','c'};
        fileWriter.write(chars);
        fileWriter.write("\r\n");
        fileWriter.write(chars,0,2);
        fileWriter.close();
    }

二、缓冲流

2.1作用

对原始流进行包装,提高原始流读写数据的性能

2.2字节缓冲流

字节缓冲流
    自带8KB缓冲区, 减少了内存和硬盘之间的交互,从而提高原始流读、写数据的性能

字节缓冲流
    public BufferedInputStream(InputStream is); 底层提供8K的缓冲区,减少和内存和硬盘的交互,真正干活的还是字节输入流
    public BufferedOutputStream(OutputStream os);底层提供8K的缓冲区,减少和内存和硬盘的交互,真正干活的还是字节输出流

代码如下(示例):

public static void main(String[] args) throws Exception {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/uplode/abc.wmv"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/uplode/abc1.wmv"));
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1){
            bos.write(bytes, 0, len);
        }
        bis.close();
        bos.close();
    }

2.3字符缓冲流

字符缓冲流
    public BufferedReader(Reader r) 把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流读字符数据的性能
    public String readLine()    读取一行数据返回,如果没有数据可读了,会返回null
    public BufferedWriter(Writer r) 把低级的字符输出流包装成一个高级的缓冲字符输出流,从而提高字符输出流写数据的性能
    public void newLine()   换行

代码如下(示例):

public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader("day09-code/b-3.txt"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("day09-code/b-4.txt"));
        String line =  null;
        while ((line = reader.readLine()) != null){
            writer.write(line);
            writer.newLine();
        }
        writer.close();
        reader.close();
    }

2.4原始流和缓冲流的性能比较

代码如下(示例):

//目标:观察原始流和缓冲流的性能。
public class Demo2 {
    // 复制的视频路径
    private static final String SRC_FILE = "D:/upload/other/duotai.wmv";
    // 复制到哪个目的地
    private static final String DEST_FILE = "D:/upload/other/duotai2.wmv";
    public static void main(String[] args) throws IOException {
        copyUseFileInputStream();//不使用缓冲流
        copyUseBufferedInputStream();//使用缓冲流
    }
    private static void copyUseFileInputStream() throws IOException {
        long startTime = System.currentTimeMillis();
        //1. 创建文件字节输入流、输出流
        FileInputStream fis = new FileInputStream(SRC_FILE);
        FileOutputStream fos = new FileOutputStream(DEST_FILE);
        //2. 使用输入流读取内容,使用输出流写出内容
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //3. 关闭流
        fos.close();
        fis.close();
        long endTime = System.currentTimeMillis();
        System.out.println("不使用缓冲流复制耗时:" + (endTime - startTime) + "ms");
    }
    private static void copyUseBufferedInputStream() throws IOException {
        long startTime = System.currentTimeMillis();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(SRC_FILE));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(DEST_FILE));
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bis.close();
        bos.close();
        long endTime = System.currentTimeMillis();
        System.out.println("使用缓冲流复制耗时:" + (endTime - startTime)+ "ms");
    }
}

三、转换流

解决不同编码读取乱码问题

字符输入转换流
    public InputStreamReader(InputStream is ,String charset) 把原始的字节输入流,按照指定字符集编码转成字符输入流
字符输出转换流
    public OutputStreamWriter(OutputStream os,String charset)   可以把原始的字节输出流,按照指定编码转换成字符输出流
JDK11开始,可直接使用字符流构造指定字符集,构造第二个参数,通过Charset的静态方法forName 指定字符集
    public FileReader(String fileName, Charset charset) throws IOException
    public FileWriter(String fileName, Charset charset) throws IOException

代码如下(示例):

public static void main(String[] args) throws Exception {
//        BufferedReader reader = new BufferedReader(new FileReader("day09-code/c-1.txt", Charset.forName("GBK")));
//
//        System.out.println(reader.readLine());
//        reader.close();
        BufferedWriter writer = new BufferedWriter(new FileWriter("day09-code/c-2.txt", Charset.forName("GBK")));
        writer.write("黑马程序员");
        writer.close();
    }

四、打印流

更加高效的写数据

PrintStream/PrintWriter(打印流)
    打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
构造器
    public PrintStream(OutputStream/File/String)    打印流直接通向字节输出流/文件/文件路径
    public PrintWriter(OutputStream/Writer/File/String) 打印流直接通向字符输出流/文件/文件路径
常用方法
    public void println(Xxx xx) 打印任意类型的数据出去
    public void write(int/byte[]/byte[]一部分) 可以支持写字节数据出去(PrintStream)
    public void write(int/String/char[]/..) 可以支持写字符数据出去(PrintWriter)
PrintStream和PrintWriter的区别
    打印数据的功能上是一样的:都是使用方便,性能高效
    PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法
    PrintWriter继承自字符输出流Writer,因此支持写字符数据出去

五、数据流

保存内容到文件

数据流
    为了保存数据而用的一种数据流, 数据流输出的数据不是给人看的,是为了保存
    数据输出流输出的数据,只能通过数据输入流读回程序

DataOutputStream(数据输出流)
    public DataOutputStream(OutputStream out)   创建新数据输出流包装基础的字节输出流

    public final void writeByte(int v) throws IOException   将byte类型的数据写入基础的字节输出流
    public final void writeInt(int v) throws IOException    将int类型的数据写入基础的字节输出流
    public final void writeDouble(Double v) throws IOException  将double类型的数据写入基础的字节输出流
    public final void writeUTF(String str) throws IOException   将字符串数据以UTF-8编码成字节写入基础的字节输出流
    public void  write(int/byte[]/byte[]一部分)    支持写字节数据出去

DataInputStream(数据输入流)
    public DataInputStream(InputStream is)  创建新数据输入流包装基础的字节输入流
    
    Public final byte readByte() throws IOException 读取字节数据返回
    public final int readInt() throws IOException   读取int类型的数据返回
    public final double readDouble() throws IOException 读取double类型的数据返回
    public final String readUTF() throws IOException    读取字符串数(UTF-8)据返回
    public int readInt()/read(byte[])   支持读字节数据进来

六、序列化对象

6.1序列化与反序列化

序列化与反序列化
    序列化: 将内存中的对象保存到磁盘文件
    反序列化: 将磁盘文件中的数据还原成内存对象

ObjectOutputStream(OutputStream out) 可以把Java对象进行序列化:把Java对象存入到文件中去。
    public final void writeObject(Object obj) 把对象写出去

public ObjectInputStream(InputStream is) 创建对象字节输入流,包装基础的字节输入流
    public final Object readObject()    把存储在文件中的Java对象读出来

注意
    对象如果要参与序列化,必须实现序列化接口(java.io.Serializable)

代码如下(示例):

public class Demo1 {
    public static void main(String[] args) throws Exception {
        //0. 准备一个Student对象
        Student student = new Student("张三", 18);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day09-code/f-1.txt"));
        oos.writeObject(student);
        oos.close();
        ObjectInputStream oif = new ObjectInputStream(new FileInputStream("day09-code/f-1.txt"));
        Student object = (Student) oif.readObject();
        System.out.println(object);
        oif.close();
    }
}
//学生类
class Student implements Serializable {
    private String name;
    private Integer age;
    public Student() {
    }
    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String
    toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

6.2对象储存

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

代码如下(示例):

public static void main(String[] args) throws Exception {
        //0. 准备一个Student对象的集合
        List<Student> students = new ArrayList<>();
        students.add(new Student("张三", 18));
        students.add(new Student("李四", 19));
        students.add(new Student("王五", 20));
        //1. 序列化(f-1.txt)
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day09-code/f-2.txt"));
        oos.writeObject(students);
        oos.close();
        //2. 反序列化(f-1.txt)
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day09-code/f-2.txt"));
        List<Student> object = (List<Student>) ois.readObject();
        System.out.println(object);
        ois.close();
    }
class Student implements Serializable {
    private String name;
    private Integer age;
    public Student() {
    }
    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String
    toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

七、释放资源

7.1try-catch-finally

try-catch-finally
    try {
        ...
    } catch (IOException e) {
        ...
    }finally{
        ...
    }

注意:
    1. finally代码块写在try-catch的最后面
    2. 无论try的代码是否出现问题, 最后一定会执行finally中的代码,除非JVM终止

7.2try-with-resource

try-with-resource
    JDK7开始提供的释放资源方式,编码更简洁


书写格式
    try(资源对象1,资源对象2..){
        ...
    }catch(Exception e){
        处理异常的代码
    }

注意:
    try后面小括号中只能定义资源对象,最终底层会帮我们释放这些对象

7.3finally相关题目

finally相关题目
  1. try-catch-finally 中哪个部分可以省略?
  2. final,finally和finalize的区别
  3. 关于finally在try-catch中的执行顺序
    当try和catch代码块中有return语句时,finally仍然会被执行
    执行try或catch代码块中的return语句之前,都会先执行finally语句
    finally代码块中的return语句一定会执行
    无论在finally代码块中是否有返回值,返回值都不会改变,仍然是执行finally代码块之前的值

代码如下(示例):

public static void main(String[] args) {
        //System.out.println(m1());
        //System.out.println(m2());
        //System.out.println(m3());
        System.out.println(m4());

    }
    //当try和catch代码块中有return语句时,finally仍然会被执行
    //执行try或catch代码块中的return语句之前,都会先执行finally语句
    public static int m1() {
        try {
            return 1;
        } finally {
            System.out.println("执行finally模块");
        }
    }
    public static int m2() {
        try {
            int a = 8 / 0;
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.println("执行finally模块");
        }
    }
    //finally代码块中的return语句一定会执行
    public static int m3() {
        try {
            int a = 8 / 0;
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.println("执行finally模块");
            return 0;
        }
    }
    //无论在finally代码块中是否有返回值,返回值都不会改变,仍然是执行finally代码块之前的值
    public static int m4() {
        int result = 0;
        try {
            return result;
        } finally {
            System.out.println("执行finally模块");
            result = 1;
        }
    }

八、commons-io工具包

框架的形式
    一般是将类、接口等编译成class文件形式,再压缩成一个jar包发行(供别人使用)

Commons-io
    是Apache开源基金组织提供的一组关于IO操作的小框架,目的是提高IO相关操作开发的效率

使用步骤
    0、从官网下载IO的jar包
    1、在模块下新建Directory文件夹,名字叫lib
    2、将准备好的jar包复制到lib文件夹
    3、对着lib目录右键Add as Library..添加到项日环境中
    4、在需要使用的地方直接调用即可

常用工具类FileUtils
    public static void copyFile(File数据源,File目的地) 复制文件
    public static void copyDirectory(File 数据源,File目的地) 复制文件夹
    public static void deleteDirectory(File 目标文件夹) 删除文件夹(有内容也直接删)
    public static String readFileToString(File 数据源,String encoding) 读数据
    public static void writeStringToFile(File file,String data,String encoding, Boolean append) 写数据

常用工具类IOUtils类
    public static int copy(InputStream inputStream, OutputStream outputStream)  复制文件
    public static int copy(Reader reader, Writer writer)    复制文件
    public static void write(String data, OutputStream output, String charsetName)  写数据

总结

以上就是今天学习的内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值