Java IO流

节点流

FileInputStream

  • 文件字节输入流
  • 通常使用read(byte[] b)方法,自定义一个数组作为缓冲数组,一次性读取若干字节存入数组,并返回字节数
java.lang.Object
	java.io.InputStream
		java.io.FileInputStream
/**
 *  IO的父类子类非常多,所以要面向父类、接口编程,面向多态编程
 *  标准步骤:【分段读取存放在byte数组里面】【文件字节输入流】FileInputStream
 *
 *  先读取到字节数组中,返回值为读取的字节个数,  len = is.read(bytes)
 *  然后根据字节数组和读取的个数进行解码 new String(bytes,0,len)
 *
 *  1. 创建源
 *  2. 选择流
 *  3. 操作
 *  4. 释放资源
 * @author: Mango
 * @create: 2020-03-16 17:15
 **/

使用FileInputStream进行文件字节读取,并输出

public class demo03 {
    public static void main(String[] args) {
        File file = new File("IO/src/testFile/test.txt");
        
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            //缓存容器 字节数组
            byte[] bytes = new byte[1024];  //缓冲容器
            //接收长度 len 每次读取多少个,最后一次没有读取到内容,返回-1
            int len = -1;
            while ((len = is.read(bytes)) != -1) {
                //从第0个开始读取len个,len就是缓存数组每次从文件读取的字节个数
                String str = new String(bytes,0,len);
                System.out.print(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileOutputStream

  • 文件字节输出流
  • 将字节输出写入到文件
java.lang.Object
  	java.io.OutputStream
     	java.io.FileOutputStream
/**
 *  四个步骤:
 *  1. 创建源
 *  2. 选择流
 *  3. 操作
 *  4. 释放资源
 *
 *  flush()方法:在关闭流之前调用此方法
 * @author: Mango
 * @create: 2020-03-17 15:36
 **/
public class demo01 {
    public static void main(String[] args) {
        //创建源
        File dest = new File("IO/src/testFile/dest.txt");

        //选择流
        OutputStream os = null;
        try {
            //如果文件不存在则自动创建文件
            os = new FileOutputStream(dest,true);   //append:是否追加写入,默认重写

            String str = "like hhhh";
            byte[] data = str.getBytes();  //字符串 --> 字节数组(编码)
            //操作 将字节数组写出到文件
            os.write(data,0,data.length);
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileIO…Stream实现文件的拷贝

/**
 * @description:
 *  文件的赋值拷贝
 *  利用文件字节输入流和输出流拷贝文件
 *  源文件 --> 程序 --> 写出文件
 *  从源文件每次读取一部分数据存放在缓存数组中,然后将缓存数组一次次的写出到文件
 * @author: Mango
 * @create: 2020-03-17 16:11
 **/
public class demo02Copy {
    public static void main(String[] args) {
        //创建源
        File source = new File("IO/src/testFile/mango.jpg");
        File target = new File("IO/src/testFile/target.jpg");

        InputStream is = null;
        OutputStream os = null;

        try {
            //选择流
            is = new FileInputStream(source);
            os = new FileOutputStream(target);
            //操作(拷贝)
                //缓存数组data  读取长度len
            byte[] data = new  byte[1024];
            int len = -1;
                //读写,注意循环读取,一次读取可能读取不完
            while ((len=is.read(data)) != -1) {
                os.write(data,0,len);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源 先打开的后关闭
            if(os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

FileReader

  • 文件字符输入流
  • 用来读取字符文件的便捷类
java.lang.Object
	java.io.Reader
		java.io.InputStreamReader
			java.io.FileReader
/**
 * @description:
 *  【文件字符】输入流 【FileReader】【节点流】
 *  标准步骤:
 *  1. 创建源
 *  2. 选择流
 *  3. 操作
 *  4. 释放资源
 * @author: Mango
 * @create: 2020-03-18 15:24
 **/

使用FileReader将纯文本内容读取,每次读取若干字符存储到字符数组

public class demo01 {
    public static void main(String[] args) {
        //创建源
        File src = new File("IO/src/testFile/test.txt");
        Reader reader = null;

        try {
            //选择流
            reader = new FileReader(src);
            char[] chars = new char[10];
            int len = -1;
            //操作
            while ((len = reader.read(chars)) != -1) {
                //字符数组到字符串
                String str = new String(chars,0,len);
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileWriter

  • 文件字符输出流
  • 用来写入字符文件的便捷类
java.lang.Object
	java.io.Writer
		java.io.OutputStreamWriter
			java.io.FileWriter
/**
 * @description:
 * 【文件字符】输出流 【FileWriter】【节点流】
 * 标准步骤:
 * 1. 创建源
 * 2. 选择流
 * 3. 操作
 * 4. 释放资源
 *
 * @author: Mango
 * @create: 2020-03-18 16:19
 **/

使用FileWriter将字符写出到文件

public class demo01 {
    public static void main(String[] args) {
        //创建源
        File src = new File("IO/src/testFile/fileWriter.txt");
        Writer writer = null;

        try {
            //选择流
            writer = new FileWriter(src);
            writer.write("诶嘿嘿嘿");
            writer.write("嘿嘿嘿");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileRW…实现纯文本文件拷贝

/**
 * @description:
 * 使用文件字符输入输出流进行纯文本的拷贝
 * @author: Mango
 * @create: 2020-03-18 16:47
 **/
public class demo02Copy {
    public static void main(String[] args) {
        File src = new File("IO/src/testFile/src.txt");
        File dest = new File("IO/src/testFile/dest.txt");

        Reader reader = null;
        Writer writer = null;

        try {
            reader = new FileReader(src);
            writer = new FileWriter(dest);

            char[] chars = new char[1024];
            int len = -1;
            while ((len = reader.read(chars)) != -1) {
                writer.write(chars,0,len);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ByteArrayInputStream

  • 字节数组输入流
  • 不是与文件操作,所以不需要关闭
  • 将一个源头字节数组读取到自定义的缓冲字节数组中
java.lang.Object
  	java.io.InputStream
      	java.io.ByteArrayInputStream
/**
 * @description:
 * 字节数组输入流(内存流) 【ByteArrayInputStream】【节点流】
 * 程序 <-- ByteArrayInputStream <-- ByteArray    read
 * 程序 --> ByteArrayOutputStream --> ByteArray    write
 * 不是跟File文件打交道,所以是不需要关闭的
 *
 * 标准步骤:
 * 1. 创建源:源头是字节数组,不要太大
 * 2. 选择流
 * 3. 操作
 * 4. 释放资源:可以不用处理释放资源
 *
 * @author: Mango
 * @create: 2020-03-18 17:07
 **/

将一个源头字节数组读取到缓冲字节数组,并每次输出这个缓冲字节数组的内容

public class demo01 {
    public static void main(String[] args) {
        //创建源
        byte[] data = "嘿嘿嘿".getBytes();
        InputStream is = null;

        try {
            //选择流 将data字节数组读取到缓存数组中
            is = new ByteArrayInputStream(data);
            byte[] flush = new byte[1024];
            int len = -1;
            while((len = is.read(flush)) != -1) {
                String str = new String(flush,0,len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ByteArrayOutputStream

  • 字节数组输出流
  • 将一个个字节数组数据累计输出到内部维护的字节数组,最后可以通过toByteArray()方法获得这个完整的数组
  • 有特殊方法,不要发生多态
java.lang.Object
  	java.io.OutputStream
      	java.io.ByteArrayOutputStream
/**
 * @description:
 * 字节数组输出流(内存流) 【ByteArrayOutputStream】【节点流】
 * 程序 <-- ByteArrayInputStream <-- ByteArray    read
 * 程序 --> ByteArrayOutputStream --> ByteArray    write
 * 不是跟File文件打交道,所以是不需要关闭的
 * 标准步骤:
 * 1. 创建源:源头是字节数组,不要太大
 * 2. 选择流
 * 3. 操作 有特殊方法,不能发生多态,最后通过toByteArray()方法获得这个完整的数组
 * 4. 释放资源:可以不用处理释放资源
 *
 * @author: Mango
 * @create: 2020-03-19 10:50
 **/

通过FileInputStream将文件多次读取到缓存数组,再通过ByteArrayOutputStream将读取到的数据输出整合到自己内部维护的数组中,最后通过toByteArray()方法获得这个完整的数组

public class demo01 {
    public static void main(String[] args) {
        //创建源
        byte[] data = "嘿嘿嘿".getBytes();
        InputStream is = null;

        try {
            //选择流 将data字节数组读取到缓存数组中
            is = new ByteArrayInputStream(data);
            byte[] flush = new byte[1024];
            int len = -1;
            while((len = is.read(flush)) != -1) {
                String str = new String(flush,0,len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ByteArrayIO…Stream实现文件复制

  • 文件转字节数组,字节数组转文件
/**
 * @description:
 * 使用文件字节输入输出流和字节数组输入输出流进行文件的复制
 * 1. 文件每次读取一部分存放在缓存数组,再将缓存数组累计写出在ByteArrayOutputStream的内部缓存数组,
 *      最后得到一个完整的文件字节数组
 * 2. ByteArrayInputStream将完整的文件字节数组每次读取到缓存数组中,FileOutputStream将缓存数组
 *      的数据一次次写出到文件
 *
 *      当然,已经获取到文件的字节数组,可以直接使用FileOutputStream直接将字节数组写出到文件,
 *      不需要通过ByteArrayInputStream
 * @author: Mango
 * @create: 2020-03-19 11:00
public class demo03Copy {
    public static void main(String[] args) {
        byte[] fileByteArray = fileToByteArray("IO/src/testFile/mango.jpg");
        byteArrayToFile(fileByteArray,"IO/src/testFile/mango-copy.jpg");

    }

    /**
     * @Description 文件到字节数组
     **/
    public static byte[] fileToByteArray(String srcPath) {
        File src = new File(srcPath);
        FileInputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            is = new FileInputStream(src);
            baos = new ByteArrayOutputStream();
            byte[] flush = new byte[1024];
            int len = -1;
            while ((len = is.read(flush)) != -1) {
                baos.write(flush,0,len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //获取文件的完整字节数组返回
        return baos.toByteArray();
    }


    /**
     * @Description 字节数组到文件
     **/
    public static void byteArrayToFile(byte[] datas, String destPath) {
        File destFile = new File(destPath);

        InputStream bais = null;
        FileOutputStream os = null;

        try {
            bais = new ByteArrayInputStream(datas);
            os = new FileOutputStream(destFile);
            byte[] flush = new byte[1024*10];
            int len = -1;
            while ((len = bais.read(flush)) != -1) {
                os.write(flush,0,len);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

缓冲处理流

BufferedInputStream

BufferedOutputStream

  • BufferedInputStream、BufferedOutputStream
  • BufferedIO…Stream是装饰设计模式,以提高IO…Stream性能
  • BufferedIO…Stream()需要一个IO…Stream参数
java.lang.Object
	java.io.InputStream
      	java.io.FilterInputStream
          	java.io.BufferedInputStream
java.lang.Object
  	java.io.OutputStream
      	java.io.FilterOutputStream
          	java.io.BufferedOutputStream
/**
 * 【原理】
 *      原理是BufferedInputStream底层用了一个数组,默认大小是8192个字节,
 *      也就是BufferedInputStream一次性会从文件读取8192个字节,
 		然后返回给程序byte[b](自定义)个字节,
 *      程序在读取8192个字节之前不需要再次去访问和读取文件,直接从缓冲区读。
 *      直到缓冲区所有的都读取过,然后再去读取8192个字节,一直这样进行下去,直到任务结束。
 *      同样的BufferedOutputStream也是内置一个数组,默认大小也是8192字节。
 *      程序向流中写出字节时,不会直接写到文件,而是先写入到缓冲区,直到缓冲区写满,
 *      BufferedInputStream才会一次性把数据写入到文件中。
 * 【原理总结】
 *      通过实现原理,buffI和buffO都会先经过默认缓存数组,当缓存数组满了之后再进行下一次的读写,
 *      极大的减少了频繁访问硬盘的时间
 * 【实测总结】
 *      通过FileIO...Stream和BufferedIO...Stream进行问价的拷贝,
 		当自定义缓存数组为8kb(1024*8)时,FileIO...Stream略胜一点,当缓存数组过大或过小,
 		FileIO...Stream耗时明显高于BufferedIO...Stream,
 * FileIO...Stream耗时随缓存数组的大小改变,BufferedIO...Stream不随自定义缓存数组大小改变
 * @author: Mango
 * @create: 2020-03-21 17:02
 **/

文件的拷贝

public static void fileCopy(String src, String dest) {
        File srcFile = new File(src);
        File destFile = new File(dest);
        try (BufferedInputStream bis = new BufferedInputStream(new 				FileInputStream(srcFile));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));) {
            int len = -1;
            byte[] flush = new byte[1024*8];
            while ((len = bis.read(flush)) != -1) {
                bos.write(flush,0,len);
            }
            bos.flush();    //刷新缓冲输出流,在关闭前刷新一次即可,否则会影响性能
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReader

  • 字符输出缓冲流

  • 从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。

  • 装饰模式,有新增方法readLine(),不要发生多态

继承树
java.lang.Object
	java.io.Reader
		java.io.BufferedReader 

使用方法:将字符输入流FileReader作为BufferedReader的参数传入

从文件每次读取一行字符并输出

public class demo01BufferedReader {
    public static void main(String[] args) {

        File file = new File("IO/src/testFile/test.txt");
        try(BufferedReader br = new BufferedReader(new FileReader(file))) {

            String sb = new String();
            //注意,读取一行返回的是一个字符串,如果没有读到内容就返回null,所以跟null作比较判断
            while ((sb = br.readLine()) != null) {
                System.out.println(sb);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

###BufferedWriter

  • 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
  • 装饰模式,有新增方法newLine(),不要发生多态
java.lang.Object 
	java.io.Writer 
			java.io.BufferedWriter 

使用方法:将字符输入流FileWriter作为BufferedWriter的参数传入

将字符高效写入文件,并且添加换行

public class demo02BufferedWriter {
    public static void main(String[] args) {

        File file = new File("IO/src/testFile/out.txt");
        try(BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
            bw.append("芒果小洛");  //追加文字
            bw.newLine();          //添加一个换行符
            bw.append("特备厉害");
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedRW…实现纯文本的拷贝

public class demo03Copy {
    public static void main(String[] args) {
        copy("IO/src/testFile/test.txt","IO/src/testFile/dest.txt");
    }
    public static void copy(String fileSrc,String fileDest) {
        try(BufferedReader br = new BufferedReader(new FileReader(fileSrc));
            BufferedWriter bw = new BufferedWriter(new FileWriter(fileDest))) {
            String str = new String();
            //逐行读取
            while ((str = br.readLine()) != null) {
                //逐行写入,并追加换行
                bw.write(str);
                bw.newLine();
            }
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

转换流

InputStreamReader

OutputStreamWriter

  • 是字节流与字符流之间的桥梁
  • Reader解码:字节 --> 字符;Writer编码:字符 -->字节
  • 解码与编码可以指定字符集
java.lang.Object
  	java.io.Reader
      	java.io.InputStreamReader
java.lang.Object
  	java.io.Writer
      	java.io.OutputStreamWriter
InputStreamReader部分构造方法
InputStreamReader(InputStream in)创建一个使用默认字符集的
InputStreamReader(InputStream in, String charsetName)创建使用指定字符集的
InputStreamReader方法
intread()读取一个字符,返回此字符的,未读到返回-1
intread(char[] cbuf, int offset, int length)读取字节流中部分字符存储到char[],返回读取的字符数量

从以下几个例子深入理解

  • 从系统输入System.in读取字节流,并获取输入的前第2个字符开始连续读取10个字符,存储到字符数组中,再将字符数组转为字节流通过System.out系统输出
public class demo01TransCoding {
    public static void main(String[] args) {
        //通过System.in系统输入字节流,将其解码为字符流
        //将字符编码为字节流,通过系统输出
        //可以使用BufferdeReader和BufferedWriter提升性能
        try(InputStreamReader is = new InputStreamReader(System.in);
            OutputStreamWriter os = new OutputStreamWriter(System.out)) {

            char[] c = new char[10];
            int len = is.read(c,2,10);
            os.write(c,0,len);
            //此类内部存在缓冲区,如果需要多次输出需要手动刷新,此处仅输出了一次
            os.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 从系统输入System.in读取字节流,并获取输入的前第2个字符开始连续读取10个字符,存储到字符数组中,再将字符数组转为【特定编码GBK】的字节流通过System.out系统输出;发现当输入中文时,输出就乱码了,因为工程默认字符集为UTF-8,所以以GBK输出中文就会乱码
image-20200326161045838
public class demo02 {
    public static void main(String[] args) {
        //通过System.in系统输入字节流,将其解码为字符流,再通过BufferedReader字符缓冲流提升性能
        //将字符编码为字节流,通过系统输出,使用字符缓冲流提升性能
        try(InputStreamReader is = new InputStreamReader(System.in);
            OutputStreamWriter os = new OutputStreamWriter(System.out,"GBK")) {

            char[] c = new char[10];
            int len = is.read(c,0,10);
            os.write(c,0,len);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 通过URL返回此网站的InputStream作为字节输入流(网络流),通过InputStreamReader转换流转换为字符流,www.163.com的默认字符编码为GBK,所以要指定字符集,不然默认字符集UTF-8显示就会中文乱码
public class demo03 {
    public static void main(String[] args) {

        //通过URL返回此网站的InputStream输入流,通过InputStreamReader转换流转换为字符流
        //BufferedReader为提高性能
        try(BufferedReader is = new BufferedReader(new InputStreamReader(
                new URL("https://www.163.com").openStream(),"GBK"))) {
            String str = new String();
            int len = -1;
            is.readLine();
            while ((str = is.readLine()) != null) {
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 将baidu.com网页以UTF-8字符集从字节流转换为字符流,再通过UTF-8字符集将字符存为网页文件,当然,保存一个网页完全可以直接通过字节输入输出流对接完成,此处只是为了演示而演示
public class demo04 {
    public static void main(String[] args) {

        //通过URL返回此网站的InputStream输入流,通过InputStreamReader转换流转换为字符流
        //BufferedReader为提高性能
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(
                new URL("https://www.baidu.com").openStream(),"UTF-8"));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("IO/src/testFile/baidu.html"),"UTF-8"))) {

            String str = null;
            while ((str = reader.readLine()) != null) {
                writer.write(str);
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

数据流

DataInputStream

DataOutputStream

  • 数据输入输出流
  • 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
  • 应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
  • 输入和输出的顺序要保持一致
java.lang.Object
  	java.io.InputStream
      	java.io.FilterInputStream
          	java.io.DataInputStream
java.lang.Object
  	java.io.OutputStream
      	java.io.FilterOutputStream
          	java.io.DataOutputStream
DataInputStream构造方法
DataInputStream(InputStream in)使用指定的底层 InputStream 创建一个 DataInputStream

以下是DataInputStream的部分方法,包含了Java的基本数据类型和String,其他更多方法详见API,

DataOutputStream的方法与此是成对的,为write开头,如writeChar(),故不一一列举

部分方法,DataInputStream和DataOutputStream方法成对
booleanreadBoolean()读取一个输入字节,如果该字节不是零,则返回 true,如果是零,则返回 false
bytereadByte()读取返回一个输入字节
charreadChar()读取两个字节并返回一个char
doublereadDobule()读取八个输入字节并返回一个 double
floatreadFloat()读取四个输入字节并返回一个 float
StringreadUTF()读取一个使用UTF-8编码的字符串
  • 从下面的例子有助于理解

(当时疑惑字节数组的写入与写出不应该是使用字节数组IO流本身的方法来完成吗,为什么字节数组IO流作为参数,通过DataIO…Stream的方法就能对字节数组IO流读写数据呢?后来明白,DataIO…Stream是装饰流,它有更加强大的方法,通过它就可以对ByteArrayIO…Stream进行读写,就相对于FileReader套了BufferedReader一样,提升了性能,直接对BufferedReader操作即可)

将数据写出到ByteArrayOutputStream内部维护的字节数组然后再获取这个完整的字节数组,作为ByteArrayInputStream 的参数,DataInputStream读取并输出;当然为了提高性能,可以在字节数组IO流外面加一个BufferedIO…Stream来提高性能

public class demo01 {
    public static void main(String[] args) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //DataOutputStream为装饰流,构造需要一个ByteArrayOutputStream,
        //所以直接使用DataOutputStream的方法即可,就和FileWriter套一个BufferedWriter一样
        DataOutputStream dos = new DataOutputStream(bos);
        dos.writeUTF("like you");   //写出字符串
        dos.writeBoolean(true);     //写出boolean值
        dos.writeInt(18);           //写出int值

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        //DataInputStream为装饰流,构造需要一个ByteArrayInputStream,
        //所以直接使用DataInputStream的方法即可,就和FileWriter套一个BufferedWriter一样
        //注意读取的顺序要和写入的顺序一样
        DataInputStream dis = new DataInputStream(bis);
        String msg = dis.readUTF();
        boolean flag = dis.readBoolean();
        int age = dis.readInt();
        System.out.println(msg+flag+age);
    }
}

将数据写出到文件,再读取输出,并输出;当然,可以在FileIO…Stream外面套一个BufferedIO…Stream提升性能

public class demo02 {
    public static void main(String[] args) {
        File file = new File("IO/src/testFile/data.txt");
        
        try(DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
            DataInputStream dis = new DataInputStream(new FileInputStream(file));) {
            
            dos.writeUTF("like you");
            dos.writeBoolean(true);
            dos.writeChar('h');
            dos.flush();

            String msg = dis.readUTF();
            Boolean flag = dis.readBoolean();
            char c = dis.readChar();
            System.out.println(msg+" "+flag+" "+c);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

对象流

ObjectInputStream

ObjectOutputStream

  • 对象输入输出流
  • 对象输入输出流:此流不仅可以输出Java的8大基本数据类型和String,还可以将类的实例化对象转为输出流,以及在输入流中读取对象
  • ObjectInputStream中的writeObject()会将对象转为字节,称为序列化,并存储到文件、数据库、内存
  • ObjectOutputStream中的readObject()会将字节还原为对象,称为反序列化
  • 只有实现java.io.Serializable接口的类,其实例对象才能进行序列化和反序列化,此接口实际上只是一个空接口,是给虚拟机看的,作为可以序列化的标识
  • 使用transient关键字修饰的类的成员属性则不进行序列化
java.lang.Object 
	java.io.InputStream 
		java.io.ObjectInputStream 
java.lang.Object 
	java.io.OutputStream 
		java.io.ObjectOutputStream 

通过以下的例子有助于理解

  • 从文件写出读取;将基本数据类型和String进行序列化存储到文件,以及对实现Serializable接口的类的实例对象进行序列化存储到文件
public class demo01 {
    public static void main(String[] args) {
        File file = new File("IO/src/testFile/obj.obj");

        //为了提高性能,可以加入BufferedIO...Stream
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            /**
             * 写出
             */
            //基本操作,写出基本数据类型和String
            oos.writeUTF("like you");
            oos.writeBoolean(true);
            //写出对象
            student stu = new student("小明",18);
            oos.writeObject(stu);
            oos.flush();

            /**
             * 读取
             */
            //按照写出顺序进行读取
            String msg = ois.readUTF();
            boolean flag = ois.readBoolean();
            Object obj = ois.readObject();
            System.out.println(msg+"\t"+flag);

            //测试一个对象是否为一个类的实例
            if(obj instanceof student) {
                student stuObj = (student)obj;
                System.out.println(stuObj.getName()+"\t"+stuObj.getAge());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

//实现Serializable接口的类才能序列化,为减少代码,删去了set方法和无参构造
class student implements Serializable {
    //使用transient关键字的属性不进行序列化
    private transient String name;
    private int age;
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

从内存写出读取;将基本数据类型和String进行序列化存储到文件,以及对实现Serializable接口的类的实例对象进行序列化存储到文件

public class demo02 { 
    //为了减少代码量,这里异常就直接抛出
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        /**
         * 从内存写出读取
         */
        //为了提高性能,可以加入BufferedIO...Stream
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        //写出
        //基本操作,写出基本数据类型和String
        oos.writeUTF("like you");
        oos.writeBoolean(true);
        //写出对象
        teacher stu = new teacher("小明", 18);
        oos.writeObject(stu);
        oos.flush();

        //获取字节数组数据
        byte[] datas = bos.toByteArray();

        //读取
        //按照写出顺序进行读取
        //为了提高性能,可以加入BufferedIO...Stream
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(datas));
        String msg = ois.readUTF();
        boolean flag = ois.readBoolean();
        Object obj = ois.readObject();
        System.out.println(msg + "\t" + flag);

        //测试一个对象是否为一个类的实例
        if (obj instanceof teacher) {
            teacher stuObj = (teacher) obj;
            System.out.println(stuObj.getName() + "\t" + stuObj.getAge());
        }
    }
}

//实现Serializable接口的类才能序列化,为减少代码,删去了set方法和无参构造
class teacher implements Serializable {
    //使用transient关键字的属性不进行序列化
    private transient String name;
    private int age;
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值