java · 2019-07-07 0

Java IO流使用总结

一、字节输入输出流、字符输入输出流

FileInputStream:文件字节输入流、FileOutputStream:文件字节输出流、FileReader:文本字符输入流、FileWriter:文件字符输出流。

读写非文本文件(图片、视频等),用字节输入输出流;读写文本文件,用字符输入输出流。如果使用字节流处理中文字符文件,输出到控制台可能会出现乱码,此时可以用转换流解决。

复制图片,从图片a.jpg读出字节放入字节数组中,再把字节数组写入图片b.jpg。

(FileOutputStream会立即writer写入磁盘;FileWriter有缓冲区,会先写入缓冲区)

    /**
     * 复制图片
     * 文件字节输入流FileInputStream、文件字节输出流FileOutputStream
     */
    public void testFileStream() throws IOException {
//      字节输入流
        FileInputStream fis = new FileInputStream("JavaBIO/a.jpg");
//      字节输出流
        FileOutputStream fos = new FileOutputStream("JavaBIO/b.jpg");

//      将字节放入byte数组内
        byte[] bs = new byte[5];
        int len;
//      调用read方法,返回读取的长度,如果到达文件末尾,返回-1
        while ((len = fis.read(bs)) != -1){
            fos.write(bs, 0, len);
        }

//       关闭流
        fos.close();
        fis.close();
    }

复制文本内容,从文本a.txt读出字符放入字符数组中,再把字符数组写入文本b.txt。

    /**
     * 复制文本文件
     * 文件字符输入流FileRead、文件字符输出流FileWriter
     */
    public void testFileRW() throws IOException, InterruptedException {
//        字符输入流
        FileReader fr = new FileReader("JavaBIO/a.txt");
//        字符输出流,第二个参数表示是否追加,默认false,即覆盖
        FileWriter fw = new FileWriter("JavaBIO/b.txt", false);

//      把字符放入char数组中
        char[] cs = new char[5];
        int len;
        while ((len = fr.read(cs)) != -1){
//            内容打印到控制台
//            System.out.println(cs);
//            内容写到b.txt
            fw.write(cs, 0, len);
        }

//      关闭流
        fw.close();
        fr.close();
    }

二、缓冲流

BufferedInputStream:字节输入缓冲流、BufferedOutputStream:字节输出缓冲流、BufferedRead:字符输入缓冲流、BufferedWriter:字符输出缓冲流。

FileInputStream每次会从磁盘读指定大小的数据,每调用一次read,就是读取一次磁盘。

(FileOutputStream会立即writer写入磁盘;FileWriter有缓冲区,会先写入缓冲区)

BufferedInputStream默认缓冲区大小为8192字节,一次会从文件读取8192个字节到缓冲区,其read(byte[] b)方法先查看缓冲区是否有数据,如果没有数据会从磁盘读取8192个字节到缓冲区,然后从缓冲区读取b.length字节到字符数组。

BufferedOutStream默认缓冲区大小也是8192个字节,把内容写到缓冲区中,当缓冲区写满,再把内容写到磁盘;也可以调用flush()方法,不等缓冲区写满,直接把缓冲区内容写到磁盘,并清空缓冲区。

BufferedWriter提供有readLine()方法,一次读取一行。

    /**
     * 复制图片
     * 文件字节输入流FileInputStream、文件字节输出流FileOutputStream
     * 缓冲输入流BufferedInputStream、缓冲输出流BufferedOutputStream
     */
    public void testBufferedStream() throws IOException {
//      字节输入流
        FileInputStream fis = new FileInputStream("JavaBIO/a.jpg");
//      字节输出流
        FileOutputStream fos = new FileOutputStream("JavaBIO/b.jpg");
//      缓冲输入流(处理流)
        BufferedInputStream bis = new BufferedInputStream(fis);
//      缓冲输出流(处理流)
        BufferedOutputStream bos = new BufferedOutputStream(fos);

//      方式一:将字节放入byte数组内
        byte[] bs = new byte[5];
        int len;
//      调用read方法,返回读取的长度,如果到达文件末尾,返回-1
//        看上去读了5个字节,实际第一次执行时,已经从文件读取了8192个字节到缓冲区,从缓冲区读5个字节
        while ((len = bis.read(bs)) != -1){
//          会先写到缓冲区,默认缓冲区8192字节,缓冲区满了,才会写到文件中
            bos.write(bs, 0, len);
        }

//       关闭处理流,处理流会关闭字节流
        bos.close();
        bis.close();
    }

三、转换流

InputStreamRead:字节输入流->字符输入流;OutputStreamWriter:字符输出流->字节输出流。

转换流作用在字节流上。如果使用字节流处理中文字符文件,输出到控制台可能会出现乱码,此时可以用转换流解决,把字节转换为字符。

    /**
     * InputStreamRead:字节输入流->字符输入流          相当于解码
     * OutputStreadWriter:字符输出流 -> 字节输出流    相当于编码
     */
    public void testStreamRW() throws IOException {
//        字节输入流
        FileInputStream fis = new FileInputStream("JavaBIO/a.txt");
//        字节输出流,第二个参数表示是否追加,默认false,即覆盖
        FileOutputStream fos = new FileOutputStream("JavaBIO/b.txt", false);

//        转换流,输入输出编码不一样,中文内容会出现乱码
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");

//      把字符放入char数组中
        char[] cs = new char[5];
        int len;
        while ((len = isr.read(cs)) != -1){
//            内容打印到控制台
//            System.out.println(cs);
//            内容写到b.txt
            osw.write(cs, 0, len);
        }

//      关闭流,关闭处理流时,处理流会关闭字节流
        osw.close();
        isr.close();
    }

