JavaSE学习之IO流

JavaSE学习之IO流

一. IO流

在这里插入图片描述
IO流的作用: 用来完成数据的传输
IO流的分类:
按照流向分类: 输入流,输出流
按照操作数据的类型: 字节流,字符流
IO流学习的前提:
1.所有文件都是以字节的形式存在的,它们的最小存储单元都是字节
2.输入和输出: 我们站在内存的角度去考虑输入和输出

二.字节流

1.字节输入流

FileInputStream
构造方法:
FileInputStream(File file) FileInputStream(String name)
如果关联的文件不存在的话,抛出异常(FileNotFoundException)
成员方法:
public int read(int b): 读取一个字节,读到文件末尾,值返回-1;

2.字节输出流

FileOutputStream
构造方法:
FileOutputStream(File file) FileOutputStream(String name)
输出流关联的文件如果不存在的话,会自动创建
输出流关联的文件如果已存在,则会将其内容清空(有不会清空的方法)
成员方法:
public void write(int b): 写出一个字节

3.一个字节一个字节的拷贝

// 创建输入流对象
FileInputStream fis = new FileInputStream("E:/Projects/study/src/resource/aaa.text");
// 创建输出流对象
FileOutputStream fos = new FileOutputStream("E:/Projects/study/src/resource/Copyaaa.text");
// 使用输入流读取
// 创建变量, 用来记录每一次读取到的字节
int b;
while ((b = fis.read()) != -1) {
    // 使用输出流写出
    fos.write(b);
}
// 关闭输出流
fos.close();
// 关闭输入流
fis.close();

4.数组拷贝

使用到的成员方法:

FileOutputStream -----write

public void read(	byte[] b,    //数组
 					int off,     //开始索引
					int len)     //长度,字节个数
写出b数组中从off开始的len个字节

FileInputStream ----read

public int read(byte[] b) : 将文件中的字节, 读取到b数组中
							read方法的返回, 返回的是读取到有效的字节个数
							如果读取到文件的末尾, 返回-1
拷贝
// 创建输入流对象
FileInputStream fis = new FileInputStream("Day09_io\\aaa.txt");
// 创建输出流对象
FileOutputStream fos = new FileOutputStream("Day09_io\\copyAaa.txt");
// 创建字节数组
byte[] arr = new byte[1024 * 8];
// 创建变量, 用来记录读取到有效的字节个数
int len;
// 使用输入流读取
while ((len = fis.read(arr)) != -1) {
    // 使用输出流写出
    fos.write(arr, 0, len);
}

// 关闭输出流
fos.close();
// 关闭输入流
fis.close();

三.字符流

只能操作我们能看懂的纯文本文件,不过一般也不用

1.字符输出流

FileWriter

public void write(int c) : 写出单个字符
public void write(String str) : 写出字符串
2.字符输入流

FileReader

public int read():读取单个字符

从网络下载

public class DemoIOStream {
    public static void main(String[] args) throws IOException {
        URL url = new URL("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2655406508,1191616699&fm=26&gp=0.jpg");
        // 打开输入流
        InputStream is = url.openStream();
        // 创建输出流
        FileOutputStream fos = new FileOutputStream("E:/Projects/study/src/resource/aaa.text");

        // 创建字节数组
        byte[] arr = new byte[1024 * 8];
        // 创建变量, 用来记录读取到有效的字节个数
        int len;

        while ((len = is.read(arr)) != -1) {
            fos.write(arr, 0, len);
        }

        fos.close();
        is.close();
    }
}

四.异常处理

finally: 释放资源

1.jdk1.6之前
public class DemoIOStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("E:/Projects/study/src/resource/aaa.text");

            fis.read();
        }finally {
            // 非空判断  inn
            if (fis != null) {
                // 流尽量能够关掉, 将关流的代码放在finally中
                fis.close(); // 1. 作用域 2.局部变量初始化
            }
        }
    }
}
2.jdk1.7

1.7版本出现了AutoCloseable

        try (FileInputStream fis = new FileInputStream("E:/Projects/study/src/resource/aaa.text");) {
            fis.read();
        }
3.jdk1.9
FileInputStream fis = new FileInputStream("E:/Projects/study/src/resource/aaa.text");
try (fis) {
    fis.read();
}

五.Properties类

public void load(InputStream inStream): 读取输入流关联配置文件中的, 配置信息(键值对)

		// 通过Properties, 获取配置文件中的信息
        Properties p = new Properties();
        // 创建和配置文件关联的输入流
        // FileInputStream fis = new FileInputStream("E:/Projects/study/src/resource/config.properties");
        
        InputStream fis = DemoIOStream.class.getClassLoader().getResourceAsStream("config.properties");
        p.load(fis);
        // 关流
        fis.close();
        // getProperty()
        String user = p.getProperty("user");
        String password = p.getProperty("password");
        System.out.println(user + "---" + password);

