Java IO学习

199 阅读7分钟

IO流分类

  • 按照流的流向:输入流和输出流
  • 按照操作单元来分:字节流和字符流
  • 按照流的角色来分:节点流和处理流
    • 节点流:程序用于直接操作目标设备(文件,内存)所对应的类称为节点流
    • 处理流:程序通过一个间接的流类去调用节点流类(使用装饰器模式,增强节点流类的功能)

Java IO流中的40多个类都是从4个抽象类基类中派生出来的

  • InputStream/Reader:所有类的输入类,前者是字节输入类,后者是字符输入类
  • OuntputStream/Writer:所有类的输出类,前者是字节输出类,后者是字符输出类

按照操作方式分类

按照操作对象分类

  • 转化控制:将字节流转化为字符流的桥梁,InputStreamReader:它使用指定的charset读取字节将其解码为字符,OutputStreamWriter:将字节输出流转化成字符输出流

  • System.in:归结为节点流,字节流,输入流

  • SequenceInputStream:字节序列输入流,可以用于将多个InputStream合并成一个InputStream,其中传入参数为一个枚举

    package io;
    
    
    import java.io.*;
    import java.util.Enumeration;
    import java.util.Vector;
    
    /**
     * @author cuckooYang
     * @create 2020-08-26 14:09
     * @description
     **/
    
    public class SequenceInputStreamDemo {
    
        private static Vector<InputStream> vector = new Vector<InputStream>();
    
    
    
        public static void main(String[] args) throws IOException {
            vector.add(new FileInputStream("D:/test/111.txt"));
            vector.add(new FileInputStream("D:/test/222.txt"));
            vector.add(new FileInputStream("D:/test/333.txt"));
            Enumeration<InputStream> enumeration =  vector.elements();
    //        test1(enumeration);
            test2(enumeration);
    
        }
        public static void test1(Enumeration<InputStream> enumeration) throws IOException {
            SequenceInputStream inputStream = new SequenceInputStream(enumeration);
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:/test/444.txt"));
            try {
    
                String len = "";
    
                while((len = bufferedReader.readLine()) != null){
                    System.out.println(len);
    
                    bufferedWriter.write(len);
    
                    bufferedWriter.flush();
    
                }
            }finally{
                inputStream.close();
                inputStreamReader.close();
                bufferedReader.close();
                bufferedWriter.close();
            }
        }
        public static void test2(Enumeration<InputStream> enumeration) throws IOException{
            SequenceInputStream se = new SequenceInputStream(enumeration);
            FileOutputStream os = new FileOutputStream("D:/test/444.txt");
            byte[] b = new byte[1024];
            int len =0;
            while((len= se.read(b)) != -1){
                os.write(b,0,len);
                os.write("\r\n".getBytes());
            }
            System.out.println("合并成功");
        }
    }
    
    
  • PipedInputStream/PipedOutputStream:管道流,作用是让多线程之间通过管道进行线程间的通讯

  • DataInputStream/DataOutputStream:数据输入输出流,允许应用程序以与机器无关方式从底层输入流中读写基本 Java 数据类型

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.InputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.FileNotFoundException;
    import java.lang.SecurityException;
    
    /**
     * DataInputStream 和 DataOutputStream测试程序
     *
     * @author skywang
     */
    public class DataInputStreamTest {
    
        private static final int LEN = 5;
    
        public static void main(String[] args) {
            // 测试DataOutputStream,将数据写入到输出流中。
            testDataOutputStream() ;
            // 测试DataInputStream,从上面的输出流结果中读取数据。
            testDataInputStream() ;
        }
    
        /**
         * DataOutputStream的API测试函数
         */
        private static void testDataOutputStream() {
    
            try {
                File file = new File("file.txt");
                DataOutputStream out =
                      new DataOutputStream(
                          new FileOutputStream(file));
    
                out.writeBoolean(true);
                out.writeByte((byte)0x41);
                out.writeChar((char)0x4243);
                out.writeShort((short)0x4445);
                out.writeInt(0x12345678);
                out.writeLong(0x0FEDCBA987654321L);
    
                out.writeUTF("abcdefghijklmnopqrstuvwxyz严12");
    
                out.close();
           } catch (FileNotFoundException e) {
               e.printStackTrace();
           } catch (SecurityException e) {
               e.printStackTrace();
           } catch (IOException e) {
               e.printStackTrace();
           }
        }
        /**
         * DataInputStream的API测试函数
         */
        private static void testDataInputStream() {
    
            try {
                File file = new File("file.txt");
                DataInputStream in =
                      new DataInputStream(
                          new FileInputStream(file));
    
                System.out.printf("byteToHexString(0x8F):0x%s\n", byteToHexString((byte)0x8F));
                System.out.printf("charToHexString(0x8FCF):0x%s\n", charToHexString((char)0x8FCF));
    
                System.out.printf("readBoolean():%s\n", in.readBoolean());
                System.out.printf("readByte():0x%s\n", byteToHexString(in.readByte()));
                System.out.printf("readChar():0x%s\n", charToHexString(in.readChar()));
                System.out.printf("readShort():0x%s\n", shortToHexString(in.readShort()));
                System.out.printf("readInt():0x%s\n", Integer.toHexString(in.readInt()));
                System.out.printf("readLong():0x%s\n", Long.toHexString(in.readLong()));
                System.out.printf("readUTF():%s\n", in.readUTF());
    
                in.close();
           } catch (FileNotFoundException e) {
               e.printStackTrace();
           } catch (SecurityException e) {
               e.printStackTrace();
           } catch (IOException e) {
               e.printStackTrace();
           }
        }
    
        // 打印byte对应的16进制的字符串
        private static String byteToHexString(byte val) {
            return Integer.toHexString(val & 0xff);
        }
    
        // 打印char对应的16进制的字符串
        private static String charToHexString(char val) {
            return Integer.toHexString(val);
        }
    
        // 打印short对应的16进制的字符串
        private static String shortToHexString(short val) {
            return Integer.toHexString(val & 0xffff);
        }
    }
    
  • ObjectInputStream 反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象,以流的方式读取对象。

  • PrintStream:是打印输出流,用来装饰其他输出流,它能为其他输出流添加功能,使它们能够方便地打印各种数据值表示形式

    /* 
     * 构造函数
     */
    // 将“输出流out”作为PrintStream的输出流,不会自动flush,并且采用默认字符集
    // 所谓“自动flush”,就是每次执行print(), println(), write()函数,都会调用flush()函数;
    // 而“不自动flush”,则需要我们手动调用flush()接口。
    PrintStream(OutputStream out)
    // 将“输出流out”作为PrintStream的输出流,自动flush,并且采用默认字符集。
    PrintStream(OutputStream out, boolean autoFlush)
    // 将“输出流out”作为PrintStream的输出流,自动flush,采用charsetName字符集。
    PrintStream(OutputStream out, boolean autoFlush, String charsetName)
    // 创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用默认字符集。
    PrintStream(File file)
    // 创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用charsetName字符集。
    PrintStream(File file, String charsetName)
    // 创建fileName对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用默认字符集。
    PrintStream(String fileName)
    // 创建fileName对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用charsetName字符集。
    PrintStream(String fileName, String charsetName)
    
    // 将“字符c”追加到“PrintStream输出流中”
    PrintStream     append(char c)
    // 将“字符序列从start(包括)到end(不包括)的全部字符”追加到“PrintStream输出流中”
    PrintStream     append(CharSequence charSequence, int start, int end)
    // 将“字符序列的全部字符”追加到“PrintStream输出流中”
    PrintStream     append(CharSequence charSequence)
    // flush“PrintStream输出流缓冲中的数据”,并检查错误
    boolean     checkError()
    // 关闭“PrintStream输出流”
    synchronized void     close()
    // flush“PrintStream输出流缓冲中的数据”。
    // 例如,PrintStream装饰的是FileOutputStream,则调用flush时会将数据写入到文件中
    synchronized void     flush()
    // 根据“Locale值(区域属性)”来格式化数据
    PrintStream     format(Locale l, String format, Object... args)
    // 根据“默认的Locale值(区域属性)”来格式化数据
    PrintStream     format(String format, Object... args)
    // 将“float数据f对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(float f)
    // 将“double数据d对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(double d)
    // 将“字符串数据str”写入到“PrintStream输出流”中,print实际调用的是write函数
    synchronized void     print(String str)
    // 将“对象o对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(Object o)
    // 将“字符c对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(char c)
    // 将“字符数组chars对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(char[] chars)
    // 将“long型数据l对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(long l)
    // 将“int数据i对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(int i)
    // 将“boolean数据b对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
    void     print(boolean b)
    // 将“数据args”根据“Locale值(区域属性)”按照format格式化,并写入到“PrintStream输出流”中
    PrintStream     printf(Locale l, String format, Object... args)
    // 将“数据args”根据“默认Locale值(区域属性)”按照format格式化,并写入到“PrintStream输出流”中
    PrintStream     printf(String format, Object... args)
    // 将“换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println()
    // 将“float数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(float f)
    // 将“int数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(int i)
    // 将“long数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(long l)
    // 将“对象o对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(Object o)
    // 将“字符数组chars对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(char[] chars)
    // 将“字符串str+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    synchronized void     println(String str)
    // 将“字符c对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(char c)
    // 将“double数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(double d)
    // 将“boolean数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
    void     println(boolean b)
    // 将数据oneByte写入到“PrintStream输出流”中。oneByte虽然是int类型,但实际只会写入一个字节
    synchronized void     write(int oneByte)
    // 将“buffer中从offset开始的length个字节”写入到“PrintStream输出流”中。
    void     write(byte[] buffer, int offset, int length)
    
  • PrintWriter是java中很常见的一个类,该类可用来创建一个文件并向文本文件写入数据

    public class FileTest {
        public static void main(String[] args) {
            PrintWriter pw = null;
            try {
                pw = new PrintWriter("f://aaa.txt");
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            pw.print("Hello World");
            pw.close();
        }
    }