美文网首页
JAVA IO基础知识

JAVA IO基础知识

作者: engineer_tang | 来源:发表于2020-11-26 11:35 被阅读0次

    JAVA IO流采用的是装饰器设计模式,通过IO操作可以完成对特定设备进行数据的读写操作,深入理解IO的设计和使用,可以提供程序的性能和简便性,本篇文章将带大家系统地了解JAVA IO技术。

    1. 流的分类

    1.1 输入流输出流
    输入流:只能从中读取数据,
    输出流:只能向其写入数据。

    1.2 字节流和字符流
    字节流和字符流所操作的数据单元不同,字节流操作的数据单元是8位的字节,而字符流操作的数据单元是16位的字符。
    字节流的基类是InputStream和OutputStream。
    字符流的基类是Reader和Writer。
    1.3 节点流和处理流
    节点流(低级流):从/向一个特定的IO设备(如键盘、网络)读/写数据。
    处理流(高级流):对一个已存在的流进行连接或封装,通过封装后的流进行读/写操作。

    处理流的优点:

    1. 提高性能,增加缓冲的方式提高输入/输出的执行效率。
    2. 简化操作,通过提供一系列便捷的方法进行一次输入/输出大批量的内容。
    3. 消除不同节点流的实现差异。采用相同的代码、透明的方式来访问不同的输入/输出设备的数据流。

    2. 输入流

    抽象基类InputStream和Reader分别是用于处理字节和字符。
    Reader类的实现如下:

    
    public abstract class Reader implements Readable, Closeable {
    
        protected Object lock;
    
        protected Reader() {
            this.lock = this;
        }
    
        protected Reader(Object lock) {
            if (lock == null) {
                throw new NullPointerException();
            }
            this.lock = lock;
        }
    
        public int read(java.nio.CharBuffer target) throws IOException {
            int len = target.remaining();
            char[] cbuf = new char[len];
            int n = read(cbuf, 0, len);
            if (n > 0)
                target.put(cbuf, 0, n);
            return n;
        }
    
        public int read() throws IOException {
            char cb[] = new char[1];
            if (read(cb, 0, 1) == -1)
                return -1;
            else
                return cb[0];
        }
        
        public int read(char cbuf[]) throws IOException {
            return read(cbuf, 0, cbuf.length);
        }
    
        abstract public int read(char cbuf[], int off, int len) throws IOException;
    
        private static final int maxSkipBufferSize = 8192;
    
        private char skipBuffer[] = null;
    
        public long skip(long n) throws IOException {
            if (n < 0L)
                throw new IllegalArgumentException("skip value is negative");
            int nn = (int) Math.min(n, maxSkipBufferSize);
            synchronized (lock) {
                if ((skipBuffer == null) || (skipBuffer.length < nn))
                    skipBuffer = new char[nn];
                long r = n;
                while (r > 0) {
                    int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
                    if (nc == -1)
                        break;
                    r -= nc;
                }
                return n - r;
            }
        }
    
        public boolean ready() throws IOException {
            return false;
        }
        
        public boolean markSupported() {
            return false;
        }
    
        public void mark(int readAheadLimit) throws IOException {
            throw new IOException("mark() not supported");
        }
    
        public void reset() throws IOException {
            throw new IOException("reset() not supported");
        }
    
         abstract public void close() throws IOException;
    
    }
    
    

    InputStream类的实现如下:

    
    public abstract class InputStream implements Closeable {
    
        private static final int MAX_SKIP_BUFFER_SIZE = 2048;
       
        public abstract int read() throws IOException;
    
        public int read(byte b[]) throws IOException {
            return read(b, 0, b.length);
        }
        
        public int read(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if (off < 0 || len < 0 || len > b.length - off) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
    
            int c = read();
            if (c == -1) {
                return -1;
            }
            b[off] = (byte)c;
    
            int i = 1;
            try {
                for (; i < len ; i++) {
                    c = read();
                    if (c == -1) {
                        break;
                    }
                    b[off + i] = (byte)c;
                }
            } catch (IOException ee) {
            }
            return i;
        }
    
        public long skip(long n) throws IOException {
    
            long remaining = n;
            int nr;
    
            if (n <= 0) {
                return 0;
            }
    
            int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
            byte[] skipBuffer = new byte[size];
            while (remaining > 0) {
                nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
                if (nr < 0) {
                    break;
                }
                remaining -= nr;
            }
    
            return n - remaining;
        }
    
        public int available() throws IOException {
            return 0;
        }
    
        public void close() throws IOException {}
    
        public synchronized void mark(int readlimit) {}
    
        public synchronized void reset() throws IOException {
            throw new IOException("mark/reset not supported");
        }
    
        public boolean markSupported() {
            return false;
        }
    
    }
    
    

    InputStream和Reader类都有3个方法名相同的同名重载方法read,使用方法除了操作数据类型外,并无二致。
    下面分别对这两个抽象类的子类使用编写示例:
    通过FileInputStream读取文件并打印

    package com.maltose.test;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class FileInputStreamTest {
    
        public static void main(String[] args) throws IOException {
            try(FileInputStream fileInputStream = new FileInputStream("E:\\document\\news.txt")) {
                byte buffer[] = new byte[1024];
                int readIndex = -1;
                while((readIndex = fileInputStream.read(buffer)) != -1) {
                    System.out.print(new String(buffer, 0, readIndex));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    通过FileReader读取文件信息

    package com.maltose.test;
    
    import java.io.FileReader;
    import java.io.IOException;
    
    public class FileReaderTest {
    
        public static void main(String[] args) {
            try(FileReader fileReader = new FileReader("E:\\document\\news.txt")) {
                int readIndex = -1;
                char buffer[] = new char[100];
                while ((readIndex = fileReader.read(buffer)) != -1) {
                    System.out.print(new String(buffer, 0, readIndex));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    自动关闭资源使用try语句可以保证输入流一定会被关闭。

    3. 输出流

    抽象基类OutputStream和Writer分别用于处理字节和字符的输出。
    FileOutputStream示例:

    package com.maltose.test;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class FileOutputStreamTest {
    
        public static void main(String[] args) {
            try(FileInputStream fileInputStream = new FileInputStream("E:\\document\\news.txt");
                FileOutputStream fileOutputStream = new FileOutputStream("E:\\document\\news2.txt")) {
                byte buffer[] = new byte[1024];
                int readIndex = -1;
                while ((readIndex = fileInputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, readIndex);
                }
            } catch (IOException e) {
    
            }
        }
    }
    
    

    FileWriter示例:

    package com.maltose.test;
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class FileWriterTest {
    
        public static void main(String[] args) {
            try(FileWriter fileWriter = new FileWriter("E:\\document\\news2.txt")) {
                fileWriter.write("你好吗?伙计\r\n");
                fileWriter.write("我现在很好!!!\r\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    4. 处理流

    处理流是高级流,它的构造器的入参不是物理IO设备节点,而是已存在的流。
    处理流PrintWriter示例

    package com.maltose.test;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class FileWriterTest {
    
        public static void main(String[] args) {
            try(FileWriter fileWriter = new FileWriter("E:\\document\\news2.txt");
                PrintWriter printWriter = new PrintWriter(fileWriter)) {
                printWriter.println("你好吗?伙计");
                printWriter.println("我现在很好!!!");
                printWriter.println("我现在很好!!!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    处理流PrintStream的示例

    package com.maltose.test;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    
    public class FileOutputStreamTest {
    
        public static void main(String[] args) {
            try(FileOutputStream fileOutputStream = new FileOutputStream("E:\\document\\news3.txt");
                PrintStream ps = new PrintStream(fileOutputStream)) {
                ps.println("这是一个字符串,用来测试处理流的");
                ps.println("怎么样?感觉不错吧?");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    5. JAVA IO体系

    分类 字节输入流 字节输出流 字符输入流 字符输出流
    抽象基类 InputStream OutputStream Reader Writer
    访问文件 FileInputStream FileOutputStream FileReader FileWriter
    访问数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
    访问管道 PipedInputStream PipedOutputStream PipedReader PipedWriter
    访问字符串 StringReader StringWriter
    缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
    转换流 InputStreamReader OutputStreamWriter
    对象流 ObjectInputStream ObjectOutputStream 1
    打印流 PrintStream PrintWriter

    如果输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入/输出的内容是二进制内容,则应该考虑使用字节流。

    相关文章

      网友评论

          本文标题:JAVA IO基础知识

          本文链接:https://www.haomeiwen.com/subject/nkmoiktx.html