【Java基础】常用IO流的基本用法演示(持续更新)

主宰稳场 提交于 2020-01-25 02:29:55

常用IO流

类型 说明
文件流 对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream
缓冲流 在读入或写出时,数据可以基于缓冲批量读写,以减少I/O的次数:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream
内存流 1.从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream
2.从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream
转换流 按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader,Writer的转换类):InputStreamReader、OutputStreamWriter
对象流 字节流与对象实例相互转换,实现对象的序列化 :ObjectInputStream、ObjectOutputStream
注意: 1.读取顺序和写入顺序一定要一致,不然会读取出错。 2.在对象属性前面加transient关键字,则该对象的属性不会被序列化
打印流 ​ 只有输出,没有输入,在整个IO包中,打印流是输出信息最方便的类,分为 PrintWriter(字符打印流)、PrintStream(字节打印流)
DataConversion数据流 按基本数据类型读/写,可以字节流与基本类型数据相互转换:DataInputStream、DataOutputStream
过滤流 在数据进行读或写时进行过滤:FilterReader、FilterWriter、FilterInputStream、FilterOutputStream
合并流 把多个输入流连接成一个输入流 :SequenceInputStream
操作ZIP包流 ZipInputStream可以读取zip格式的流,ZipOutputStream可以把多份数据写入zip包
操作JAR包流 JarInputStream/JarOutputStream,派生自ZipInputStream/ZipOutputStream,它增加的主要功能是直接读取jar文件里面的MANIFEST.MF文件。因为本质上jar包就是zip包,只是额外附加了一些固定的描述文件。
管道流 实现管道的输入和输出(进程间通信): PipedReader、PipedWriter、PipedInputStream、PipedOutputStream
Counting计数 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream
推回输入流 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream
接收和响应客户端请求流 servletinputstream:用来读取客户端的请求信息的输入流
servletoutputstream:可以将数据返回到客户端
随机读取写入流 RandomAccessFile 既可以读取文件内容,也可以向文件输出数据,RandomAccessFile 对象包含一个记录指针,标识当前读写处的位置,可以控制记录指针从IO任何位置读写文件
加密流 对流加密/解密
CipherOutputStream 由一个 OutputStream 和一个 Cipher 组成 ,write() 方法在将数据写出到基础 OutputStream 之前先对该数据进行处理(加密或解密) ,
同样CipherInputStream是由InputStream和一个Cipher组成,read()方法在读入时,对数据进行加解密操作.
数字签名流 DigestInputStream : 最大的特点是在读取的数据的时候已经调用MessageDigest实例的update方法,当数据从底层的数据流中读取之后就只可以直接调用MessageDigest实例的digest()方法了,从而完成对输入数据的摘要加密
DigestOutputStream :最大的特点是在向底层的输出流写入数据的时候已经调用MessageDigest实例的update方法,并作为MessageDigest的输入数据,之后就可以直接调用MessageDigest实例的digest()方法完成加密过程;同样的,是否对数据加密也是由该流的on(boolean b)方法进行控制的,如果设置成false,那么在写出数据的过程中便不会将数据传给update方法,那么此时它跟普通的输出流就没有任何区别了。

CipherInputStream和CipherOutputStream与DigestInputStream/DigestOutputStream/类似,只是后者更为彻底,它们不用在显示地调用传入的Cipher对象的update和doFinal方法,加密或解密过程在读写数据的同时已经隐式地完成了

