IO流【字节流、字符流、缓冲流、转换流、序列化流】

1、IO流

IO流就是把数据以流的形式在其它设备和内存中传输,就像水流;

根据流动方向课分为:

  • 输入流 :把数据从其他设备上读取到内存中的流。
  • 输出流 :把数据从内存 中写出到其他设备上的流

在这里插入图片描述

2、字节流

所有的文件都是以二进制存储在计算机上的,都是一个字节一个字节的

字节输出流【OutPutStream】

java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
  • public abstract void write(int b) :将指定的字节输出流。
FileOutputStream类

一个参数的构造方法传递一个文件路径字符串或一个File对象,此构造方法是当文件存在时,会重写里面的内容,每次执行都是一个新的文件,不会追加写在里面,若要追加写,则应该用另一个构造方法。

  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。
  • public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。

这两个构造方法,参数中都需要传入一个boolean类型的值,true 表示追加数据,false 表示清空原有数据

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //字节输出流,此构造方法数据不追加
        FileOutputStream stream = new FileOutputStream(new File("E:\\aaa\\1.txt"));

        //一次写一个字节
        stream.write(97);
        stream.write(98);
        stream.write(99); //运行结果为:abc

        //写一个字节数组
        stream.write("你好".getBytes());//运行结果为:你好

        //写入一个指定数组的指定索引处
        stream.write("你好Hello".getBytes(),3,8);//运行结果为:Hello

        stream.close();
    }
}

追加写:

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //字节输出流,此构造方法数据追加
        FileOutputStream stream = new FileOutputStream(new File("E:\\aaa\\1.txt"),true);

        //换行
        stream.write("\r\n".getBytes());
        //一次写一个字节
        stream.write(97);
        stream.write(98);
        stream.write(99); 

        //写一个字节数组
        stream.write("你好".getBytes());

        //写入一个指定数组的指定索引处
        stream.write("你好Hello".getBytes(),3,8);

        stream.close();
    }
}

Windows系统里,换行符号是\r\n

字节输入流【InputStream】

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read(): 从输入流读取数据的下一个字节。
  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
FileInputStream类
  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

读取字节read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1

public class Demo3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(new File("E://aaa//1.txt"));

        //读一个字节
//        int read = fileInputStream.read();
//        System.out.println((char) read);
//
//        while((read = fileInputStream.read()) != -1){
//            System.out.println((char)read);
//        }

        //数组读取
        byte[] b = new byte[1024];
        int len;
        while((len=fileInputStream.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }

//        fileInputStream.read(b);
//        System.out.println(new String(b));
        fileInputStream.close();
    }
}

练习:文件复制

将E:\aaa\bb\1.jpg文件复制到E:\aaa\cc\2.jpg下

public class Demo4 {
    public static void main(String[] args) throws IOException {
        long l = System.currentTimeMillis();
        FileInputStream fileInputStream = new FileInputStream(new File("E:\\aaa\\bb\\1.jpg"));
        FileOutputStream fileOutputStream = new FileOutputStream(new File("E:\\aaa\\cc\\2.jpg"));

        byte[] b = new byte[1024];
        int len;
        while ((len = fileInputStream.read(b)) != -1){
            fileOutputStream.write(b,0,len);
        }

        fileInputStream.close();
        fileInputStream.close();
        long l2 = System.currentTimeMillis();
        System.out.println(l2-l);
    }
}

流的关闭原则:先开后关,后开先关

3、字符流

字符输入流【Reader】

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read(): 从输入流读取一个字符。
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中
FileReader类

java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区

构造方法

  • FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。
  • FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的名称

一个一个字符读取;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader(new File("E:\\aaa\\1.txt"));

        int read = fileReader.read();
        System.out.println((char) read);
        while((read = fileReader.read()) != -1){
            System.out.println((char) read);
        }
        fileReader.close();
    }
}

字符输出流【Writer】

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地

  • void write(int c) 写入单个字符。
  • void write(char[] cbuf)写入字符数组。
  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
