JavaIO流之字符流和字节流

JavaIO流之字符流和字节流

字符流

  • 简单知识介绍:一个字母和数字是1个字节,一个汉字是3个字节,中文标点占3个字节,英文标点是1个字节。(本介绍是按照utf-8字符集所示)其他字符集所占字节不同。
Reader
BufferedReader
  1. 简单介绍
    • 读取文本的字符输入流,通过缓冲字符从而提供对字符、数组和行的高效读取。
    • Reader构成的对象是字符对象,每次的读取请求都会涉及到字节读取解码字符的过程,而BufferedReader类中有设计减少这样的解码次数的方法,进而提高转换效率。
  2. 常用方法
        public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\file\\test.txt"));
        char[] chars = new char[1024];
        bufferedReader.read(chars);
        System.out.println(chars);
        bufferedReader.close();
    }
    
  3. 源码解析
    1. 从构造方法中可看出BufferedReader有默认缓冲大小,默认为8192个字符
     private static int defaultCharBufferSize = 8192;
        public BufferedReader(Reader in) {
        this(in, defaultCharBufferSize);
    }
    
InputStreamReader
  1. 简单介绍
    • 该类读取字节,并用指定的字符集将其解码为字符,时从字节流到字符流的桥梁。
  2. 常用方法
    • 两种构造方法展示
    public static void main(String[] args) throws IOException {
        //InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("D:\\file\\test.txt"));
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("D:\\file\\test.txt"),"UTF-8");
        char[] chars = new char[1024];
        inputStreamReader.read(chars);
        System.out.println(chars);
        inputStreamReader.close();
    }
    
    • 控制台结果
    a
    b
    c
    d
    
StringReader
  1. 简单介绍
    • 将字符串转化成一个字符串流
  2. 常用方法
    public static void main(String[] args) {
        StringReader stringReader = new StringReader("哈哈哥");
        System.out.println(stringReader.toString());
        stringReader.close();
    }
