java I/O流(字节流、字符流)

基于白嫖:2020最新版 Java基础-IO框架

1 概述

  • 流:内存和存储设备之间传输数据的通道;
  • 输入流:将存储设备中的内容读入到内存中;
  • 输出流:将内存中的内容写入到存储设备中;
  • 字节流:以字节为单位,可以读写所有数据;
  • 字符流:以字符为单位,只能读写文本数据;
  • 节点流:具有实际传输数据的读写功能;
  • 过滤流:在节点流的基础之上增强功能;

2 继承关系

在这里插入图片描述

3 字节流

3.1 抽象父类InputStream

字节输入流父类抽象类InputStream实现了Closeable接口,定义了一个输入流应该具有的方法。

  • int available():返回估计可以访问的字节数;
  • void close():关闭此输入流并释放相关资源;
  • void mark(int readlimit):标记当前位置;
  • boolean markSupported():测试该输入流是否支持markreset方法;
  • abstract int read():读入下一个字节;
  • int read(byte[] b):读入一定数量的字节,并将其缓存在b中,返回读到的个数;
  • int read(byte[] b, int off, int len):讲输入流中最多len个数据读入到b中,返回读到的个数;
  • void reset():重新定位到最新的mark位置;
  • long skip(long n):跳过和丢弃n个字节;

3.2 抽象父类OutputStream

字节输出流父类抽象类实现了CloseableFlushable接口。

  • void close():关闭输出流并释放资源;
  • void flush():刷新强制所有的缓冲写出输出字节;
  • void write(byte[] b):将b写入到输出流;
  • void write(byte[] b, int off, int len):指定b[off,off+len)长的字节写出流;
  • abstract void write(int b):抽象方法,将指定一个字节输出到流;

3.3 文件字节流

FileInputStreamFileOutputStream分别继承InputStreamOutputStream实现其方法,用于从文件读入和写出字节;

3.3.1 FileInputStream

可以直接使用文件名路径字符串来实例化:

FileInputStream fileInputStream = new FileInputStream("data.txt");

如果文件不存在,抛出FileNotFoundException
一般采用读入到byte数组的方式进行读取数据;

3.3.2 FileOutputStream

FileOutputStream outputStream = new FileOutputStream("data.txt");
String data = "aaAA";
outputStream.write(data.getBytes());

可以覆盖和追加内容,写入字节或者字节数组;

3.3.3 文件复制