FileWriter类
public class Demo6 {
    public static void main(String[] args) throws IOException {
        FileWriter fileWReader = new FileWriter(new File("E:\\aaa\\2.txt"));

        fileWReader.write("你好java");

        fileWReader.flush();
        //fileWReader.close();
    }
}

注意:

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush 方法了

4、Properties类

方法:

  • public Object setProperty(String key, String value) : 保存一对属性。

  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

  • public Set<String> stringPropertyNames() :所有键的名称的集合

  • public void load(InputStream inStream): 从字节输入流中读取键值对

public class Demo7 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileReader("E:\\aaa\\2.txt"));

        Set<String> key = properties.stringPropertyNames();
        for (String s : key) {
            System.out.println(s+"::"+ properties.getProperty(s));
        }
    }
}
/*
运行结果:
334::你好
file::java
*/

5、缓冲流

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率,缓冲流读写方法与基本的流是一致的。

字节缓冲流

public class Demo8 {
    public static void main(String[] args) {

        long start = System.currentTimeMillis();
        try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("E:\\aaa\\bb\\1.zip"));
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("E:\\aaa\\cc\\2.zip"));
                ){
            int b;
            byte[] bytes = new byte[1024*3];
            while((b = bufferedInputStream.read(bytes)) != -1){
                bufferedOutputStream.write(bytes,0,b);
            }

        }catch (IOException e){
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");
    }
}
//4032毫秒

通过复制一个大文件发现,缓冲流的效率远远高于普通的字节流

字符缓冲流

public class Demo9 {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("E:\\aaa\\1.txt"));

        String s = bufferedReader.readLine();
        String s2 = bufferedReader.readLine();
        String s3 = bufferedReader.readLine();

        System.out.println(s);
        System.out.println(s2);
        System.out.println(s3);
        bufferedReader.close();
    }
}

练习:文本排序

将下图文件中的内容按序号排序:

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
9.今当远离,临表涕零,不知所言。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo10 {
    public static void main(String[] args) throws IOException{
        BufferedReader bufferedReader = new BufferedReader(new FileReader("E:\\aaa\\1.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("E:\\aaa\\3.txt"));
        Map<String ,String> map = new HashMap<>();

        String s = null;
        while((s = bufferedReader.readLine()) != null){
            String[] split = s.split("\\.");
            map.put(split[0],split[1]);
        }
        Set<String> strings = map.keySet();
        for (String string : strings) {
            System.out.println(string+"::"+map.get(string));
        }
        //


        for (int i = 1; i <= map.size(); i++) {
            String st = String.valueOf(i);

            String s1 = map.get(st);

            bufferedWriter.write(st+"."+s1);
            bufferedWriter.newLine();
        }

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

6、转换流

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码 。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码

常见的编码集:GBKASCII字符集utf-8ISO-8859-1字符集

如果文件的编码和解码的编码集不同就会出现乱码。

InputStreamReader类&OutputStreamWriter类

转换流java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。
转换流java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。
默认编码集为:utf-8

import java.io.*;

public class Demo11 {
    public static void main(String[] args) throws IOException {
        //OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("E:\\aaa\\6.text"),"Utf-8");
        InputStreamReader ir = new InputStreamReader(new FileInputStream("E:\\aaa\\6.text"),"GBK");

        int r ;
        while((r = ir.read()) != -1){
            System.out.print((char) r);
        }
        // ow.write("你好java");
        //ow.close();
    }
}

7、序列化

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据对象的类型对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化对象的数据对象的类型对象中存储的数据信息,都可以用来在内存中创建对象

ObjectOutputStream类&ObjectInputStream类

java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。
ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

被序列化或反序列化的对象的类需要实现Serializable 接口,否则就会出现序列化或反序列化异常

Person类:

import java.io.Serializable;

public class Person implements Serializable{
    private String name;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

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

public class Demo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //Person p = null//new Person("张三");

//        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream("E:\\aaa\\a.txt"));
//
//        oo.writeObject(p);
//
//        oo.close();

        ObjectInputStream oi = new ObjectInputStream(new FileInputStream("E:\\aaa\\a.txt"));

        Object o = oi.readObject();
        System.out.println(o.toString());

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值