PipedReader
  1. 简单介绍
    • 用于线程中通信的管道的输入流。
  2. 常用方法
    1. 创建发送者线程类
    public class Sender extends Thread{
        // 管道输出流对象。
        // 它和“管道输入流(PipedReader)”对象绑定,
        // 从而可以将数据发送给“管道输入流”的数据,然后用户可以从“管道输入流”读取数据。
        private PipedWriter out = new PipedWriter();
    
        // 获得“管道输出流”对象
        public PipedWriter getWriter() {
            return out;
        }
    
        @Override
        public void run() {
            writeShortMessage();
            //writeLongMessage();
        }
    
        // 向“管道输出流”中写入一则较简短的消息:"this is a short message"
        private void writeShortMessage() {
            String strInfo = "this is a short message";
            try {
                out.write(strInfo.toCharArray());
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        // 向“管道输出流”中写入一则较长的消息
        private void writeLongMessage() {
            StringBuilder sb = new StringBuilder();
            // 通过for循环写入1020个字符
            for (int i = 0; i < 102; i++)
                sb.append("0123456789");
            // 再写入26个字符。
            sb.append("abcdefghijklmnopqrstuvwxyz");
            // str的总长度是1020+26=1046个字符
            String str = sb.toString();
            try {
                // 将1046个字符写入到“管道输出流”中
                out.write(str);
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    2.创建接收者线程类
    public class Receiver extends Thread{
    // 管道输入流对象。
    // 它和“管道输出流(PipedWriter)”对象绑定,
    // 从而可以接收“管道输出流”的数据,再让用户读取。
    private PipedReader in = new PipedReader();
    
    // 获得“管道输入流对象”
    public PipedReader getReader() {
        return in;
    }
    
    @Override
    public void run() {
        readMessageOnce();
        //readMessageContinued() ;
    }
    
    // 从“管道输入流”中读取1次数据
    public void readMessageOnce() {
        // 虽然buf的大小是2048个字符,但最多只会从“管道输入流”中读取1024个字符。
        // 因为,“管道输入流”的缓冲区大小默认只有1024个字符。
        char[] buf = new char[2048];
        try {
            int len = in.read(buf);
            System.out.println(new String(buf, 0, len));
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 从“管道输入流”读取>1024个字符时,就停止读取
    public void readMessageContinued() {
        int total = 0;
        while (true) {
            char[] buf = new char[1024];
            try {
                int len = in.read(buf);
                total += len;
                System.out.println(new String(buf, 0, len));
                // 若读取的字符总数>1024,则退出循环。
                if (total > 1024){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }
    
    1. 测试类
    /**
    * 管道输入流和管道输出流的交互程序
    */
    public class PipeTest {
        public static void main(String[] args) {
            Sender t1 = new Sender();
            Receiver t2 = new Receiver();
            PipedWriter out = t1.getWriter();
            PipedReader in = t2.getReader();
            try {
                //管道连接。下面2句话的本质是一样。
                //out.connect(in);
            in.connect(out);
            /**
             * Thread类的START方法:
             * 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
             * 结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。
             * 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
             */
            t1.start();
            t2.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    }
    
  3. 源码分析
    • PipedWriter
    package java.io;
    
    public class PipedWriter extends Writer {
    
        // 与PipedWriter通信的PipedReader对象
        private PipedReader sink;
    
        // PipedWriter的关闭标记
        private boolean closed = false;
    
        // 构造函数,指定配对的PipedReader
        public PipedWriter(PipedReader snk)  throws IOException {
            connect(snk);
        }
    
        // 构造函数
        public PipedWriter() {
        }
    
        // 将“PipedWriter” 和 “PipedReader”连接。
        public synchronized void connect(PipedReader snk) throws IOException {
            if (snk == null) {
                throw new NullPointerException();
            } else if (sink != null || snk.connected) {
                throw new IOException("Already connected");
            } else if (snk.closedByReader || closed) {
                throw new IOException("Pipe closed");
            }
    
            sink = snk;
            snk.in = -1;
            snk.out = 0;
            // 设置“PipedReader”和“PipedWriter”为已连接状态
            // connected是PipedReader中定义的,用于表示“PipedReader和PipedWriter”是否已经连接
            snk.connected = true;
        }
    
        // 将一个字符c写入“PipedWriter”中。
        // 将c写入“PipedWriter”之后,它会将c传输给“PipedReader”
        public void write(int c)  throws IOException {
            if (sink == null) {
                throw new IOException("Pipe not connected");
            }
            sink.receive(c);
        }
    
        // 将字符数组b写入“PipedWriter”中。
        // 将数组b写入“PipedWriter”之后,它会将其传输给“PipedReader”
        public void write(char cbuf[], int off, int len) throws IOException {
            if (sink == null) {
                throw new IOException("Pipe not connected");
            } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {
                throw new IndexOutOfBoundsException();
            }
            sink.receive(cbuf, off, len);
        }
    
        // 清空“PipedWriter”。
        // 这里会调用“PipedReader”的notifyAll();
        // 目的是让“PipedReader”放弃对当前资源的占有,让其它的等待线程(等待读取PipedWriter的线程)读取“PipedWriter”的值。
        public synchronized void flush() throws IOException {
            if (sink != null) {
                if (sink.closedByReader || closed) {
                    throw new IOException("Pipe closed");
                }
                synchronized (sink) {
                    sink.notifyAll();
                }
            }
        }
    
        // 关闭“PipedWriter”。
        // 关闭之后,会调用receivedLast()通知“PipedReader”它已经关闭。
        public void close()  throws IOException {
            closed = true;
            if (sink != null) {
                sink.receivedLast();
            }
        }
    }
    
    • PipedReader
    package java.io;
    
    public class PipedReader extends Reader {
        // “PipedWriter”是否关闭的标记
        boolean closedByWriter = false;
        // “PipedReader”是否关闭的标记
        boolean closedByReader = false;
        // “PipedReader”与“PipedWriter”是否连接的标记
        // 它在PipedWriter的connect()连接函数中被设置为true
        boolean connected = false;
    
        Thread readSide;    // 读取“管道”数据的线程
        Thread writeSide;    // 向“管道”写入数据的线程
    
        // “管道”的默认大小
        private static final int DEFAULT_PIPE_SIZE = 1024;
    
        // 缓冲区
        char buffer[];
    
        //下一个写入字符的位置。in==out代表满,说明“写入的数据”全部被读取了。
        int in = -1;
        //下一个读取字符的位置。in==out代表满,说明“写入的数据”全部被读取了。
        int out = 0;
    
        // 构造函数:指定与“PipedReader”关联的“PipedWriter”
        public PipedReader(PipedWriter src) throws IOException {
            this(src, DEFAULT_PIPE_SIZE);
        }
    
        // 构造函数:指定与“PipedReader”关联的“PipedWriter”,以及“缓冲区大小”
        public PipedReader(PipedWriter src, int pipeSize) throws IOException {
            initPipe(pipeSize);
            connect(src);
        }
    
        // 构造函数:默认缓冲区大小是1024字符
        public PipedReader() {
            initPipe(DEFAULT_PIPE_SIZE);
        }
    
        // 构造函数:指定缓冲区大小是pipeSize
        public PipedReader(int pipeSize) {
            initPipe(pipeSize);
        }
    
        // 初始化“管道”:新建缓冲区大小
        private void initPipe(int pipeSize) {
            if (pipeSize <= 0) {
                throw new IllegalArgumentException("Pipe size <= 0");
            }
            buffer = new char[pipeSize];
        }
    
        // 将“PipedReader”和“PipedWriter”绑定。
        // 实际上,这里调用的是PipedWriter的connect()函数
        public void connect(PipedWriter src) throws IOException {
            src.connect(this);
        }
    
        // 接收int类型的数据b。
        // 它只会在PipedWriter的write(int b)中会被调用
        synchronized void receive(int c) throws IOException {
            // 检查管道状态
            if (!connected) {
                throw new IOException("Pipe not connected");
            } else if (closedByWriter || closedByReader) {
                throw new IOException("Pipe closed");
            } else if (readSide != null && !readSide.isAlive()) {
                throw new IOException("Read end dead");
            }
    
            // 获取“写入管道”的线程
            writeSide = Thread.currentThread();
            // 如果“管道中被读取的数据,等于写入管道的数据”时,
            // 则每隔1000ms检查“管道状态”,并唤醒管道操作:若有“读取管道数据线程被阻塞”,则唤醒该线程。
            while (in == out) {
                if ((readSide != null) && !readSide.isAlive()) {
                    throw new IOException("Pipe broken");
                }
                /* full: kick any waiting readers */
                notifyAll();
                try {
                    wait(1000);
                } catch (InterruptedException ex) {
                    throw new java.io.InterruptedIOException();
                }
            }
            if (in < 0) {
                in = 0;
                out = 0;
            }
            buffer[in++] = (char) c;
            if (in >= buffer.length) {
                in = 0;
            }
        }
    
        // 接收字符数组b。
        synchronized void receive(char c[], int off, int len)  throws IOException {
            while (--len >= 0) {
                receive(c[off++]);
            }
        }
    
        // 当PipedWriter被关闭时,被调用
        synchronized void receivedLast() {
            closedByWriter = true;
            notifyAll();
        }
    
        // 从管道(的缓冲)中读取一个字符,并将其转换成int类型
        public synchronized int read()  throws IOException {
            if (!connected) {
                throw new IOException("Pipe not connected");
            } else if (closedByReader) {
                throw new IOException("Pipe closed");
            } else if (writeSide != null && !writeSide.isAlive()
                    && !closedByWriter && (in < 0)) {
                throw new IOException("Write end dead");
            }
    
            readSide = Thread.currentThread();
            int trials = 2;
            while (in < 0) {
                if (closedByWriter) {
                    /* closed by writer, return EOF */
                    return -1;
                }
                if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
                    throw new IOException("Pipe broken");
                }
                /* might be a writer waiting */
                notifyAll();
                try {
                    wait(1000);
                } catch (InterruptedException ex) {
                    throw new java.io.InterruptedIOException();
                }
            }
            int ret = buffer[out++];
            if (out >= buffer.length) {
                out = 0;
            }
            if (in == out) {
                /* now empty */
                in = -1;
            }
            return ret;
        }
    
        // 从管道(的缓冲)中读取数据,并将其存入到数组b中
        public synchronized int read(char cbuf[], int off, int len)  throws IOException {
            if (!connected) {
                throw new IOException("Pipe not connected");
            } else if (closedByReader) {
                throw new IOException("Pipe closed");
            } else if (writeSide != null && !writeSide.isAlive()
                    && !closedByWriter && (in < 0)) {
                throw new IOException("Write end dead");
            }
    
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
    
            /* possibly wait on the first character */
            int c = read();
            if (c < 0) {
                return -1;
            }
            cbuf[off] =  (char)c;
            int rlen = 1;
            while ((in >= 0) && (--len > 0)) {
                cbuf[off + rlen] = buffer[out++];
                rlen++;
                if (out >= buffer.length) {
                    out = 0;
                }
                if (in == out) {
                    /* now empty */
                    in = -1;
                }
            }
            return rlen;
        }
    
        // 是否能从管道中读取下一个数据
        public synchronized boolean ready() throws IOException {
            if (!connected) {
                throw new IOException("Pipe not connected");
            } else if (closedByReader) {
                throw new IOException("Pipe closed");
            } else if (writeSide != null && !writeSide.isAlive()
                    && !closedByWriter && (in < 0)) {
                throw new IOException("Write end dead");
            }
            if (in < 0) {
                return false;
            } else {
                return true;
            }
        }
    
        // 关闭PipedReader
        public void close()  throws IOException {
            in = -1;
            closedByReader = true;
        }
    

}
```

FilterReader实现类之PushBackInputStream
  1. 简单介绍
    • PushBackInputStream有一个PushBack缓冲区,只不过PushbackReader所处理的是字符。从这个对象读出数据后,如果愿意的话,只要PushBack缓冲区没有满,就可以使用unread()将数据推回流的前端。
  2. 使用方法
        public static void main(String[] args) throws IOException {
        PushbackReader pr = null;
        try {
            //创建一个PushbackReader对象,指定推回缓冲区的长度为64
            pr = new PushbackReader(new FileReader("D:\\file\\test.txt"), 64);
            char[] buf = new char[65];
            //用以保存上次读取的字符串内容
            String lastContent = "";
            int hasRead = 0;
            //循环读取文件内容
            while ((hasRead = pr.read(buf)) > 0) {
                //将读取的内容转换成字符串
                String content = new String(buf, 0, hasRead);
                int targetIndex = 0;
                //将上次读取的字符串和本次读取的字符串拼起来,查看是否包含目标字符串
                //如果包含目标字符串
                if ((targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0) {
                    //将本次内容和上次内容一起推回缓冲区
                    pr.unread((lastContent + content).toCharArray());
                    //再次读取指定长度的内容(就是目标字符串之前的内容)
                    pr.read(buf, 0, targetIndex);
                    //打印读取的内容
                    System.out.print(new String(buf, 0, targetIndex));
                    int i = 0;
                    System.out.println(++i);
                    System.exit(0);
                } else {
                    //打印上次读取的内容
                    System.out.print(lastContent);
                    //将本次内容设为上次读取的内容
                    lastContent = content;
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try {
                if (pr != null)
                    pr.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
    
    • 控制台内容
    12312312312412341412312312312412341412312312312412341412312312312
    
    • 文本内容
    1231231231241234141231231231241234141231231231241234141231231231241234141231231231241234141231231231241234145
    
    • 代码解读:以65个字符为一组,进行文本内容读取拼接,直到最后不为一组时进行打印.
Writer
BufferedWriter
  1. 简单介绍
    • 字符缓冲输出流
  2. 常用方法
        public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\file\\test.txt"));
        bufferedWriter.write("hello-felix");
        // 相当于空格
        bufferedWriter.write(2);
        bufferedWriter.write("hello-fei");
        // 会在关闭之前进行 flush()刷新流,因为BufferedWriter是缓冲流会先把字符存放到缓冲中,进行刷新才会更新到目标文件中
        bufferedWriter.close();
    }
    
    • 文本
    hello-felix�hello-fei
    
OutputStreamWriter
  1. 简单介绍
    • 转换流,是字符流到字节流的桥梁,它使用指定的字符集将字节编码为字节.
  2. 常用方法
        public static void main(String[] args) throws IOException {
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("D:\\file\\test.txt"), "utf-8");
        // 把字符转化为字节存储在缓冲区中(编码)
        outputStreamWriter.write("felix");
        outputStreamWriter.write(2);
        outputStreamWriter.write("fei");
        // 把内存缓冲区中的字节书刷新到文件中(使用字节流写字节的过程)
        outputStreamWriter.flush();
        // 释放资源
        outputStreamWriter.close();
    }
    
    • 文本内容
    felix�fei
    
PrintWriter
  1. 简单介绍
    • 向文件中打印带格式的内容,针对于字符流.
  2. 常用方法
        public static void main(String[] args) throws IOException {
        PrintWriter printerWriter = new PrintWriter(new FileOutputStream("D:\\file\\test.txt"));
        printerWriter.println("felix"+"\n");
        printerWriter.println("fei"+"\n");
        printerWriter.close();
    }
    
  3. 文本内容
    felix
    
    fei
    
    
StringWriter
  1. 简单介绍
    • 将字符串写入缓冲流.
  2. 常用方法
        public static void main(String[] args) throws IOException {
        StringWriter sw = new StringWriter();
        //write(int c)写入单个字符
        sw.write('a');
        //write(char[w] cbuf, int off, int len)写入字符数组的某一部分,偏移量和写入长度
        char[] c = {'h', 'e', 'l', 'l', 'o'};
        sw.write(c, 1, 3);
        //write(String str)写入一个字符串
        sw.write("sunny day");
        //write(String str, int off, int len)写入字符串的某一部分,偏移量和写入长度
        String s = "hello world";
        sw.write(s, 0, 3);
        //append(char c)将指定字符添加到此 writer
        sw.append('g');
        //append(CharSequence csq)将指定的字符序列添加到此 writer。
        sw.append("apple");
        //append(CharSequence csq, int start, int end)将指定字符序列的子序列添加到此 writer。
        sw.append("tulun", 0, 3);
        /*返回当前值:返回类型不同,一个是StringBuffer类型,一个是String类型*/
        //getBuffer()返回该字符串缓冲区本身。
        System.out.println(sw.getBuffer());
        //toString()以字符串的形式返回该缓冲区的当前值。
        System.out.printf(sw.toString());
        //flush() 刷新该流的缓冲。
        sw.flush();
        //close() 关闭 StringWriter 无效。
        sw.close();
    }
    
    • 控制台结果
    aellsunny dayhelgappletul
    aellsunny dayhelgappletul
    
PipedWriter
  1. 简单介绍
    • 用于线程之间通过管道内容写入,和PipedReader配合使用.
  2. 常用方法
    • 可查看上面的PipedReader方法
FilterWriter
  1. 简单介绍
    • 字符流过滤,由于该类是个抽象类,暂时没有实际用处.
CharArrayWriter
  1. 简单介绍
    • 该类实现了一个可用作字符输出流的字符缓冲区,当数据写入流时,缓冲区自动增长
  2. 常用方法
        public static void main(String[] args) throws IOException {
        CharArrayWriter charArrayWriter = new CharArrayWriter();
        charArrayWriter.append("felix");
        charArrayWriter.write(2);
        charArrayWriter.write("fei");
        System.out.println(charArrayWriter.toCharArray());
        System.out.println(charArrayWriter.toString());
    }
    
    • 控制台结果
    felix�fei
    felix�fei
    

字节流

InputStream(接口)
FileInputStream
  1. 简单介绍
    • 文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等.
  2. 常用方法
        public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("D:\\file\\test.txt");
        byte[] bytes = new byte[1024];
        fileInputStream.read(bytes);
        System.out.println(new String(bytes));
        fileInputStream.close();
    }
    
    • 控制台结果
    123456  
    
    • 文本内容
    123456  
    
    • 注意:使用read(byte b[])方法时的数组长度至关重要,若长度小于流的字节长度,那么最后得出的内容会出现丢失。若大于流的字节长度,那么最后数组的内存就浪费了,那么就需要根据文件的字节长度来设置数组的长度
FilterInputStream
  1. 简单介绍
    • 用来“封装其它的输入流,并为它们提供额外的功能”。它的常用的子类有BufferedInputStream和DataInputStream。
ObjectInputStream
  1. 简单介绍
    • 反序列化流,将使用ObjectOutputStream序列化的原始数据恢复为对象,以流的方式读取对象.
  2. 常用方法
        public static void main(String[] args) throws IOException, ClassNotFoundException {
        
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\file\\test.txt"));
        // 需要User对象实现Serializable(序列化)接口
        User user1 = new User();
        user1.setName("felix");
        objectOutputStream.writeObject(user1);
        objectOutputStream.close();
        
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\file\\test.txt"));
        User user = (User)objectInputStream.readObject();
        System.out.println(user.getName());
        objectInputStream.close();
    }
    
    • 控制台结果
    felix
    
    • 文本内容
     �sr �com.example.demo.test.User)?��)�� �L �namet �Ljava/lang/String;xpt �felix
    
PipedInputStream
  1. 简单介绍
    • 管道输入流PipedInputStream与管道输出流PipedOutputStream实现了类似管道的功能,用于不同线程之间的相互通信.
SequenceInputStream
  1. 简单介绍
    • SequenceInputStream 表示其他输入流的逻辑串联(合并流)
  2. 常用方法
    
    

public static void main(String[] args) throws IOException {

//封装源文件
InputStream in1 = new FileInputStream("StringDemo.java") ;
InputStream in2 = new FileInputStream("SystemInDemo.java") ;
    
//创建合并流对象
SequenceInputStream sis = new SequenceInputStream(in1, in2) ;
//创建一个字节缓冲输入流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
    
//原来怎么读写,现在依然这样读写
byte[] bys = new byte[1024] ;
int len = 0 ;
while((len=sis.read(bys))!=-1) {
    bos.write(bys, 0, len);
    bos.flush(); //读图片文件的时候
}
    
//关闭资源
sis.close();
bos.close();
}
```
```

public static void main(String[] args) throws IOException {
//StringDemo.java+SystemInDemo.java+PrintWriterDemo.java--->Copy.java文件中

    //定义一个集合Vector
    Vector<InputStream> v  = new Vector<InputStream>() ;
    //使用InputStream封装文件
    InputStream s1 = new FileInputStream("StringDemo.java") ;
    InputStream s2 = new FileInputStream("SystemInDemo.java") ;
    InputStream s3 = new FileInputStream("PrintWriterDemo.java") ;
    
    //将流对象添加到集合中
    v.add(s1) ;
    v.add(s2) ;
    v.add(s3) ;
    
    //特有功能
    Enumeration<InputStream> en = v.elements() ;
    
    //创建合并输入流对象
    SequenceInputStream sis = new SequenceInputStream(en) ;
    //创建字节缓冲输出流对象
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java")) ;
    
    //一次读取一个字节数组
    byte[] bys = new byte[1024] ;
    int len = 0 ;
    while((len=sis.read(bys))!=-1) {
        bos.write(bys, 0, len);
        bos.flush();
    }
    
    //关闭资源
    bos.close();
    sis.close();
}
```
StringBufferInputStream
  1. 简单介绍
    • 创建字符串输入流以从指定字符串读取数据.
ByteArrayInputStream
  1. 简单介绍
    • 包含一个内部缓冲区,其中包含可以从流中读取的字节。 内部计数器跟踪由read方法提供的下一个字节。关闭一个ByteArrayInputStream没有任何效果。 该流中的方法可以在流关闭后调用,而不生成IOException 。意思就是说,比如文件流的处理对象的外存中的文件,而它的处理对象是内存中的缓冲区。它是从一个内存读到另一个内存方式。
OutputStream
  1. 简单介绍
    • 是一个抽象类,表示字节输出流的所有类的超类,将指定的字节信息写出到目的地.
FileOutputStream
  1. 简单介绍
    • FileOutPutStream是文件字节输出流,用于将字节流数据输入到指定的文件中.
  2. 常用方法
    public static void main(String[] args) throws IOException{
       // FileOutputStream fileOutputStream = new FileOutputStream("D:\\file\\test.txt",true);
       // FileOutputStream fileOutputStream = new FileOutputStream("D:\\file\\test3.txt",false);
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\file\\inner\\test3.txt",false);
        String content = "123";
        fileOutputStream.write(content.getBytes());
        fileOutputStream.close();
    }
    
    • 从以上方法可得知在使用FileOutputStream时如果文件不存在则会创建文件,如果文件夹不存在时则会抛出java.io.FileNotFoundException异常。
    • 该构造方法第二个参数true表示数据写入方式为从尾部进行追加,参数为false表示数据写入方式为从头进行覆盖。
ObjectOutputStream
  1. 简单介绍
    • 对象序列化流,把对象转成字节数据输出到文件中保存,对象的输出过程称为序列化,可实现对象的持久存储.
  2. 需要注意的点
    • 需要序列化的对象必须实现Serializable接口
    • 如果需要个别属性不被序列化,则该属性必须注明是瞬态的,使用transient关键字修饰
    • 被static关键字修饰的不能被序列化
    • 序列化一个对象时,要求它的属性要么是基本数据类型,如果是引用数据类型,这个引用数据类型必须实现Serializable接口。关于数据类型请查看 Java基本类型和引用类型
PipedOutputStream
  1. 简单介绍
    • 被称为管道输出流,和PipedInputStream配合使用,用于线程之间的通讯.
ByteArrayOutputStream
  1. 简单介绍
    • 此类实现一个字节输出流、其中数据被写入到字节数组中, 缓冲区在数据写入时会自动增长,关闭该流无效,关闭此流后调用方法不会有异常
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341