public static void main(String[] args) {
    try {
        FileInputStream fileInputStream = new FileInputStream("data.txt");
        FileOutputStream fileOutputStream=new FileOutputStream("out.txt");
        //假设数组是3
        byte[] buf=new byte[3];
        int num=0;
        while ((num=fileInputStream.read(buf))!=-1){
            fileOutputStream.write(buf,0,num);
        }
        fileInputStream.close();
        fileOutputStream.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

建立缓冲区,每次读入到buf,把实际读入的个数返回给num,然后同时写入到输出流,注意写出的参数是左闭右开的;

3.4 字节缓冲(buffer)流

数据存储在缓冲区中,提高效率。

3.4.1 BufferedInputStream

要学习BufferedInputStream先学习FilterInputStream(过滤器输入流),FilterInputStream过滤器流继承自InputStream,内部还含有一个InputStream成员变量,这是典型的装饰器模式,当调用对外显示的方法时候,一方面执行成员变量的方法,另一方面添加自己的私货;

BufferedInputStream继承自FilterInputStream,构造方法需要传入一个InputStream(装饰器模式的上一级对象),内部成员变量有一个byte[]类型的缓冲区。

为什么需要使用缓冲区?使用FileInputStream时候,每一次read()都会直接去磁盘进行读取文件操作,消耗较大的IO时间,而使用了BufferedInputStream,会先读入一部分到缓冲区(内存),当read()的时候先去缓冲区(内存)找,如果没有才继续又读入下一批数据到缓冲区,然后返回read()需要的值,减少了IO次数。

3.4.2 BufferedOutputStream

public static void main(String[] args) {
    try {
        FileOutputStream outputStream = new FileOutputStream("data.txt");
        BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
        bufferedOutputStream.write(65);//不会立即写入,先放缓存区
        bufferedOutputStream.write(66);//不会立即写入,先放缓存区
        bufferedOutputStream.flush();//刷新一下才回存入硬盘
        bufferedOutputStream.close();//会主动关闭FileOutputStream,也会调用flush
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

当写入的时候,不会立即写入到磁盘,而是先写入缓存区,当缓存区满的时候再写入磁盘或者主动调用flush()或者close(),减少IO次数,提高效率;

3.5 对象流(序列化)

3.5.1 Serializable接口

public interface Serializable {
}

该接口,没有定义任何抽象方法,对于实现这个接口的类来说就是一个标记类,标记这个类可以被序列化。
如果不想序列化某一个属性使用关键字:transient,静态属性不属于对象所以也不能序列化;

3.5.2 ObjectInputStream

继承InputStream抽象类,实现ObjectInputObjectStreamConstants接口;使用了缓冲区功能;增强了读写8种基本类型字符串功能;增强了读写对象的功能。

FileInputStream fileInputStream=new FileInputStream("stu.object");
ObjectInputStream objectInputStream =new ObjectInputStream(fileInputStream);
Student student= (Student) objectInputStream.readObject();
System.out.println(student.toString());

3.5.3 ObjectOutputStream

FileOutputStream fileOutputStream=new FileOutputStream("stu.object");
ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
Student stu=new Student(1,"Tom");
objectOutputStream.writeObject(stu);
objectOutputStream.close();

注意初始化对象输出流的时候需要有一个基流对象作为其成员变量(装饰者模式),由于Collection接口下面的实体类基本上都实现了Serializable接口,所以可以传入一个集合实体类。

3.6 字节数组流(ByteArrayStream)

ByteArrayInputStreamByteArrayOutputStream**字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。**该流的目的内存to内存,适用于内存到内存的一些操作,比如对象的复制clone()。最重要的就是一个字节数组作为中间的媒介。

4 字符流

4.1 字符编码

  • ISO-8859-1:收录ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号;
  • UTF-8:针对Unicode码表的可变长字符编码;国际上多一些,最长使用3 Bytes来表示一个字符;
  • GB2312:简体中文;
  • GBK:简体中文、扩充;
  • BIG5 台湾,繁体中文;

4.2 抽象父类Reader和Writer

和字节流的抽象父类差不多也是定义了一些基本的想读写方法;

4.3 文件字符流

4.3.1 FileReader

FileReader继承自InputStreamReader。默认的字符编码使用UTF-8

FileReader fileReader =new FileReader("data.txt");
char[] buf=new char[4];
int readNum= 0;
while ((readNum=fileReader.read(buf))!=-1){
    String s=new String(buf,0,readNum);
    System.out.println(s);
}
fileReader.close();

注意字节流读到缓冲区使用的是byte[],而字符流读到的是char[],这就是为什么要字节流和字符流了,在java中char类型用2个字节表示

4.3.2 FileWriter

FileWriter fileWriter=new FileWriter("file.txt");
for(int i=0;i<10;i++){
    fileWriter.write("我爱你中国\n");
}
fileWriter.close();

可以写入字符串、字符数组、字符等。

4.4 字符缓冲流

BufferedReaderBufferedWriter支持高效读写、支持输入换行符、支持读一行写一行。也是装饰者模式,需要有一个基的输入输出流。缓冲流多的方法:

  • 读流中readLine():一行一行的读,返回String,行末返回的null
  • 写流中newLine():写入一个换行符;

4.5 打印流PrintWriter

PrintWriter封装了print()/println()方法,可以像print一行输出到文本;

4.6 转换流

InputStreamReaderOutputStreamWriter可以将字节流转换成字符流,可以设计字符的编码方法;类名的设计刚好是字节流和字符流的两个抽象父类组合在一起。

  • InputStreamReader:从磁盘到内存,可以指定读入文件的编码格式,返回的是一个编码格式的字符;
  • OutputStreamWriter:从内存到磁盘,可以指定写文件的编码格式;

5 File类

5.1 概述

FIle类代表了物理盘符中的一个文件或者一个文件夹;

5.2 常见方法

  • mkdir():创建一个新目录;
  • delete():删除文件或者空目录;
  • exists():判断文件对象是否存在;是
  • getName():获得名字;
  • isFile():是否是文件;
  • length():获得文件的长度;
  • renameTo():修改文件名为;
  • createNewFile():创建新文件;
  • deleteOnExit():JVM退出时删除;

注意:File对象表示的不仅仅是文件,还可以表示文件夹及相关操作;

5.3 例子:打印目录下全部文件

public class Main {
    public static void main(String[] args) {
        File dir0=new File("/home/lwj/IdeaProjects/javaIO/");
        //遍历这个目录
        show(dir0);
    }

    public static void show(File dir){
        //获得该目录全部列表
        File[] files=dir.listFiles();
        for(File file:files){
            if(file.isFile()) System.out.println(file.getAbsolutePath());
            else show(file);
        }

    }
}

6 properties

使用方法上和hashset差不多,但是它常和流相关,所以经常被用来作为一些框架的配置文件.properties

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值