四、标准输入、输出流

System.in 标准的输入流,默认从键盘输入;System.out 标准的输出流,默认从控制台输出。

    public void systenIO1() throws IOException {
        InputStream is = System.in;         //System.in标准的输入流
        PrintStream ps = System.out;        //System.out标准的输出流

        char c = (char)is.read();
        ps.print(c);

        ps.close();
        is.close();
    }

setIn()指定输入流,改变默认从键盘输入,此时指定文件,则从指定文件输入;setOut()指定输出流,改变默认从控制台输出,此时指定文件,输出到指定文件。

   public void systenIO2() throws IOException {
        System.setIn(new FileInputStream("JavaBIO/a.txt"));
        System.setOut(new PrintStream("JavaBIO/b.txt"));

        InputStream is = System.in;         //System.in标准的输入流
        PrintStream ps = System.out;        //System.out标准的输出流

        int d;
        System.out.println(is.read());
        while ((d = is.read()) != -1){
            ps.print((char)d);
        }

        ps.close();
        is.close();
    }

五、打印流

PrintStream 字节打印流;PrintWriter 字符打印流。打印到指定的文件。

    public void print() throws FileNotFoundException {
        PrintStream ps = new PrintStream("JavaBIO/b.txt");
        ps.println("abcd中国");
        ps.close();

        PrintWriter pw = new PrintWriter("JavaBIO/c.txt");
        pw.println("abcd中国");
        pw.close();
    }

六、数据流

DataInputStream:数据输入流;DataOutputStream:数据输出流。数据流方便操作基本类型和字符串。

读文件的数据类型(int、String)的顺序,与写入文件时的类型(int、String)的顺序要保持一致。

    public void testDataStream() throws IOException {
//        数据输出流
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("JavaBIO/b.txt"));
//       写一个数字
        dos.writeInt(11);
//        写一个字符串
        dos.writeUTF("abcd");
//        关闭数据输出流
        dos.close();

//        数据输入流
        DataInputStream dis = new DataInputStream(new FileInputStream("JavaBIO/b.txt"));
//        读一个数字
        int num = dis.readInt();
//        读一个字符串
        String str = dis.readUTF();
//        打印
        System.out.println(num);
        System.out.println(str);
//        关闭数据输入流
        dis.close();
    }

七、对象流

ObjectInputStream:对象输入流、ObjectOutputStream:对象输出流。

定义一个Person类,需要继承序列化接口。用ObjectOutputStream把对象存入b.txt文件中,因为存入的是对象,所以打开是乱码;用ObjectInputStream从文件中读取对象。

public class ObjectStreamTest {

    public void testObjectStream() throws IOException, ClassNotFoundException {
//        对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("JavaBIO/b.txt"));
        Person p1 = new Person(18,"zz");
//        写对象
        oos.writeObject(p1);
        oos.close();

//       对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("JavaBIO/b.txt"));
//        读对象
        Person p2 = (Person) ois.readObject();
        ois.close();
        System.out.println(p2.getAge() + " " + p2.getName());
    }
}

//实现序列化接口
class Person implements Serializable {

    private static final long serialVersionUID = 6495153350280013035L;

    private int age;

    private String name;

    public Person() {

    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

}

八、随机存取文件流

RandomAccessFile:随机存取文件流。既可以作为输入流,又可以作为输出流,作为输入流,不是对原有文件的覆盖,是对原有文件内容的覆盖,可以调用seek方法,指定指针的位置(开始覆盖内容的位置)。

    public void testRandomAccessFile() throws IOException {
//        第二个参数数mode:r、rw、rwd、rws
        RandomAccessFile raf1 = new RandomAccessFile("JAVABIO/a.txt", "r");
        RandomAccessFile raf2 = new RandomAccessFile("JAVABIO/b.txt", "rw");

//        指定指针的位置,从指定的位置开始覆盖内容
//        raf2.seek(3);

        byte[] buffer = new byte[1024];
        int len;
        while ((len = raf1.read(buffer)) != -1){
            raf2.write(buffer, 0, len);
        }

        raf2.close();
        raf1.close();

    }

九、字节数组流

ByteArrayOutputStream:字节数组流,相当于StringBuilder。

    public void testByteArrayOutputStreamT() throws IOException {
//      默认32字节的缓冲区
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bos.write("abcd".getBytes());
        System.out.println(bos.toString());
        bos.close();
    }

十、管道流

PipedInputStream 和 PipedOutputStream 设计用来解决跨线程的字节数据传输。它们总是成对出现的。

public void testPipeStream() throws IOException {
    // 创建 PipedInputStream 对象
    final PipedInputStream in = new PipedInputStream();
    final PipedOutputStream out = new PipedOutputStream();

    // 两个类进行连接
    in.connect(out);

    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
    writer.write("Hello");
    writer.close();

    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    String str = reader.readLine();
    reader.close();

    System.out.println(str);
}