JavaSE进阶——Day10

1-IO流


I:input(输入 | 读取); O:output(输出 | 写出)

读取数据,和写出数据

1.1-作用

  • 用于数据的传输

  • 文件拷贝:

  • 1.文件上传(读取本地文件,将数据写到服务器)

  • 2.文件下载(读取服务器文件,将数据写到本地)

  • ....

1.2-分类

1.按流向分:

  • 输入流

  • 输出流

2.按类型分:

  • 字节流:万能流,计算机中任何一个文件或数据,底层都是以字节的形式进行存储

注意:字节流虽然可以操作任意类型的文件,但是操作纯文本文件的时候,有可能会出现中文乱码问题

-纯文本文件:用记事本打开,可以直接看得懂的文件

  • 字符流:用于读取纯文本文件,能够保证没有中文乱码

1.3-IO流的体系结构

2-字节流

2.1-字节流写出数据

作用:用来写数据

2.1.1-FileOutputStream

构造方法

  • public FileOutputStream(File file) : 创建一个字节输出流 , 向指定File对象的文件中写入内容

  • public FileOutputStream(File file, boolean append) : 第二个参数为true, 表示追加写数据

  • public FileOutputStream(String name) : 创建一个字节输出流 , 向指定名称的文件中写入内容

  • public FileOutputStream(String name, boolean append) : 第二个参数为true, 表示追加写数据

成员方法

  • public void write(int b ) : 将指定字节写入到文件中

  • public void write(byte[] b) : 将字节数组中的字节写入到文件中

  • public void write(byte[] b, int off, int len) : 将字节数组的一部分写到文件中 , b代表的是字节数组, off代表开始索引, len代表个数

  • public void close() : 释放资源 , 断开流与文件之间的联系

注意 : 字节输出流是否可以写一个字符串 ?

  • -String类 : public byte[] getBytes();

字节流常见的两个问题

  1. 换行 :

windows : \r\n 举例 : 输出流对对象.write("\r\n".getBytes())

mac : \r

linux : \n

  1. 追加 :

public FileOutputStream(String file, boolean append) : 第二个参数为true, 表示追加写数据

注意 : 如果构造方法没有打开追加写入的开关, 执行构造会把文件中内容清空

示例

JDK7之前:

