IO流复习

IO流专题复习

1、常用的文件操作

1.1、创建文件对象构造器(三种方法)

在这里插入图片描述

代码展示

package com.zhangjiangbo.cn.files;

import java.io.File;
import java.io.IOException;

/**
 * 1、创建文件
 */
public class FileCreate {
    public static void main(String[] args) {
//        create01();
//        create02();
        create03();
    }

    // 方式1 new File(String pathname)
    public static void create01(){
        File file = new File("D:\\测试\\new.txt");
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 方式2 new File(File parent,String child) 根据父目录+子路径构建
    public static void create02(){
        File parent = new File("D:\\测试\\");
        // 这里的file对象在java程序中只是一个java对象而已,存储在堆内存中
        File file = new File(parent,"test01.txt");
        try {
            // 真正的执行了创建文件
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 方式3 new File(String parent,String child) 根据父级目录+子路径构建
    public static void create03(){
        String parent = "D:\\";
        String child = "测试\\test02.txt";
        File file = new File(parent,child);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

1.2、获取文件的信息常用方法

在这里插入图片描述

  • getName 获取名称
  • getAbsoutePath 获取绝对路径
  • getParent 获取父级目录
  • length 获取文件大小(按字节来算)
  • exists 文件是否存在
  • isFile 是否是一个文件
  • isDirectory 是否是一个目录

代码展示

    @Test
    public void info(){
        File file = new File("D:\\测试\\test01.txt");
        // 获取文件名
        System.out.println("文件名:"+file.getName());
        // 获取绝对路径
        System.out.println("绝对路径:"+file.getAbsolutePath());
        // 获取文件父目录
        System.out.println("文件父目录:"+file.getParent());
        // 获取文件大小(按字节来算)
        System.out.println("文件大小为:"+file.length());
        // 判断文件是否存在
        System.out.println("文件是否存在:"+file.exists()); // true
        // 是不是一个文件
        System.out.println("是不是一个文件:"+file.isFile());
        // 是不是一个目录
        System.out.println("是不是一个目录:"+file.isDirectory());
    }

1.3 目录的操作和文件删除

在这里插入图片描述
注意:当创建目录是多级时需要用mkdirs,否则会报错,只有一级时用mkdir

代码展示

    /**
     * 判断文件是否存在,存在就删除
     */
    @Test
    public void test01(){
        File file = new File("D:\\测试\\test02.txt");
        if(file.exists()){
            file.delete();
            System.out.println("文件删除完成");
        }else{
            System.out.println("该文件不存在");
        }
    }

    /**
     * 判断文件夹是否存在
     * 在java程序中,目录也被当做文件
     */
    @Test
    public void test02(){
        File file = new File("D:\\测试\\测试是否存在");
        if(file.exists()){
            if(file.delete()){
                System.out.println("文件删除完成");
            }else{
                System.out.println("文件删除有误");
            }
        }else{
            System.out.println("文件不存在");
        }
    }

    /**
     * 判断文件是否存在,如果存在则提示已存在,不存在则创建文件
     * 当创建目录是多级时需要用mkdirs,否则会报错,只有一级时用mkdir
     */
    @Test
    public void test03(){
        File file = new File("D:\\测试\\test02\\a\\b\\c");
        if(file.exists()){
            System.out.println("目录已存在");
        }else{
            if(file.mkdirs()){
                System.out.println("文件不存在,已创建新文件");
            }else{
                System.out.println("文件创建失败");
            }
        }
    }

2、IO流原理及流的分类

2.1 JavaIO流原理

在这里插入图片描述

2.2 流的分类

在这里插入图片描述

3、IO流常用类

3.1、IO流体系图

在这里插入图片描述

3.2、FileInputStream

功能:读取文件的数据输出到程序的控制台

思路:创建对象,将要读取的文件路径通过构造器传给对象,调用对象的read() 方法,将读取到的数据输出到控制台,关闭流

两种读取方式:

  • read() 单个字节读取

    直接调用read方法,返回int类型的单个字符,当查询到末尾时返回 -1 (读取效率慢)

  • read(byte[] b) 数组读取

    根据数组读取指定个数的字节,将数据暂存到数组内,当查询到末尾时返回 -1 (推荐使用)

代码展示

package com.zhangjiangbo.cn.inputStreams;

import org.junit.Test;

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

/**
 * 字节流 FileInputStream
 * 演示FileInputStream的使用(字节输入流)
 */
public class FileStreamTest {
    public static void main(String[] args) {


    }

    /**
     * 读取文件中的内容
     * 使用read()方法
     */
    @Test
    public void readFiel01(){
        String pathName = "D:\\测试\\new.txt";
        // 创建fileInputStream对象,读取文件
        FileInputStream fileInputStream = null;
        int count = 0;
        try {
            fileInputStream = new FileInputStream(pathName);
            while (count != -1){
                // 如果返回-1则表示数据已经读取到了末尾
                count = fileInputStream.read();
                // 返回的数据类型是int,需要转换成字符型
               System.out.print((char) count);
           }
            System.out.println();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                // 使用完之后一定要关闭,释放文件连接,否则会造成资源浪费
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 使用read(byte[] b) 提高效率
     */
    @Test
    public void readFiel02(){
        String path = "D:\\测试\\new.txt";
        FileInputStream fileInputStream = null;
        byte[] buf = new byte[3]; // 一次要读8个字符
        int count = 0;
        try {
            fileInputStream = new FileInputStream(path);
            while (count!=-1){
                count = fileInputStream.read(buf);
                if(count!=-1){
                    System.out.print(new String(buf,0,count));
                }
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3.3、FileOutputStream

功能:将程序内的数据输出到指定文件内

思路:创建对象,将要输出的文件地址通过构造器传给对象,将准备好的数据通过调用对象的write()方法输出到文件内,关闭流

注意点:
new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖

三种输出方式

  • write() 方法输出

    直接调用 write方法一个一个字节输出

  • write(byte[] b) 数组输出

    将数据放到数组中,根据数组来输出

  • write(byte b[], int off, int len) 输出

    将数据放到数组中,指定输出的长度(推荐) 例如: fileOutputStream.write(bytes,0,bytes.length);

代码展示

package com.zhangjiangbo.cn.outputStream;

import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 在a.txt文件中输出你好,世界,会自动创建文件(前提:文件夹必须存在)
 */
public class FileOutputStream01 {
    public static void main(String[] args) {

    }

    /**
     * 使用FileOutputStream 将数据写到文件中,如果文件不存在则创建该文件
     * 如果没有文件,write方法会自动创建文件(前提:文件夹必须存在)
     * new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
     * new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖
     */
   @Test
    public void writeFile(){
       String pathName = "D:\\测试\\test03.txt";
       // 创建FileOutputStream对象
       FileOutputStream fileOutputStream = null;
       try {
           // 判断文件是否存在
           File file = new File(pathName);
           if(file.exists()){
               fileOutputStream = new FileOutputStream(pathName,true);
               // 三种方式
//               fileOutputStream.write('a');
               String str = "hello,world";
               byte[] bytes = str.getBytes();
//               fileOutputStream.write(bytes);
               fileOutputStream.write(bytes,0,bytes.length);
               System.out.println("写入数据成功");
           }else{
               file.createNewFile();
               fileOutputStream = new FileOutputStream(pathName);
               fileOutputStream.write('a');
               System.out.println("文件不存在,已创建新文件并成功写入数据");
           }
       } catch (FileNotFoundException e) {
           throw new RuntimeException(e);
       } catch (IOException e) {
           throw new RuntimeException(e);
       } finally {
           try {
               fileOutputStream.close();
           } catch (IOException e) {
               throw new RuntimeException(e);
           }
       }

   }
}

应用实例

通过FileOutputStream和FileInputStream实现文件的拷贝

思路:创建输入流、输出流对象,将要复制的文件通过构造方法传给输入流,将要复制到的文件传给输出流,调用输入流的read()方法读取到数据,调用输出流的write方法输出数据到指定文件

代码展示

package com.zhangjiangbo.cn.outputStream;

import org.junit.Test;

import java.io.*;
import java.util.Objects;

/**
 * 文件拷贝
 */
public class FileCopy {
    public static void main(String[] args) {

    }

    /**
     * 文件拷贝 将D:\测试\test02\mini.jpg 文件 拷贝到D:\测试\mini.jpg
     * 思路:
     * 1、创建文件的输入流,将文件写入程序
     * 2、创建文件的输出流,将文件输出
     */
    @Test
    public void test01(){
        String pathName = "D:\\测试\\test02\\mini.jpg";
        String toPathName = "D:\\测试\\mini.jpg";
        // 创建输入流
        FileInputStream inputStream = null;
        // 创建输出流
        FileOutputStream fileOutputStream = null;
        int count = 0;
        try {
            fileOutputStream = new FileOutputStream(toPathName);
            inputStream = new FileInputStream(pathName);
            byte[] bytes = new byte[1024];
            while(count!=-1){
                count = inputStream.read(bytes);
                // 读取到文件之后写入文件 边读边写
                fileOutputStream.write(bytes,0,bytes.length);
            }
            System.out.println("拷贝成功!");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                if(Objects.equals(null,fileOutputStream)){
                    inputStream.close();
                }
                if(Objects.equals(null,fileOutputStream)){
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

3.4、FileReader

功能:读取文件中的字符到程序

思路:创建对象,将要读取的文件路径通过构造器传给对象,调用对象的read()方法读取数据,关闭流

在这里插入图片描述
常用方法
在这里插入图片描述

两种读取方式

  • read()方法读取

    直接调用read()方法,一个字符一个字符的读取,当读取到数据末尾时返回 -1 (读取效率慢)

  • read(char cbuf[]) 读取

    读取指定位数的数据,将读取到的数据暂时存放到数组中,当读取末尾时返回-1 (推荐使用)

代码展示

package com.zhangjiangbo.cn.reader;

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

/**
 * 读取文件内的汉字
 * 使用fileReader
 */
public class FileReaderTest {
    public static void main(String[] args) {
        String pathName = "D:\\测试\\test03.txt";
        FileReader fileReader = null;
        int count = 0;
        try {
            fileReader = new FileReader(pathName);
            char[] bytes = new char[1024];
            while(count!=-1){
                // 一个字一个字的读
//                count = fileReader.read();
                // 读取数组
                count = fileReader.read(bytes);
                if(count!=-1){
                    System.out.println(new String(bytes,0,count));
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3.5、FileWriter

功能:将程序的字符输出到指定文件内

思路:创建对象,将要输出的文件地址通过构造方法传给对象,调用对象的write()方法 输出到文件内

注意点:
new FileOutputStream(pathName); 方式创建文件,当写入内容时,会覆盖之前文件的数据
new FileOutputStream(pathName,ture); 追加到文件内容的末尾,不会覆盖
对象调用write方法之后一定要刷新流或者关闭流,否则数据不会写入到文件内

在这里插入图片描述
常用方法
在这里插入图片描述
五种输出方式

  • write(String str) 方法

    直接输出字符串

  • write(int c)

    输出单个字符

  • write(char cbuf[])

    将数据放到数组中,输出数组

  • write(char cbuf[], int off, int len)

    将数据放到数组中,输出数组指定位置的数据

  • write(String str, int off, int len)

    输出字符串指定位置的数据

代码展示

package com.zhangjiangbo.cn.write;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Objects;

/**
 * 将指定内容输出到文件中
 * 注意:一定要执行flush或者close才可以将数据写到文件中,否则数据只会存在内存中,不会写进文件内
 */
public class FileWriteTest {
    public static void main(String[] args) {
        String pathName = "D:\\测试\\test03.txt";
        FileWriter fileWriter = null;
        try {
            // 注意点,true,如果添加了则代表追加,没有加true则直接覆盖之前的数据
            fileWriter = new FileWriter(pathName,true);
            // 1、写入字符串
//            String str = "\n我们都很相爱";
//            fileWriter.write(str);
            // 2、写入单个字符
            fileWriter.write('张');
            // 3、写入数组
//            char[] chars = {'张','江','博'};
//            fileWriter.write(chars);
            // 4、写入数组指定内容
//            char[] chars = {'张','江','博'};
//            fileWriter.write(chars,0,1);
            // 5、写入字符串指定内容
            String str = "你好啊,我的朋友们";
            fileWriter.write(str,0,3);
            // 注意点
            fileWriter.flush();
            System.out.println("数据写入完成");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                if(Objects.equals(null,fileWriter)){
                    fileWriter.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

4、字节流和处理流

在这里插入图片描述
在这里插入图片描述

4.1、节点流和处理流的区别

  1. 节点流是底层流/低级流,直接跟数据源相接
  2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供方便的方法来完成输入输出。
  3. 处理流对节点流进行包装,使用了修饰器模式,不会直接与数据源相连

作用

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  2. 操作的便捷:处理流可以提供一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

4.2 BufferReader

在这里插入图片描述
BufferReader中封装了Reader类,这使得Reader及子类都可以放到BufferReader内

实现思路:创建节点流,将节点流通过构造器传入到包装流BufferReader中,使用包装流使得功能更加强大

读取方式
readLine 按行读取

readLine 读取文本内的一行数据,当读取到最后一行为空是,返回null

代码展示

package com.zhangjiangbo.cn.reader;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Objects;

/**
 * 使用BufferReader读取文本文件
 */
public class BufferReaderTest {
    public static void main(String[] args) {
        String path = "D:\\测试\\new.txt";
        FileReader fileReader = null;
        try {
            fileReader = new FileReader(path);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        // 创建bufferReader对象
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        // 按行读取 效率高
        String line = "";
        // 说明
        // 1、bufferedReader.readLing()是按照行读取文件
        // 2、当返回null时,则表示文件读取完毕
        try {
            while ((line = bufferedReader.readLine())!=null){
                System.out.println(line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            // 关闭流,这里注意,只需要关闭BufferedReader(最外层)就可以了,因为底层会自动的去关闭节点流
            bufferedReader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

关于只关闭最外层的包装流的源码部分

    public void close() throws IOException {
        synchronized (lock) {
            if (in == null)
                return;
            try {
                in.close();
            } finally {
                in = null;
                cb = null;
            }
        }
    }

其中in 就是动态穿进去的节点流对象

4.3、BufferedWriter

注意

  • Writer节点流的new FileWriter(path,true) 是否覆盖
  • 将数据写入后注意调用flash方法,否则数据写不到文件内
  • 关闭流时,只关闭最外层包装流即可,它会自动调用底层方法帮我们关闭节点流

使用方法
newLine()

newLine() 切换到下一行,当将数据写入到文件后使用此方法可以完成换行

write(String str)

write() 通过此方法写入数据

代码展示

package com.zhangjiangbo.cn.write;

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

/**
 *  使用BufferedWriter将"hello,小迷你"写入到文件中去
 */
public class BufferedWriterTest {
    public static void main(String[] args) {
        String path = "D:\\测试\\new.txt";
        // 创建节点流
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(path,true);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 创建包装流
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        try {
            bufferedWriter.newLine();
            bufferedWriter.write("hello,小迷你");
            // 插入一个和系统相关的换行符
            bufferedWriter.newLine();
            bufferedWriter.write("hello2,小迷你");
            bufferedWriter.newLine();
            bufferedWriter.write("hello3,小迷你");
            bufferedWriter.newLine();
            bufferedWriter.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 关闭外层流即可,传入的FileWriter会在底层关闭
        try {
            bufferedWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4.4、通过包装流实现文件的拷贝

    // 通过包装流,进行文件拷贝
    // BufferedReader 和 BufferedWriter是对字符进行操作的,
    // 不要去操作二进制文件,如果去操作二进制文件会导致文件损坏
    @Test
    public void test02() throws IOException {
        String pathName = "D:\\测试\\test03.txt";
        String toPathName = "D:\\测试\\test04.txt";
        // 创建读取节点流
        FileReader fileReader = new FileReader(pathName);
        // 创建输出节点流
        FileWriter fileWriter = new FileWriter(toPathName);
        // 创建读取包装流
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        // 创建输出包装流
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        String line = null;
        while ((line=bufferedReader.readLine())!=null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();

        bufferedWriter.close();
        bufferedReader.close();
    }

4.5、使用包装流实现对二进制文件(图片、音乐、视频等)的拷贝

 @Test
    public void test03() throws IOException {
        String pathName = "D:\\测试\\test02\\mini.jpg";
        String toPathName = "D:\\测试\\mini.jpg";

        // 创建读取节点流
        FileInputStream fileInputStream = new FileInputStream(pathName);
        // 创建输出节点流
        FileOutputStream fileOutputStream = new FileOutputStream(toPathName);
        // 创建读取包装流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        // 创建输出包装流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
        byte[] chars = new byte[1024];
        int count = 0;
        while (true){
            count = bufferedInputStream.read(chars);
            if(count==-1){
                break;
            }
            bufferedOutputStream.write(chars,0,count);
        }
        bufferedOutputStream.flush();

        bufferedInputStream.close();
        bufferedOutputStream.close();
    }

4.6、ObjectInputStream和ObjectOutputStream

看一个需求
1、将int num = 100 这个int数据保存到文件中,注意不是100数字,而是int 100 并且能够从文件中直接回复 int 100
2、将Dog dog = new Dog(“小黄”,3)这个dog对象,保存到文件中,并且能够从文件回复
3、上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化

序列化和反序列化

  • 序列化就是在保存数据时,保存数据的值和数据类型
  • 反序列化就是在回复数据时,恢复数据的值和数据类型
  • 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一
    • Serizalizable // 这是一个标记接口,没有方法
    • Externalizable // 该接口有方法需要实现,因此我们一般实现上面的Serializable接口

应用案例
1、使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name,age),并保存到data.dat 文件中

package com.zhangjiangbo.cn.outputStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 演示 ObjectOutStream的使用,完成数据的序列化
 */
public class ObjectOutStreamTest {
    public static void main(String[] args) throws IOException {

        // 序列化之后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String pathName = "D:\\测试\\data.dat";
        // 创建节点流对象
        FileOutputStream fileOutputStream = new FileOutputStream(pathName);
        // 创建包装流对象
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        // 序列化数据到文件中
        objectOutputStream.write(100); // int -> Integer 底层实现了自动装箱(实现了Serializable)
        objectOutputStream.writeBoolean(true); // boolean -> Boolean (实现了Serializable)
        objectOutputStream.writeChar('a'); // char -> Character (实现了Serializable)
        objectOutputStream.writeDouble(8.6); // double -> Double (实现了Serializable)
        objectOutputStream.writeUTF("张江博"); // String  (实现了Serializable)
        // 保存一个dog对象 Dog必须实现序列化接口,否则会报异常
        objectOutputStream.writeObject(new Dog("小黄",3));
        objectOutputStream.close();
        System.out.println("数据保存完毕(序列化形式)");
    }
}

// 注意实现序列化接口
class Dog implements Serializable {

    private String name;
    private int age;

    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2、取出案例1保存在data.dat文件中的数据

注意点:取出时的顺序要和存储的顺序要保持一致,并且存储对象时必须是同一个包下的对象,因为保存的时候会将对象的报名也保存上,否则取出会报错

package com.zhangjiangbo.cn.inputStreams;

import com.zhangjiangbo.cn.bean.Dog;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反序列化
 * 取出案例1保存的序列化数据
 */
public class ObjectInputStreamTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // 指定反序列化文件地址
        String pathName = "D:\\测试\\data.dat";
        // 创建节点流对象
        FileInputStream inputStream = new FileInputStream(pathName);
        // 创建包装流对象
        ObjectInputStream objectOutputStream = new ObjectInputStream(inputStream);
        // 读取的时候读取的顺序要与保存的保持一致
        int read = objectOutputStream.readInt();
        System.out.println(read);
        boolean b = objectOutputStream.readBoolean();
        System.out.println(b);
        char c = objectOutputStream.readChar();
        System.out.println(c);
        double v = objectOutputStream.readDouble();
        System.out.println(v);
        String s = objectOutputStream.readUTF();
        System.out.println(s);
        Object o = objectOutputStream.readObject();
        System.out.println(o);

        objectOutputStream.close();

        Dog dog = (Dog)o;
        String name = dog.getName();
        System.out.println(name);
        int age = dog.getAge();
        System.out.println(age);
    }
}

注意点

  • 读写顺序要一致
  • 要求序列化或反序列化对象,需要实现Serializable接口
  • 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
  • 序列化对象时,默认将里面所有属性都进行序列化,但除了static(静态的)或transient(转瞬即逝的)修饰的成员
  • 序列化对象时,要求里面属性的类型也需要实现序列化接口(比如其中一个属性是一个类,这个类也是要实现序列化的)
  • 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

4.7、标准输入流输出流

类型默认设备
System.in 标准输入InputStream键盘
System.out 标准输出PrintStream显示器

代码展示

package com.zhangjiangbo.cn.standard;

import java.util.Scanner;

/**
 *
 */
public class InputAntOutPut {
    public static void main(String[] args) {
        // System.in
        // System 类的 public final static InputStream in = null;属性
        // System.in 编译类型 InputStream
        // System.in 运行类型 BufferedInputStream
        // 表示标准输入 键盘
        System.out.println(System.in.getClass());

        // System.out
        // System 类的 public final static PrintStream out = null;
        // 编译类型 PrintStream
        // 运行类型 PrintStream
        // 表示标准输出 显示器
        System.out.println(System.out.getClass());

        System.out.println("张江博,要加油鸭!!!");

        // Scanner 扫描器
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入内容");
        String next = scanner.next();
        System.out.println(next);
    }
}

4.8、转换流-InputStreamReader 和 OutputStreamWriter

问题引导,中文出现乱码

/**
 * 引导出问题,中文乱码问题
 */
public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        // 读取一个字符文件将内容输出到控制台
        // 默认情况下读取文件是按照utf-8编码 
        String pathName = "D:\\测试\\new.txt";
        // 创建字符流
        FileReader fileReader = new FileReader(pathName);
        // 创建处理流
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line = null;
        while ((line = bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        bufferedReader.close();
    }
}

默认情况下读取文件是按照utf-8编码 当文件编码格式不是utf-8编码时就会发生中文乱码问题
此时需要转换流来处理 指定文件编码格式

解决办法 使用转换流多包装了一层,修改使用字节流读取文件,后使用bufferedReader转换

InputStreamReader()对象通过构造器传入节点流和编码格式,返回转换流之后在使用包装流包装读取数据

public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        // 读取一个字符文件将内容输出到控制台
        // 默认情况下读取文件是按照utf-8编码
        String pathName = "D:\\测试\\new.txt";
        // 创建字符流
        FileInputStream fileInputStream = new FileInputStream(pathName);
        // 创建转换流
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"gbk");
        // 创建包装流
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String line = null;
        while ((line = bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        bufferedReader.close();
    }
}

将字节流FileOutputStream 包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式)

    /**
     * 演示OutputStreamWriter(转换流)的使用
     * 将字节流FileOutputStream 包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式)
     */
    @Test
    public void test01() throws IOException {
        String path = "D:\\测试\\test05.txt";
        // 创建节点流 加true不会覆盖
        FileOutputStream fileOutputStream = new FileOutputStream(path,true);
        // 创建转换流
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk");
        // 创建包装流
        BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
        String str = "张江博,要加油鸭!!!";
        bufferedWriter.write(str);
        bufferedWriter.newLine();
        bufferedWriter.flush();
        bufferedWriter.close();
    }

4.9、打印流-PrintStream 和 PrintWriter

只有输出流没有输入流
PrintStream 字节流
PrintWriter 字符流

/**
 * 演示 PrintStream 字节打印/输出流
 */
public class PrintStreamTest {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        // 在默认的情况下, PrintStream打印数据的位置是标准输出,即显示器
        out.print("hello");
        /**
         *
         * 底层调用方法
         *     public void print(String s) {
         *         if (s == null) {
         *             s = "null";
         *         }
         *         write(s);
         *     }
         *     真正执行的是write方法
         * 我们也可以直接调用write方法直接进行输出
         */
        out.write("你好".getBytes());
        out.close();
        // 我们可以修改打印流输出的位置
        System.setOut(new PrintStream("D:\\测试\\test05.txt"));
        System.out.println("hello 这是文件输出");
    }
}
/**
 * PrintWriter 使用方法
 */
public class PrintWriterTest {
    public static void main(String[] args) throws IOException {
        // 会输出到控制台
        // PrintWriter printWriter = new PrintWriter(System.out);
        // 输出到文件
        PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\测试\\test05.txt"));
        printWriter.print("hi,张江博");
        // 一定要关闭,否则写不进文件 ,只有close之后才会将数据写进文件
        printWriter.close();
    }
}

4.10、 Properties类

从配置文件获取属性的值

要求配置文件中数据的格式

  • 专门用于读写配置文件的集合类
    - 配置文件格式:key=value
  • 注意:键值对不需要有空格,值不需要用引来引起来,默认类型是String

不使用Properties类获取

public class PropertiseTest {
    public static void main(String[] args) throws IOException {
        // 读取mysql.properties配置文件中的值
        // 使用原先的方法
        String path = "src/main/resources/mysql.properties";
        FileReader fileReader = new FileReader(path);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line = null;
        while ((line = bufferedReader.readLine()) != null){
            String[] split = line.split("=");
            System.out.println(split[0]+"值为:"+split[1]);
        }
    }
}

Properties的常见方法

  • load:加载配置文件的键值对到Properties对象
  • list:将数据显示到指定设备
  • getProperty(key):根据键获取值
  • setProperty(key,value):设置键值对到Properties对象
  • store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
   /**
     * 使用Propertise类获取配置文件数据
     */
    @Test
    public void test01() throws IOException {
        // 创建Properties对象
        Properties properties = new Properties();
        String path = "src/main/resources/mysql.properties";
        FileReader fileReader = new FileReader(path);
        // 加载指定配置文件
        properties.load(fileReader);
        // 吧数据显示到控制台
        properties.list(System.out);
        // 根据key获取对应的值
        String possword = properties.getProperty("possword");
        System.out.println(possword);
    }

    /**
     * 使用Propertise类来创建配置文件或者修改配置文件
     */
    @Test
    public void test02() throws IOException {
        // 创建对象
        Properties properties = new Properties();
        // 创建
        // 如果该文件没有key,就是创建
        // 如果有这个key,就是修改
        properties.setProperty("charset","utf-8");
        properties.setProperty("user","张江博");
        properties.setProperty("possword","xiaoxiaomini.521");

        // 将k-v存储到文件中
        properties.store(new FileOutputStream("src/main/resources/mysql2.properties"),null);
        System.out.println("保存配置文件成功");
    }

可能会遇到的问题

1、读取到文件中中文乱码,查看程序设置的字符集是否是UTF-8
在这里插入图片描述

待补充…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值