Java 输入输出流(二)

流就是内存与存储设备之间传输数据的通道

java response 输出流字符 java 输入输出流_序列化


请看看图象形理解

java response 输出流字符 java 输入输出流_字符流_02

流的分类

1.按流向分类

  • 输入流:存储设备的内容读入内存
  • 输出流:内存中的内容写入存储设备

java response 输出流字符 java 输入输出流_字符流_03

2.按单位来区分

  • 字节流: 以字节为单位,可以读写所有数据。
  • 字符流: 以字符为单位,只能读写文本数据。

3.按功能来区分

  • 节点流: 具有实际传输数据的读写功能。
  • 过滤流: 在节点流的基础上的增强功能。

文件输入输出流,请看Java 输入输出流(一)

字节缓存流

  • 缓冲流: BufferedInputStream/BufferedOutputStream
    作用
  • 提高IO效率,减少磁盘的访问次数
  • 数据存储在缓冲区中,flush是将缓存区的内容写入到文件中,也可以直接close.
package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {

        InputStream inputStream = new FileInputStream("E://test/1.txt");
        OutputStream outputStream = new FileOutputStream("E://test/2.txt");
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        int data = 0;
        while((data = bis.read())!=-1){
            System.out.println((char)data);
        }
        bis.close();
    }
}

上述代码,我们只关闭了缓冲流,为什么没有关闭字符输入流,其实在缓冲流关闭的时候,已经帮我们关闭了字符流,请看下面源码:

/**
     * Closes this input stream and releases any system resources
     * associated with the stream.
     * Once the stream has been closed, further read(), available(), reset(),
     * or skip() invocations will throw an IOException.
     * Closing a previously closed stream has no effect.
     *
     * @exception  IOException  if an I/O error occurs.
     */
    public void close() throws IOException {
        byte[] buffer;
        while ( (buffer = buf) != null) {
            if (bufUpdater.compareAndSet(this, buffer, null)) {
                InputStream input = in;
                in = null;
                if (input != null)
                    input.close();
                return;
            }
            // Else retry in case a new buf was CASed in fill()
        }
    }
package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {

        InputStream inputStream = new FileInputStream("E://test/1.txt");
        OutputStream outputStream = new FileOutputStream("E://test/2.txt");
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        BufferedOutputStream bos = new BufferedOutputStream(outputStream);
        int data = 0;
        while((data = bis.read())!=-1){
            bos.write(data);
            System.out.println((char)data);
        }
        bos.close();
        outputStream.close();
        bis.close();
    }
}

缓冲流

  • 对象流: ObjectOutputStream/ObjectInputStream
    作用
    1.增强了缓冲区功能
    2.增强了读写8种基本数据类型和字符串功能
    3.增强了读写对象的功能: a.readObject() 从流中读取一个对象 b.writeObject(Object obj) 向流中写入了一个对象。

使用流传输对象的过程称为序列化、反序列化。

序列化

package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {
        OutputStream outputStream = new FileOutputStream("E://test/2.obj");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        Student student = new Student("zhsnagsna ","12");
        objectOutputStream.writeObject(student);
        objectOutputStream.close();
    }
}

反序列化

package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {
        InputStream inputStream = new FileInputStream("E://test/2.obj");
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        Object o = objectInputStream.readObject();
        if(o instanceof Student){
            System.out.println(o);
        }
        objectInputStream.close();
    }
}

序列化与反序列化时的注意事项

  1. 序列化的类必须要实现Serializable接口
  2. 序列化类中对象属性要求实现Serializable接口:比如学校类中的一个学生属性
  3. 序列化版本ID,保证序列化的类和反序列化的类是同一个类
  4. 使用transient来修饰不能序列化的属性
  5. 静态属性也是不能序列化的
  6. 序列化多个对象的时候可以借助对象

字符编码

在讨论字符流时,我们先来看看字符编码

  • ISO-8859-1 收录了除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来 语对应的文字符号
  • UTF-8 针对Unicode码表的可变长度字符编码
  • GB2312 简体中文
  • GBK 简体中文、扩充
  • BIG5 繁体中文(台湾)

字符流

  • 字符流的父类(抽象类):
    1.Reader:字符输入流
    2.Writer:字符输出流
文件字符流
  • FileReader:
    1.public int read(char[] c) //从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1
  • FileWriter:
    1.public void write(String str);//一次写多个字符,将b数组中所有字符,写入输出流。
package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("E://test/1.txt");
        FileWriter fw = new FileWriter("E://test/2.txt");
        int data = 0;
        char [] c = new char[1024];
        while((data = fr.read(c))!=-1){
            fw.write(c);
            System.out.println(c);
        }
        fw.close();
        fr.close();
    }
}

转换流

桥转换流: InputStreamReader/OutputStreamWriter
  • 可将字节流转换为字符流。
  • 可设置字符的编码方式。
package com.sean.iotest;

import java.io.*;

public class Test <T> {
    public static void main(String[] args) throws Exception {
        FileInputStream fileInputStream = new FileInputStream("E:\\test\\1.txt");
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");

        FileOutputStream fileOutputStream = new FileOutputStream("E:\\test\\11.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"utf-8");

        int data = 0;
        while((data = inputStreamReader.read())!=-1){
            outputStreamWriter.write(data);
            System.out.println((char)data);
        }
        outputStreamWriter.close();
        inputStreamReader.close();
    }
}