package com.lyl.io.output;
​
import java.io.FileOutputStream;
import java.io.IOException;
​
public class IODemo3 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("day10\\a.txt", true);
            fos.write("哈哈哈".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    //目的:就算程序死了,流也要关,所以放在finally里,finally里的代码是一定会执行的
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

JDK7之后

package com.lyl.io.output;
​
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class IODemo4 {
    public static void main(String[] args) throws FileNotFoundException {
        //将需要关流的对象放在try的小括号里,这样就会自动调用close方法了
        try (FileOutputStream fos = new FileOutputStream("day10\\a.txt");){
            fos.write("JDK7之后的方法".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2-字节流读取数据

作用:用来读数据

2.2.1-FileInputStream

构造方法

  • public FileInputStream(File file) : 创建一个字节输入流对象, 从指定File对象的文件中读取数据

  • public FileInputStream(String name) : 创建一个字节输入流对象, 从指定名称的文件中读取数据

成员方法

  • public int read() : 读取一个字节数据并返回 , 读到末位返回 -1

  • public int read(byte[] b) : 把数据读取字节数组中, 并返读到数据的个数返回

读取方式 : 一次读取一个数据 ;一次读取一个字节数组

案例 : 字节流拷贝文件

package com.lyl.io;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class CopyFileTest1 {
    public static void main(String[] args) throws IOException {
        //1,创建字节输入流对象,管理数据源
        FileInputStream fis = new FileInputStream("day10\\a.txt");
        //2,创建字节输出流对象,管理数据目的
        FileOutputStream fos = new FileOutputStream("day10\\copy.txt");
        //3,一个一个读,一个一个写
        int i;
        while ((i = fis.read())!=-1){
            fos.write(i);
        }
        //4,关闭流释放资源
        fis.close();
        fos.close();
    }
}
package com.lyl.io;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class CopyFileTest2 {
    public static void main(String[] args) throws IOException {
        //1,创建字节输入流对象,管理数据源
        FileInputStream fis = new FileInputStream("day10\\a.txt");
        //2,创建字节输出流对象,管理数据目的
        FileOutputStream fos = new FileOutputStream("day10\\copy2.txt");
        byte[] bys = new byte[2048];
        //3.读写操作,一次读取一个数组
        int i;
        while ((i = fis.read(bys)) != -1){
            fos.write(bys,0,i);
        }
        //4,关闭流释放资源
        fis.close();
        fos.close();
    }
}

3-字节缓冲流

介绍 : 提高读写效率

3.1-输入

构造方法 : public BufferedInputStream(InputStream in) : 创建一个缓冲输入流对象,参数是基本的字节输入流

3.2-输出

构造方法 : public BufferedOutputStream(OutputStream out) : 创建一个缓冲输出流对象, 参数是基本的字节输出流

3.3-案例 : 拷贝文件, 测试效率

测试程序大小:29.9 MB (31,367,480 字节)

普通字节流, 单个字节拷贝

package com.lyl.io;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class CopyFileTest1 {
    public static void main(String[] args) throws IOException {
        //测试程序大小:29.9 MB (31,367,480 字节)
        FileInputStream fis = new FileInputStream("D:\\test.exe");
        FileOutputStream fos = new FileOutputStream("E:\\copy.exe");
        //开始时间
        long start = System.currentTimeMillis();
        //一个一个读,一个一个写
        int i;
        while ((i = fis.read())!=-1){
            fos.write(i);
        }
        fis.close();
        fos.close();
        //结束时间
        long end = System.currentTimeMillis();
        //打印时间差,计算耗时
        System.out.println(end - start);
    }
}

输出结果:

131855

  • 耗时131855毫秒

普通字节流 + 自定义数组拷贝

package com.lyl.io;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class CopyFileTest2 {
    public static void main(String[] args) throws IOException {
        //1,创建字节输入流对象,管理数据源
        FileInputStream fis = new FileInputStream("D:\\test.exe");
        //2,创建字节输出流对象,管理数据目的
        FileOutputStream fos = new FileOutputStream("E:\\copy.exe");
        //开始时间
        long start = System.currentTimeMillis();
        //底层源码数组大小为8192,我们让其保持一致
        byte[] bys = new byte[8192];
        //3.读写操作,一次读取一个数组
        int i;
        while ((i = fis.read(bys)) != -1){
            fos.write(bys,0,i);
        }
        //4,关闭流释放资源
        fis.close();
        fos.close();
        //结束时间
        long end = System.currentTimeMillis();
        //打印时间差,计算耗时
        System.out.println(end - start);
    }
}

输出结果:

43

  • 耗时225毫秒

缓冲流单个字节拷贝

package com.lyl.io;
​
import java.io.*;
​
public class CopyFileTest3 {
    public static void main(String[] args) throws IOException {
        //缓冲输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\test.exe"));
        //缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\copy.exe"));
        long start = System.currentTimeMillis();
        int i;
        while ((i = bis.read()) != -1) {
            bos.write(i);
        }
        bis.close();
        bos.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

输出结果:

957

  • 耗时957毫秒

缓冲流 + 自定义数组拷贝

package com.lyl.io;
​
import java.io.*;
​
public class CopyFileTest4 {
    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\test.exe"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\copy.exe"));
        long start = System.currentTimeMillis();
        //自定义数组
        byte[] bys = new byte[8192];
        int i;
        while ((i = bis.read(bys)) != -1) {
            bos.write(bys,0,i);
        }
        bis.close();
        bos.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

输出结果:

53

  • 耗时53毫秒

结论

首选普通字节流 + 自定义数组拷贝更好,因为代码少,效率高,还是自己编写的,逻辑更清晰

注意事项

缓冲流不具备读写功能, 只提供缓冲区, 读写操作, 还是需要依赖于基本的流

4-过渡知识 - 字符集

字符集 : 说的就是编码表

编码表 : 计算机中, 字符到字节的一套对应关系

  • ASCII 码表

  • 问题 : 计算机中, 存储 a 字符是怎么存的 ?

  • 思考 : 计算机中存储数据的单位是什么 ?

    字节

  • 思考 : 字节再往下是什么 ?

    二进制

    所以, 计算机存储任何数据, 都是以二进制的形式进行存储

需要记住的结论

我们在文件中存储的字符, 实际上都有一份数值的表示形式 !

4.1-常见的编码表

  • ASCII : 所有码表都囊括了 ASCII 码表

  • GBK : 中国的码表, 每个中文, 占用2个字节

  • Unicode - UTF-8:万国码, 每个中文, 占用3个字节

4.2-编码-解码

概念介绍 :

  • 编码 : 将看得懂的, 变成看不懂的 (字符转字节)

  • 解码 : 将看不懂的, 变成看得懂的 (字节转字符)

编码

package com.lyl.test;
​
import java.util.Arrays;
​
public class Test {
    public static void main(String[] args) {
        String s = "你好,你好";
        byte[] bytes = s.getBytes();
        System.out.println(Arrays.toString(bytes));
    }
}

输出结果:

[-28, -67, -96, -27, -91, -67, 44, -28, -67, -96, -27, -91, -67]

解码

package com.lyl;
​
public class Test2 {
    public static void main(String[] args) {
        byte[] bytes = {-28, -67, -96, -27, -91, -67, 44, -28, -67, -96, -27, -91, -67};
        String s = new String(bytes);
        System.out.println(s);
    }
}

输出结果:

你好,你好

字符串类 String 的编码解码

4.3-需要重点记住的

如果今后出现了乱码 : 查看编码和解码的方式是否一致

GBK : 每个中文占用2个字节

UTF-8 : 每个中文占用3个字节

英文, 数字, 标点符号, 都占用1个字节

中文的字节表示形式, 第一个肯定是负数

5-IO流-字符流

字符流应用:字节流虽然可以操作任意类型的文件,但是读中文时,可能会出现乱码,字符流就可以解决读写过程中出现乱码的问题

5.1-字符流组成

字节流 + 编码表

5.2-字符流方法

读数据方法:

public int read():一次读取一个字符

public int read(char[] cbuf):一次读取一个字符数组

5.3-分类

FileReader(字符输入流)

概述 : 用来读取字符文件的便捷类

构造方法:public FileReader(String fileName) : 据给定的文件名构造一个FileReader对象

package com.lyl.reader;
​
import java.io.FileReader;
import java.io.IOException;
​
public class ReaderDemo {
    public static void main(String[] args) throws IOException {
​
        FileReader fr = new FileReader("day10\\a.txt");
​
        char[] chars = new char[1024];
        int len;
        while ((len = fr.read(chars)) != -1) {
            String s = new String(chars, 0, len);
            System.out.println(s);
        }
    }
}

a.txt 中的内容:FileReader读取字符文件...展示

输出结果:

FileReader读取字符文件...展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值