Thinking in java自读笔记:常用输入输出流

这次总结以用法为主,涉及的深入原理暂不理会

1 继承于InputStream的常用输入流
(1). 文件输入流FileInputStream
(2). 管道输入流PipedInputStream
(3). 缓冲输入流BufferedInputStream
(4). 合并输入流SequenceInputStream
(5). 对象输入流ObjectInputStream
(6). 字节输入流ByteArrayInputStream
2.继承于OutputStream的常用输出流
(1). 文件输出流FileOutputStream
(2). 管道输出流PipedOutputStream
(3). 缓冲输出流BufferedOutputStream
(4). 对象输出流ObjectOutputStream
(5). 字节输出流ByteArrayOutputStream
3.继承于Reader的常用输入流
(1). FileReader
(2). BufferedReader
(3). PipedReader
(4). CharArrayReader
4.继承于Writer的常用输出流
(1). FileWriter;
(2). BufferedWriter;
(3). PipedWriter;
(4). CharArrayWriter;

一.FileInputStream和FileOutputStream的使用例子:

import java.io.*;

public class Test {
    public static void main(String[] args) {
        File file=new File("C:\\Users\\Mloong\\Desktop\\text_in_2.txt");
        byte[] buf=new byte[32];//读缓冲区
        try {
            FileInputStream in = new FileInputStream(file);//这个参数可以选择添文件路径
            FileOutputStream out=new FileOutputStream("C:\\Users\\Mloong\\Desktop\\text_out.txt");
            String str="";
            int ch;
            while ((ch=in.read(buf))!=-1)//ch为本次读取的字节数
            {
                out.write(buf,0,ch);
            }
            System.out.println(str);
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

二.PipedInputStream和PipedOutputStream的使用例子,管道输入输出流不能用于同一线程

import java.io.*;

public class Test {
    public static void main(String[] args) {
        PipedInputStream in=new PipedInputStream();
        PipedOutputStream out=new PipedOutputStream();
        In read=new In(in);
        Out write=new Out(out);
        Thread t1=new Thread(read);
        Thread t2=new Thread(write);
        try {
            in.connect(out);
            t1.start();
            t2.start();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
class In implements Runnable
{
    int num=0;
    PipedInputStream in;
    public In(PipedInputStream in)
    {
        this.in=in;
    }
    @Override
    public void run() {
        int length;
        try {
            while (true)
            {
                int thisNum=in.available();
                if(num!=0&&thisNum==0)break;
                num=thisNum;
                byte[] buf=new byte[10];
                length = in.read(buf);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
class Out implements Runnable
{
    PipedOutputStream out;
    String str="Hello PipedOutStream231321313";
    public Out(PipedOutputStream out)
    {
        this.out=out;
    }
    @Override
    public void run() {
        try{
            out.write(str.getBytes());
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

注意点:管道输入流和输出流共用一个缓冲区,大小为1024个字节,当缓冲区满,则输出流阻塞,当缓冲区空,则输入流阻塞,如果缓冲区为空且输出流线程关闭,输入流读取数据会报错!在PipedInputStream里有个available()方法可以获取当前可以读取的字节数,将上次可读取的字节数和这次可读取的字节数做对比,若上次不为空,这次为空则证明读取完,可以用这种方式来避免报错,大小为1024字节的数组是一个循环数组,用一个out和一个in来控制数据的读写,详细可了解这篇博客https://blog.csdn.net/zlp1992/article/details/50298195
三.BufferedInputStream和BufferedOutputStream的使用例子

public class Test {
    public static void main(String[] args) throws IOException{
        BufferedInputStream in=new BufferedInputStream(new FileInputStream("C:\\Users\\Mloong\\Desktop\\text_in_2.txt"));
        BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream("C:\\Users\\Mloong\\Desktop\\text_out.txt"));
        int ch;
        while ((ch=in.read())!=-1)
        {
            out.write(ch);
        }
        out.flush();
    }
}

注意点:缓冲流的构造函数需要一个相应的输入输出流对象,在不带缓冲的输入输出流中,每次对磁盘进行字节的读写操作相比内存要慢很多,在缓冲流中,每次读写时,先将数据存到缓冲区,缓冲区数据达到一定的量时,对数据进行一次性的读写操作,这样避免了单字节的读写,相对而言速度要快许多,因此在写操作完之后一定要使用flush()或者close()来强制写入缓冲区剩下的数据。
四.SequenceInputStream的使用例子

    public static void main(String[] args) throws IOException{
        Vector<FileInputStream> vec=new Vector<FileInputStream>();
        vec.addElement(new FileInputStream("C:\\Users\\Mloong\\Desktop\\text_in_1.txt"));
        vec.addElement(new FileInputStream("C:\\Users\\Mloong\\Desktop\\text_in_2.txt"));
        Enumeration<FileInputStream> it=vec.elements();
        SequenceInputStream in=new SequenceInputStream(it);
        FileOutputStream out=new FileOutputStream("C:\\Users\\Mloong\\Desktop\\text_out.txt");
        byte[] buf=new byte[1024];
        int ch;
        while ((ch=in.read(buf))!=-1)
        {
            out.write(buf,0,ch);
        }
    }

SequenceInputStream相当于把几个输入流捆绑在一起,从第一个输入流的数据开始读取,读到最后一个输入流结束为止。
五.ObjectInputStream和ObjectOutputStream使用例子

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

public class Test {
    public static void main(String[] args) throws IOException{
        ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("C:\\Users\\Mloong\\Desktop\\text_out.txt"));
        ArrayList<Student> ls=new ArrayList<Student>();
        Student st=new Student("123");
        Student st1=new Student("456");
        Student st2=new Student("789");
        ls.add(st);
        ls.add(st1);
        ls.add(st2);
        out.writeObject(ls);
        out.close();
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("C:\\Users\\Mloong\\Desktop\\text_out.txt"));
        try {
            ArrayList<Student> newLs=(ArrayList<Student>) in.readObject();
            for(int i=0;i<newLs.size();i++)
            {
                System.out.println(newLs.get(i));
            }
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}
class Student implements Serializable
{
    String name;
    public Student(String name)
    {
        this.name=name;
    }

    @Override
    public String toString() {
        return "Student[name="+name+"]";
    }
}

在这个例子中,我创建了一个ArrayList的列表存放Student对象,然后将ArrayList对象存入文件中,也可以存入单一的Student对象,不过在读取时我目前还没有找到如何避免读到文件尾继续读报错的问题,存放的对象必须实现Serializable接口。
六.ByteArrayInputStream和ByteArrayOutputStream使用例子

import java.io.*;

public class Test {
    public static void main(String[] args) throws IOException {
        String str="ABCDEFGHIL";
        ByteArrayInputStream in=new ByteArrayInputStream(str.getBytes());
        ByteArrayOutputStream out=new ByteArrayOutputStream();
        byte[] buf=new byte[6];
        int ch;
        System.out.println(in.available());
        while ((ch=in.read(buf))!=-1)
        {
            System.out.println(new String(buf,0,ch));
            out.write(buf);
        }
        System.out.println(out.toString());
    }
}

.ByteArrayInputStream内部有一个缓冲区,用来保存从字节数组读取的数据,只能用字节数组进行构造,所以内部缓冲区大小是固定的。ByteArrayOutputStream内部也有一个缓冲区,会随着写入的数据增多而增大。

字符流的使用和文件流相差不大,在java中,一个字符由2个字节组成,因此字符流可以说是一次性读取2个字节。

字节流可以转化为字符流:
InputStreamReader
OutputStreamWriter

关于字符流可参考这篇博客:https://blog.csdn.net/zq787312057/article/details/78594331?locationNum=9&fps=1

猜你喜欢

转载自blog.csdn.net/qq_27368993/article/details/82693787
今日推荐