properties文件

六.缓冲流

1.字节流

带缓冲区的字节输入流(高效的字节输入流)
BufferedInputStream
构造方法

public void BufferedInputStream(InputStream in)

带缓冲区的字节输出流(高效的字节输出流)
BufferedOutputStream

public void BufferedOutputStream(OutputStream out)

拷贝

		// 创建输入流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("Buffer\\actor.mp3"));
        // 创建输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Buffer\\copyActor.mp3"));
        // 使用输入流读取
        int b;
        while ((b = bis.read()) != -1) {
            // 使用输出流写出
            bos.write(b);
        }
        // 关闭输出流
        bos.close();
        // 关闭输入流
        bis.close();
2.字符流

带缓冲区的字符流
BufferedReader
构造方法

public BufferedReader(Reader in)

特有方法

public String readLine(): 读取一个文本行,遇到换行符就结束,读取到文件末尾会返回null

换行符
windows默认的换行符: “\r\n”

​ \t: 制表符 tab

​ \" : 单个双引号, 没有任何其他含义, 只是一个字符

带缓冲区的字符输出流
BufferedWriter
构造方法

public BufferedWriter(Writer out)

特有方法

public void newLine(): 写出跨平台换行符

面试题

  • close()和flush()方法的区别?
    • 如果使用的输出流带有缓冲区(数组), 写出的内容会先写到缓冲区中, 然后在从缓冲区中刷出到文件上.
    • 缓冲区中内容刷出到文件有两种方式:
    • 缓冲区满了, 自动刷出.
    • 手动刷出.
    • close() : 在关闭输出流之前, 刷出了一次缓冲区.
    • flush(): 刷出缓冲区中的内容到文件

七.转换流

  • 指定字符集进行读写
  • 转换流是字符流

输入流
InputStreamReader

public InputStreamReader(InputStream in, String charsetName)
    是字节流通向字符流的桥梁
    可以通过指定的字符集将字节转换成字符

输出流
OutputStreamWriter

public OutputStreamWriter(OutputStream out, String charsetName)
    是字符流通向字节流的桥梁
    可以通过指定的字符集将字符转换成字节

转换流拷贝

public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 创建转换流的输入流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\gbk.txt"), "gbk");
        // 创建转换流的输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Demo01\\utf-8.txt"), "utf-8");

        int c;
        while ((c = isr.read()) != -1) {
            osw.write(c);
        }

        osw.close();
        isr.close();
    }
}

需求

  • 文件上是中文, 读取这个文件, 只能获取到字节流, 想要读取一行.

  • 能够得到FileInputStream(字节流)

    ​ 转换↓

  • 需要读取一行: BufferedReader(字符流)

BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("Demo01\\aaa.txt")));
        String s = br.readLine();
        System.out.println(s);
        br.close();

八.序列化流

序列化流是字节流

1.流对象解析

输出流

  • 序列化流, 对象输出流 — ObjectOutputStream
  • 构造方法
public ObjectOutputStream(OutputStream out)
  • 成员方法
public final void writeObject(Object obj)

输入流

  • 反序列化流, 对象输入流 — ObjectInputStream
  • 构造方法
public ObjectInputStream(InputStream in)
  • 成员方法
public final Object readObject()
2.序列化字符串
  • 序列化
public class Demo01_序列化 {
    public static void main(String[] args) throws IOException {
        // 创建序列化流对象, 对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Demo01\\object.txt"));
        // 写出字符串对象
        oos.writeObject("你好");
        // 关流
        oos.close();
    }
}
  • 反序列化
public class Demo01_反序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 反序列化流, 对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Demo01\\object.txt"));
        // 读取对象
        String o = (String) ois.readObject();
        System.out.println(o);
        // 关流
        ois.close();
    }
}
3.序列化自定义对象
  • 自定义对象
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    // 瞬时, 瞬态: 序列化时跳过此变量
    private transient int age;


    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 序列化
public class Demo02_序列化自定义对象 {
    public static void main(String[] args) throws IOException {
        // 创建对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Demo01\\object.txt"));
        // 创建Person对象
        Person p = new Person("张三", 23);
        // 写出对象
        oos.writeObject(p);
        // 关流
        oos.close();
    }
}
  • 反序列化
public class Demo02_反序列化自定义对象 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 创建对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Demo01\\object.txt"));
        // 读取对象
        Person p = (Person) ois.readObject(); // 找不到.class 字节码文件
        System.out.println(p);
        // 关流
        ois.close();
    }
}
  • 为什么要用序列化?
  • 当两个进程在进行远程通信时,对彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。
    把对象转换为字节序列的过程称为对象的序列化。
    把字节序列恢复为对象的过程称为对象的反序列化。
    说的再直接点,序列化的目的就是为了跨进程传递格式化数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值