Java基础 IO流

IO流

1 字节流

InputStreamOutputStream是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。

字符是一个一个字节读取的,可以读取一切文件,那他读取文本文件可以吗?当读取英文字符时是可以的,因为一个字节表示一个英文字符,可是当我们读取到中文时,一个中文一般由多个字节来表示,如果字节流第一次读取读到一个中文字符的前一般字节,将它输出,这时中文字符就丢失了,所以我们引入了字符流来读取文本文件,而用字节流读取图像视频之类的文件。

当然字节流依然可以读取到字符,下面演示字节流读取中文(不推荐,可能会乱码)

    public static void main(String[] args) throws IOException {
        File file = new File("2.txt");
        //写入字符
        String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(s.getBytes());//字节流只能读写字节,所以需要将字符串转为字节
        //读取
        FileInputStream fis = new FileInputStream(file);
        byte[] arr= new byte[1024];
        int len = 0;
        StringBuilder sb = new StringBuilder();
        while((len=fis.read(arr))!=-1){//如果刚好一个中文字符被分开读取了,那就会乱码
            String s2 = new String(arr, 0, len);//字节数组转为字符串
            sb.append(s2);//字符串拼接
        }
        System.out.println(sb);//昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。

    }

插入

结点流与处理流之间的关系

在诸多处理流中,有一个非常重要,那就是缓冲流。

我们知道,程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。


2 字符流

与字节流类似,字符流也有两个抽象基类,分别是ReaderWriter。其他的字符流实现类都是继承了这两个类。

使用字符流输入输出字符

public static void main(String[] args) throws IOException {
        File file = new File("2.txt");
        //写入字符
        String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
        FileWriter fw = new FileWriter(file);
        fw.write(s);
        //读取
        FileReader fr = new FileReader(file);
        int len = 0;
        char[] arr = new char[1024];
        StringBuilder sb = new StringBuilder();
        while((len=fr.read(arr))!=-1){
            sb.append(arr);
        }
        System.out.println(sb);//输出为空

    }

咦?为什么我们输出为空呢?

注意:关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。

有两种解决方法,一是每次写入后刷新缓冲区,二是关闭流。

flush :刷新缓冲区,流对象可以继续使用。

close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

    public static void main(String[] args) throws IOException {
        File file = new File("2.txt");
        //写入字符
        String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
        FileWriter fw = new FileWriter(file);
        fw.write(s);
        fw.flush();
        //读取
        FileReader fr = new FileReader(file);
        int len = 0;
        char[] arr = new char[1024];
        StringBuilder sb = new StringBuilder();
        while((len=fr.read(arr))!=-1){
            sb.append(arr,0,len);//注意,一定要写清楚追加长度,不让把数组中空的也加进来会乱码
        }
//        fr.close();
//        fw.close();
        System.out.println(sb);//输出为空

    }

3 字节缓冲流

public static void main(String[] args) throws IOException {
    File file = new File("2.txt");
    String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    //写入字符
    bos.write(s.getBytes());
    bos.flush();
    //读取
    int len = 0;
    byte[] arr = new byte[1024];
    StringBuilder sb = new StringBuilder();
    while((len=bis.read(arr))!=-1){
        String s2 = new String(arr,0,len);
        sb.append(s2);
    }
    System.out.println(sb);
}

4 字符缓冲流

public static void main(String[] args) throws IOException {
    File file = new File("2.txt");
    String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
    BufferedReader br = new BufferedReader(new FileReader(file));
    BufferedWriter bw = new BufferedWriter(new FileWriter(file));
    //写入
    bw.write(s);
    bw.flush();
    //读取
    int len = 0;
    char[] arr = new char[1024];
    StringBuilder bs = new StringBuilder();
    while((len=br.read(arr))!=-1){
        bs.append(arr,0,len);
    }
    System.out.println(bs);
}

5 转换流

转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定 的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符 编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

在这里插入图片描述

6 序列化流

在这里插入图片描述

对象可以被序列化的条件:

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

该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任 何状态序列化或反序列化,会抛出 NotSerializableException 。

该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰。 (static修饰的属性无法被序列化)

**注意:**对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。 另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操 作也会失败,抛出一个 InvalidClassException 异常。

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配

  • 该类包含未知数据类型

  • 该类没有可访问的无参数构造方法

    反序列化进行连续读取时,如果读取到最后一个,再读取下一个为空的值时会抛出异常,我们可以再序列化所有数据后,在追加一个null。

    public class ObjectIO {
        public static void main(String[] args){
            Student s1 = new Student(12,"zhansagn");
            Student s2 = new Student(13,"lsii");
            Student s3 = new Student(14,"wangwu");
            Student s4 = new Student(15,"zhaoliu");
            ObjectInputStream ois = null;
            ObjectOutputStream oos = null;
            try {
                File file = new File("obj.txt");
                oos = new ObjectOutputStream(new FileOutputStream(file));
                oos.writeObject(s1);
                oos.writeObject(s2);
                oos.writeObject(s3);
                oos.writeObject(s4);
                oos.writeObject(null);//
                ois = new ObjectInputStream(new FileInputStream(file));
                Object o = null;
                while((o=ois.readObject())!=null){
                    Student s = (Student) o;
                    System.out.println(s);
                }
    
            } catch (IOException e) {
    //            e.printStackTrace();
    //            System.out.println("读取结束");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }finally {
                if(ois!=null){
                    try {
                        ois.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(oos!=null){
                    try {
                        oos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
            }
    
        }
    }
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    class Student implements Serializable{
    
        private static final long serialVersionUID = -2985676753883318447L;
        int age;
        String name;
    
    }
    

7 Properties

public static void main(String[] args) throws IOException {
    File file = new File("pro.properties");
    Properties pro = new Properties();
    pro.load(new InputStreamReader(new FileInputStream(file),"GBK"));
    String name = pro.getProperty("name");
    System.out.println(name);
    Set<String> strings = pro.stringPropertyNames();
    for (String s : strings) {
        System.out.println(s+"="+pro.getProperty(s));
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值