FileInputStream——FileOutputStream

  • FileInputStream(文件字节输入流)——FileOutputStream(文件字节输出流),操作数据单元为 字节, 适用与读取/写入任何类型的文件
    /**
     * @param srcPath 源文件路径
     * @param destPath 拷贝文件路径
     * @param length 每次缓存大小
     */
    public static void copyFile(String srcPath, String destPath, Integer length) {
        File srcFile = new File(srcPath);// 源头
        File destFile = new File(destPath);//目的地

        if (srcFile.isDirectory() || destFile.isDirectory() || length == null) {// 参数校验
            return;
        }

        try (
                InputStream fis = new FileInputStream(srcFile);
                OutputStream fos = new FileOutputStream(destFile);
        ) {
            byte[] bytes = new byte[length];//缓冲容器
            int len = -1;//保存每次输入流读取的字节长度,与bytes长度有关

            while ((rslen= fis.read(bytes)) != -1) {
                System.out.println("剩余大小==>"+fis.available()+"kb" +"==>"+(fis.available()/1024/1024)+"M");
                fos.write(bytes,0,len);
            }
            fos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//将E盘下的ROOT.war 复制到D盘下,每次读写缓存大小为1024
//   copyFile("E:/ROOT.war", ""D:/ROOT.war"", 1024);

FileReader——FileWriter

  • FileReader(文件字符输入流)——FileWriter(文件字符输出流),操作数据单元为 字符, 适用于读取/写入文本类型的文件
  /**
     *
     * @param srcPath 源文件路径
     * @param destPath 拷贝文件路径
     * @param length 每次缓存大小
     */
    public static void copyFile(String srcPath, String destPath, Integer length) {
        File srcFile = new File(srcPath);// 源头
        File destFile = new File(destPath);//目的地

        if (srcFile.isDirectory() || destFile.isDirectory() || length == null) {// 参数校验
            return;
        }

        try (
                Reader reader = new FileReader(srcFile);
                Writer writer = new FileWriter(destFile);
        ) {
            char[] chars = new char[length];//缓冲容器
            
            int len = -1;//保存每次输入流读取的字节长度,与bytes长度有关

            while ((len = reader.read(chars)) != -1) {
                writer.write(chars,0,len);
            }
            writer.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//将E盘下的ROOT.war 复制到D盘下,每次读写缓存大小为1024
//   copyFile("E:/ROOT.txt", ""D:/ROOT.txt"", 1024);

BufferedInputStream——BufferedOutputStream

  • 在读入或写出时,数据可以基于缓冲批量读写,以减少I/O的次数, 操作单位为字节

  • 当创建这两个缓冲流的对象时时,会创建了内部缓冲数组,默认使用32字节大小的缓冲区.

  • 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区

  • 当写入数据时,首先写入缓冲区,当缓冲区满时,其中的数据写入所连接的输出流。使用方 法flush()可以强制将缓冲区的内容全部写入输出流

  • 关闭流的顺序和打开流的顺序相反.只要关闭高层流即可,关闭高层流其实关闭的底层节点流 • Flush的使用:手动将buffer中内容写入文件

 /**
     *
     * @param srcPath 源文件路径
     * @param destPath 拷贝文件路径
     * @param length 每次缓存大小
     */
    public static void copyFile(String srcPath, String destPath, Integer length) {
        File srcFile = new File(srcPath);// 源头
        File destFile = new File(destPath);//目的地

        if (srcFile.isDirectory() || destFile.isDirectory() || length == null) {// 参数校验
            return;
        }

        try (
                InputStream is = new BufferedInputStream(new FileInputStream(srcPath));
                OutputStream os = new BufferedOutputStream(new FileOutputStream(destPath, true));//追加写入
        ) {
            byte[] bytes = new byte[length];//缓冲容器

            int len = -1;//保存每次输入流读取的字节长度,与bytes长度有关

            while ((len = is.read(bytes)) != -1) {
                os.write(bytes,0,len);
            }
            os.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

BufferedReader——BufferedWriter

  • 在读入或写出时,数据可以基于缓冲批量读写,以减少I/O的次数, 操作单位为字符
  • BufferedReader
    readLine() 读取一个文本行的数据
  • BufferedWriter
    newLine(); 写入一个行分隔符
 /**
     *
     * @param srcPath 源文件路径
     * @param destPath 拷贝文件路径
     * @param length 每次缓存大小
     */
    public static void copyFile(String srcPath, String destPath, Integer length) {
        File srcFile = new File(srcPath);// 源头
        File destFile = new File(destPath);//目的地

        if (srcFile.isDirectory() || destFile.isDirectory() || length == null) {// 参数校验
            return;
        }

        try (
                BufferedReader is = new BufferedReader(new FileReader(srcPath));
                BufferedWriter os = new BufferedWriter(new FileWriter(destPath, true));//追加写入
        ) {
            
            //3、操作 (分段读取)
            String line = null;
            while ((line = is.readLine()) != null) {
                os.write(line);
            }
            os.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

ByteArrayInputStream——ByteArrayOutputStream

  • 从/向内存字节数组读写数据,操作单位为字节
/**
 * @Description TODO  1、 图片读取到字节数组   2、 字节数组写出到文件
 */
public class FileUtils {
    @Test
    public  void main() {
        //图片转成字节数组
        byte[] datas = fileToByteArray("a.jpg");
        System.out.println(datas.length);
        byteArrayToFile(datas, "a-byte.jpg");
    }

    /**
     * 1、图片读取到字节数组
     * 1)、读取图片并转换成字节数组
     * 2)、返回字节数组
     */
    private static void byteArrayToFile(byte[] datas, String src) {
        //1、创建源
        File srcFile = new File(src);

        //2、选择流
        try (
                InputStream bais = new ByteArrayInputStream(datas, 0, datas.length);
                OutputStream fos = new FileOutputStream(srcFile);
        ) {

            //3、分段读取
            byte[] bytes = new byte[1024];//缓冲容器
            int len = -1;//接收长度

            //4.写出到文件
            while ((len = bais.read(bytes,0,bytes.length)) != -1) {
                fos.write(bytes,0,len);
            }

            fos.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 2、字节数组写出到图片
     * 1)、读取字节数组到程序 ByteArrayInputStream
     * 2)、将读取到的字节数组写入输入流
     */
    private static byte[] fileToByteArray(String dest) {
        //1. 创建源
        File destFile = new File(dest);

        //2. 选择流
        try (
                InputStream fis = new FileInputStream(destFile);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ) {

            byte[] bytes = new byte[1024];//缓冲容器

            //3. 分段读取
            int len = -1;
            while ((len = fis.read(bytes, 0, bytes.length)) != -1) {
                baos.write(bytes, 0, len);
            }

            //4. 刷新缓冲
            baos.flush();

            //5. 字节数组输出流返回字节数组
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

CharArrayReader——CharArrayWriter

  • 从/向内存字符数组读写数据,操作单位为字符
/**
 * @Description TODO  1、 图片读取到字符数组   2、 字符数组写出到文件
 */
public class FileUtils {
    @Test
    public  void main() {
        //图片转成字节数组
        char[] datas = fileToByteArray("a.jpg");
        System.out.println(datas.length);
        byteArrayToFile(datas, "a-byte.jpg");
    }

    /**
     * 1、图片读取到字节数组
     * 1)、读取图片并转换成字节数组
     * 2)、返回字节数组
     */
    private static void byteArrayToFile(char [] datas, String src) {
        //1、创建源
        File srcFile = new File(src);

        //2、选择流
        try (
                Reader bais = new CharArrayReader(datas, 0, datas.length);
                Writer fos = new FileWriter(srcFile);
        ) {

            //3、分段读取
            char[] chars = new char[1024];//缓冲容器
            int len = -1;//接收长度

            //4.写出到文件
            while ((len = bais.read(chars,0,chars.length)) != -1) {
                fos.write(chars,0,len);
            }

            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 2、字节数组写出到图片
     * 1)、读取字节数组到程序 ByteArrayInputStream
     * 2)、将读取到的字节数组写入输入流
     */
    private static char[] fileToByteArray(String dest) {
        //1. 创建源
        File destFile = new File(dest);

        //2. 选择流
        try (
                Reader fis = new FileReader(destFile);
                CharArrayWriter baos = new CharArrayWriter();
        ) {

            char[] chars = new char[1024];//缓冲容器

            //3. 分段读取
            int len = -1;
            while ((len = fis.read(chars, 0, chars.length)) != -1) {
                baos.write(chars, 0, len);
            }

            //4. 刷新缓冲
            baos.flush();

            //5. 字节数组输出流返回字节数组
            return baos.toCharArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

StringReader——StringWriter

  • 用于操作字符流,相对其他字符流拥有了对String类型数据进行操作的能力。
/**
 * @Description TODO 专门用来读取文本文件
 */
public class StringStream {

    @Test
    public  void main() {
        // 获取文本文件的文本内容
        String datas =  readTextFileToString("test.txt");
        System.out.println(datas);
        // 将文本内容写入指定文件
        StringToTextFile(datas, "toTest.txt");
    }


    /**
     *将文本内容写入指定文件
     * @param datas 字符串
     * @param src 文件路径
     */
    private static void StringToTextFile(String datas, String src) {
        //1、创建源
        File srcFile = new File(src);

        //2、选择流
        try (
                StringReader sr = new StringReader(datas);
                Writer fw = new FileWriter(srcFile);
        ) {

            //3、分段读取
            char[]  chars = new char[20];//缓冲容器
            int len = -1;//接收长度

            //4.写出到文件
            while ((len = sr.read(chars,0,chars.length)) != -1) {
                fw.write(chars,0,len);
            }

            fw.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 读取文本文件并将该文本内容返回
     * @param dest 文件路径
     * @return
     */
    private static String readTextFileToString(String dest) {
        //1. 创建源
        File destFile = new File(dest);

        //2. 选择流
        try (
                Reader fr  = new FileReader(destFile);
                StringWriter sw = new StringWriter();
        ) {

            char[] bytes = new char[1024];//缓冲容器

            //3. 分段读取
            int len = -1;
            while ((len = fr.read(bytes, 0, bytes.length)) != -1) {
                sw.write(bytes, 0,len);
            }

            //4. 刷新缓冲
            sw.flush();

            //5. 字节数组输出流返回字节数组
            return sw.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

InputStreamReader——OutputStreamWriter

  • 按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader,Writer的转换类)
  • 用于将字节流转化成字符流,字符流与字节流之间的桥梁
  • InputStreamReader的作用是把InputStream转换成Reader
  • OutputStreamWriter的作用是把OutputStream转换成Writer
  • 存在将字节流转换成字符流的转换流,因为字符流操作文本更简单
  • 不存在把字符流转换成字节流的转换流,因为没有必要
	@Test
    /**
     * 字节流转换成循环读取键盘输入并输出到控制台
     */
    public void main1() {
        //操作System.in 和System.out
        try (
          BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
          BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        ) {
            //循环获取键盘的输入(exit退出),输出此内容
            String msg = "";
            while (!msg.equals("exit")) {
                msg = reader.readLine(); //循环读取
                writer.write(msg); //循环写出
                writer.newLine();
                writer.flush(); //强制刷新
            }
        } catch (IOException e) {
            System.out.println("操作异常");
        }
    }


    /**
     * 循环读取键盘输入并输出到指定文件中
     * @param args
     */
    public static void   main(String[] args) {
        //操作System.in 和System.out
        try (
       		//获取字节打印流并通过转换流转换为字符流然后通过字符包装流处理
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            //将字符包装流读取的字符写入到字符输出包装流(输出在当前路径的上一目录)
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("print.txt", true)));
        ) {

            //循环获取键盘的输入(exit退出),输出此内容
            String msg = "";
            while (!msg.equals("exit")) {
                msg = reader.readLine(); //循环读取
                System.out.println(msg);
                writer.write(msg+'\n');
                writer.flush(); //强制刷新
            }
        } catch (IOException e) {
            System.out.println("操作异常");
        }
    }

ObjectInputStream——ObjectOutputStream

  • 对象流输入流:,不仅可以读取/写入基本类型,也可以写入对象 ,读取的顺序与写出保持一致否则报错
@Data
@Getter
@Setter
@ToString
@AllArgsConstructor
class User implements Serializable {
    private static final long serialVersionUID = -2119298670197329888L;

    private Integer id;
    private String userName;
    private String passWord;
}

/**
 * 对象流: 不仅可以读取/写入基本类型,也可以写入对象 ,读取的顺序与写出保持一致否则报错java.io.EOFException
 * 1、写出后读取
 * 2、读取的顺序与写出保持一致
 * 3、不是所有的对象都可以序列化Serializable,必须要实现Serializable接口
 * <p>
 * ObjectOutputStream ObjectInputStream
 */
public class ObjectStream0 {

    @Test
    public void tesObjectStream() throws IOException, ClassNotFoundException {
        // 写出 -->序列化
        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("obj.ser")));
        // 操作数据类型 +数据
        oos.writeUTF("编码辛酸泪");
        oos.writeInt(18);
        oos.writeBoolean(false);
        oos.writeChar('a');

        //对象
        oos.writeObject("谁解其中味");
        oos.writeObject(new Date());
        Employee emp = new Employee("马云", 400);
        oos.writeObject(emp);
        oos.flush();
        oos.close();

        // 读取 -->反序列化
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("obj.ser")));
        //序列化写出和反序列化读取读取顺序必须一致
        String msg = ois.readUTF();
        int age = ois.readInt();
        boolean flag = ois.readBoolean();
        char ch = ois.readChar();
        System.out.println(flag);
        // 对象的数据还原
        Object str = ois.readObject();
        Object date = ois.readObject();
        Object employee = ois.readObject();

        if (str instanceof String) {
            String strObj = (String) str;
            System.out.println(strObj);
        }
        if (date instanceof Date) {
            Date dateObj = (Date) date;
            System.out.println(dateObj);
        }
        if (employee instanceof Employee) {
            Employee empObj = (Employee) employee;
            System.out.println(empObj.getName() + "-->" + empObj.getSalary());
        }
        ois.close();
    }


    /**
     * 序列化集合到文件中
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testSerializeObject() throws IOException, ClassNotFoundException {
        String path = "user.ser";
        List<User> userList = new ArrayList<>();

        for (int i = 0 ;i<100000 ;i++) {
            userList.add(new User(i,"admin"+i,"123"+i));
        }

        serializationObjectToFile(Arrays.asList(userList), path);

    }

    /**
     * 反序列化文件中集合对象
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testDeSerializeObject() throws IOException, ClassNotFoundException {
        String path = "user.ser";
        List<User> userList = deserializationObjectToFile(path);
        System.out.println(userList);

    }

    /**
     * 序列化对象到指定文件
     *
     * @param list 对象
     * @param path 文件路径
     */
    public static <T> void serializationObjectToFile(List<T> list, String path) {

        try (
                //1.选择流
                // 写出->序列化
                ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
        ) {
            oos.writeObject(list);
            oos.flush();
            System.out.println("序列化成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反序列指定文件中的集合
     *
     * @param path 文件路径
     */
    public <T> List<T> deserializationObjectToFile(String path) {
        try (
                //1.选择流
                // 读取->反序列化
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
        ) {
            System.out.println("反序列化成功");
            List<T> list = (List<T>) ois.readObject();
            return  list;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

PrintStream

  • 只有输出,没有输入,在整个IO包中,打印流是输出信息最方便的类,分为 PrintWriter(字符打印流)、PrintStream(字节打印流)
  • PrintStream提供了一系列的print()和println(),可以实现将基本数据类型格式化成字符串输出。
  • 对象类型将先调用toString(),然后输出该方法返回的字符串
  • System.out就是PrintStream的一个实例,代表显示器
  • System.err 也是PrintStream的一个实例,代表显示器
  • PrintStream的输出功能非常强大,通常需要输出文本内容,都可以将输出流包装成 PrintStream后进行输出
  • PrintStream的方法都不抛出IOException
 /**
     * 1. 字节输入流读取键盘输入字节
     * 2. 字节打印流输出字节流读取字节数组解码后的字符串到指定文件中
     * @param args success
     */
    public static void main(String[] args) {
        try (
                InputStream is = System.in;
                PrintStream out = new PrintStream(new File("printStream.txt"));
        ) {

            int len = -1;
            byte[] bytes = new byte[1024];
            while ((len = is.read(bytes)) != -1) {
                String msg = new String(bytes, "UTF-8");
                out.print(msg);
                msg = null;
//                out.write(bytes);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

PrintWriter

  • 只有输出,没有输入,在整个IO包中,打印流是输出信息最方便的类,分为 PrintWriter(字符打印流)、PrintStream(字节打印流)
  • PrintStream的对应字符流,功能相同,方法对应。
  • PrintWriter的方法也不抛出IOException
  • 复制文件时可以使用PrintWriter代替BufferedWriter完成,更简单)

    /**
     * 1. 字节输入流读取键盘输入字节
     * 2. 字符打印流输出字节流读取字节数组解码后的字符串到指定文件中
     * @param args
     */
    public static void main(String[] args) {
        try (
                InputStream reader = System.in;
                PrintWriter out = new PrintWriter(new FileWriter("printStream.txt"),true);
        ) {
            int len = -1;
            byte[] bytes = new byte[1024];
            while ((len = reader.read(bytes,0,bytes.length)) != -1) {
               out.println(new String(bytes,"UTF-8"));
            }

//           for (int i = 0;i<=100000;i++) {
//              out.println("Java从入门到放弃"+i);
//           }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

ZipInputStream——ZipOutputStream

  • ZipInputStream可以读取zip格式的流,ZipOutputStream可以把多份数据写入zip包
	@Test
    public void testReadZipToFile() {
        String srcPath = "test.zip";
        readZipToFile(srcPath,"zip-",1024);
    }

    @Test
    public void testWriteFileToZip() {
        String outPath = "test.zip";
        File[] files = {new File("a.jpg"), new File("baidu.html"), new File("test444.txt")};
        writeFileToZip(outPath, files);
    }

    /**
     * 读取压缩包文件 输出到指定位置
     * @param srcPath 压缩包位置
     * @param outPath 输出压缩包文件位置
     * @param length 每次读取大小
     */
    public static void readZipToFile(String srcPath, String outPath, int length) {
        FileOutputStream fos = null;
        try (
                ZipInputStream zip = new ZipInputStream(new FileInputStream(srcPath));
        ) {

            ZipEntry entry = null;
            while ((entry = zip.getNextEntry()) != null) {
                String name = entry.getName();//当前文件名字

                fos = new FileOutputStream(outPath + name);


                //非目录
                if (!entry.isDirectory()) {

                    int len = -1;
                    byte[] bytes = new byte[length];
                    while ((len = zip.read(bytes)) != -1) {
                        fos.write(bytes,0,len);
                    }
                    fos.flush();
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将多个文件推入压缩包中
     * 1.我们要先创建一个ZipOutputStream,通常是包装一个FileOutputStream,
     * 2.每写入一个文件前,先调用putNextEntry(),然后用write()写入byte[]数据
     * 3.写入完毕后调用closeEntry()结束这个文件的打包。
     * 4.上面的代码没有考虑文件的目录结构。如果要实现目录层次结构,new ZipEntry(name)传入的name要用相对路径
     *
     * @param outPath 输出文件路径
     * @param files   要压缩的多个文件
     */
    public static void writeFileToZip(String outPath, File[] files) {
        try (
                ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(outPath));
        ) {

            for (File file : files) {
                zip.putNextEntry(new ZipEntry(file.getName()));
                zip.write(getFileDataAsBytes(file, 1024));//根据文件名获取当前文件的所有字节数公共方法
                zip.closeEntry();
            }
            System.out.println("执行成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取制定文件对象字节数组
     *
     * @param srcPath 源文件路径
     * @return byte[]
     */
    public static byte[] getFileDataAsBytes(File srcPath, int length) {
        try (

                InputStream fis = new FileInputStream(srcPath);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ) {

            int len = -1;
            byte[] bytes = new byte[length];
            while ((len = fis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            bos.flush();

            return bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

SequenceInputStream

  • SequenceInputStream 可以将两个或多个其他 InputStream 按顺序合并为一个
 @Test
    public void testSequenceInputStream() {
        SequenceInputStream sis = null;

        try (
                //需要合并的输入流
                InputStream input1 = new FileInputStream("test222.txt");
                InputStream input2 = new FileInputStream("testRandom.txt");
                InputStream input3 = new FileInputStream("baidu.html");

                //用于输出合并的后输入流
                OutputStream output = new FileOutputStream("sequence.txt");
        ) {

            //保存到Vector中
            Vector<InputStream> streams = new Vector<>();
            streams.add(input1);
            streams.add(input2);
            streams.add(input3);


            // 利用 Vector 对象的 elements() 方法返回 enumeration 对象
            sis = new SequenceInputStream(streams.elements());

            int len = -1;
            byte[] bytes = new byte[1024];
            while ((len = sis.read(bytes)) != -1) {
                output.write(bytes, 0, len);
            }

            output.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                sis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!