Java.io

Java中可以从其中读入一个字节序列的对象称作为输入流。可以向其中写入一个字节序列的对象称为输出流。这些字节序列的来源可以是文件,也可以是网络连接和内存。输入/输出流家族家中类的数量超过了60个,下面列举了常用的类。
IO操作 - 图1

字节流

InputStream与OutputStream是java.io包提供的抽象类,定义了读写字节流的抽象方法,真正的读写方法由子类实现。读写方法read和write方法在执行时都将阻塞,直到字节确实被读入或者写出。这使得工作线程在等待流变得可用这段时间里,其他的线程有机会执行有用的工作。
在完成对输入、输出流的的读写后,应该调用close方法来关它,来释放操作系统掉操作系统十分有限的资源(在linux中可以使用ulimit来设置)。在关闭一个输出流的同时还会刷新用于该输出流的缓冲区,当然也可以使用flush来刷新它。
java.io.InputStream

  • abstract int read(), 从数据中读入一个字节,并返回该字节。碰到输入流的结尾时返回-1
  • int read(byte[] b) 读入数据到字节数组,并返回实际读入的字节数,碰到输入流的结尾时返回-1
  • int read(byte[] b, int off, int len), 读入数据到字节数组,并且指定偏移量和最大填充数,碰到输入流的结尾时返回-1,
  • long skip(long n ), 在输入流中跳过n个字节,并返回实际跳过的字节数
  • int available(), 返回在不阻塞的情况下可获取的字节数
  • void close() 关闭这个输入流

java.io.OutputStream

  • abstract void write(), 写出一个字节的数据
  • void write(byte[] b)
  • void write(byte[] b, int offm int len),将字节数组b中的第off+1个元素开始的len个数据。顺序的写入此输出流中
  • void close() 冲刷并关闭输出流
  • void flush() 冲刷输出流,也就是将所有缓冲的数据发送到目的地。

    文件读写

    java.io.FileInputStream

  • FileInputStream(String name) 使用文件地址来创建一个新的文件输入流

  • FileInputStream(FIle file) 使用file对象指定的路径名来创建一个新的文件输入流

java.io.FileOutputStream

  • FileOutputStream(String name)
  • FileOutputStream(String name, boolean append)
  • FileOutputStream(FIle file)
  • FileOutputStream(File file, boolean append) ```java package com.example.demo;

import java.io.*;

public class FileStreamTest {

  1. public static void processFile(String pathName) throws IOException {
  2. File file = new File(pathName);
  3. try (OutputStream output = new FileOutputStream(file)) {
  4. byte data[] = {1, 2, 3, 4, 5};
  5. output.write(data);
  6. }
  7. try (InputStream input = new FileInputStream(file)) {
  8. int n;
  9. while ((n = input.read()) != -1) {
  10. System.out.println(n);
  11. }
  12. }
  13. }
  14. public static void main(String[] args) {
  15. try {
  16. processFile("C:\\Users\\Desktop\\data.txt");
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }

}

<a name="qZg6O"></a>
### 字节数组读写
**java.io.ByteArrayInputStream**

- ByteArrayInputStream(bye[] buf)使用内存中的数组来创建一个输入流

**java.io.ByteArrayOutputStream**

- ByteArrayInputStream(bye[] buf)使用内存中的数组来创建一个输出流
<a name="O6D5I"></a>
### 对象的序列化
java.io包提供了将java对象序列化与反序列的接口。前提是该类必须实现了serializable接口,而且反序列化时JVM中存在该类的class对象。<br />[**serialVersionUID**](https://www.cnblogs.com/qq3111901846/p/7894532.html)<br />serialVersionUID用于校验序列化的版本一致性,如果不手动指定,据编译的Class自动生成一个。序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断根据该字段来判断版本是否正确
```java
import java.io.Serializable;

public class Student implements Serializable {
    private  int id;
    private  String name;
    private  String sex;

    private static final long serialVersionUID = 8735132092273200831L;

    // 加上 transient 关键字后Serializable就不会再本地存储该类型
      transient private String school;
}

java.io.ObjectInputStream

  • ObjectInputStream(InputStream in)
  • Object readObject() 从输入流中读入对象

java.io.ObjectOutputStream

  • ObjectOutputStream(OutputStream out)
  • void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。

    数据管道

    管道流一般用于多线程通信,相当于一个基于堆空间内存的消息队列,由锁机制来防止冲突的发生。建议不要尝试使用单个线程中的两个对象,因为可能使线程死锁。
    java.io.PipedInputStream
    java.io.PipedOutputStream

    组合输入输出流

    输入与输出流可以通过嵌套来实现多种功能,其采用了装饰器设计模式来实现。一般而言DataInputStream就只能从中读取数字,但是没有任何从文件中获取数据的方法,而FileInputStream只能读入文件类型,并从中读入字节或者字节数组;如果我们想从文件中读取数字可以执行一下方法:

    FileInputstream fin = new FileInputStream("number.data");
    DataInputstream din = new DataInputStream(fin);
    double x = din.readDouble();
    

    java.io.FilterInputStream/FilterOutputStream

  • protected FilterInputStream(InputStream in)

  • protected FilterOutputStream(OutputStream out)

    读写二进制数据

    文本数据可以方便测试和调试,因为他是人类可以阅读的;但是二进制可以更加高效地传递数据。DataInputStream与DataOutputStream中定义了多种接口用于写二进制数据,例如writeInt总是将一个整数写出为4字节的二进制数值,而不管它有多少位,这样的结果并非是可阅读的,但是对于给定类型的每个值,所产产生的空间都是都是相同的,大大的加快了解析的速度。

    DataInputStream in = new DataInputStream(new FileInputStream("test.data"))
    DataOutputStream out = new dataOutputStream(new FileoutStream("test.data"))
    

    java.io.DataInputStream

  • int readInt()

  • long readLong()
  • String readUTF() 读入修订过UTF-8格式字字符构成的字符串
  • … …

java.io.DataOutputStream

  • void writeByte(itn b)
  • void writeChar(int c)
  • void writeChars(String s) 写出字符串中所有的字符
  • String writeUTF() 写出修订过UTF-8格式字字符构成的字符串

    缓存流

    java.io.BufferedInputStream/BufferedOutputStream

  • BufferedInputStream(inputStream in) 创建一个带缓冲区的输入流。从流中读入字符时,每次都不会访问设备。当缓冲区为空时,会向缓冲区读入一个新的数据块。

  • BufferedOutputStream(InputStream in) 创建一个带缓冲区的输出流。带缓冲区的输出流在收集要写出的字符时,每次都不会访问设备。当缓冲区填满或者当流被冲刷时,数据被写出

    回退数据

    java.io.PushbackInputStream

  • PushbackInputStream(InputStream in)

  • PushbackInputStream(InputStream in, int size),构建一个可以预览一个字节或者具有执行大小的输入流
  • void unread(int b),回推一个字节,他可以在下次调用read时被再次获取

    打印数据

    public class PrintStream extends FilterOutputStream
      implements Appendable, Closeable
    {
      /**
       * The underlying output stream to be filtered.
       */
      protected OutputStream out;
      private final boolean autoFlush;
    
      /**
       * Track both the text- and character-output streams, so that their buffers
       * can be flushed without flushing the entire stream.
       */
      private BufferedWriter textOut;
      private OutputStreamWriter charOut;
    
      public void print(char c) {
          write(String.valueOf(c));
      }
    
      private void write(String s) {
          try {
              synchronized (this) {
                  ensureOpen();
                  textOut.write(s);
                  textOut.flushBuffer();
                  charOut.flushBuffer();
                  if (autoFlush && (s.indexOf('\n') >= 0))
                      out.flush();
              }
          }
          catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
          }
          catch (IOException x) {
              trouble = true;
          }
      }
    }
    

    java.io.PrintStream
    打印数据,是System.out的实现类

    其他

    java.io.SequenceInputStream

  • SequenceInputStream(InputStream s1, InputStream s2) 将两个输入流合并成一个输入流

java.io.StringBufferInputStream

  • StringBufferInputStream(String s) 将字符串作为输入流

字符流

在保存数据时,可以选择二进制格式或者将二进制数据进行编码的文本格式。Java内部使用是UTF-16作为为默认的编码。字符流中大部分类用法与字节流中的相同,这里不做详细介绍了。
java.io.Reader/Writer
Reader与Writer的基本方法与InputStream和OutputStream类似,区别是Reader与Writer读写的是Unicode码元(一个0-65536之间的则整数)。

字节转换为字符流

java.io.InputStreamReader

  • InputStreamReader(InputStream in, String charsetName), 将包含字节的输入流转换为可以产生Unicode码元的读入

java.io.OutputStreamWriter

  • OutputStreamReader(putStream out, String charsetName), 使用选定的字符编码方式,把Unicode码元输出流转换为字节流

    文件读写

    java.io.FileReader ```java import java.io.File; import java.io.FileReader; import java.io.IOException;

public class TestStream {

public static void main(String[] args) {
    File f = new File("/root/Test.java");
      try (FileReader fr = new FileReader(f)) {
          char[] all = new char[(int) f.length()];
        fr.read(all);
        for (char b : all) {
            System.out.println(b);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

      try (FileWriter fr = new FileWriter(f)) {
        String data="abcdefg1234567890";
        char[] cs = data.toCharArray();
        fr.write(cs);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

**java.io.FileWriter**
```java
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class TestStream {
    public static void main(String[] args) {
        File f =new File("/root/data.txt");
        try(FileWriter fr = new FileWriter(f);PrintWriter pw = new PrintWriter(fr);) {
                //强制把缓存中的数据写入硬盘,无论缓存是否已满
            pw.println("abc");
            pw.flush();           
            pw.println("123");
            pw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

文本输出

对于文本输出可以使用PrintWriter.这个类拥有以文本格式打印字符串和数字得我方法,它还有一个将PrintWriter连接到FileWriter的便捷方法:

PrintWriter out = new PrintWriter("employee.txt", "UTF-8")

java.io.PrintWriter

  • PrintWriter(Writer out)
  • PrintWriter(OutputStream out)
  • PrintWriter(String filename, String encoding)
  • PrintWriter(File file, String encoding)

创建一个使用给定编码方式向给定文件写出的新PrintWriter

  • void print(Object obj)
  • void print(String s)
  • boolean checkError() 如果格式化或者输出产生错误,将返回true

    文本输入

    java.util.Scanner

  • Scanner提供了多种凡是读入文本,不论是字节流还是字符流

文件读入

// 直接将文本读入到字符串中
String content = new String(Files.readAllBytes(path), charset);
// 将文本按行读入到List中
List<String> lines = Files.readAlllines(path, charset);
// 将文本读入到Stream中
try(Stream<String> lines  = Files.lines(path, charset))
{
   . . . 
}

Java.nio

Java NIO全程 java non-blocking IO,是指JDK提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NIO,是同步非阻塞的。NIO相比较于BIO有以下区别:

  • BIO基于字节流和字符流进行操作,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
  • BIO是阻塞的,NIO是非阻塞的,Java NIO的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其它的事情。非阻塞也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
  • NIO使用了多路复用技术,Selector(选择器)用于监听多个通道的时间(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道。

NIO相关类都被放在java.nio包及子包下,并且对原java.io包中的很多类进行改写。NIO有三大核心部分:Channel(通道),Buffer(缓冲区),Selector(选择器)。

                                          ![](https://cdn.nlark.com/yuque/0/2020/jpeg/217875/1602213206511-cfab6e26-705d-45d6-9227-c3d94106d7fe.jpeg#crop=0&crop=0&crop=1&crop=1&height=304&id=yTMFp&originHeight=570&originWidth=516&originalType=binary&ratio=1&rotation=0&showTitle=false&size=0&status=done&style=none&title=&width=275)

Selector

Buffer

Buffer类是一个抽象类,是一个由相同类型的数值构成的数组。包括ByteBuffer,CharBuffer等,每一个缓冲区都具有:

  • capacity 一个容量,也就是数组的大小,不能够被改变
  • position 一个读写位置,下一个值将在此处进行读写
  • limit 一个界限,超过它进行读写时没有意义的
  • mark一个可选的标记,用于重复读入或者写出操作

                         ![image.png](https://cdn.nlark.com/yuque/0/2020/png/217875/1583674395894-1df90235-d867-4108-8b5f-ef4719e3b2b8.png#crop=0&crop=0&crop=1&crop=1&height=207&id=ocR7w&name=image.png&originHeight=414&originWidth=1015&originalType=binary&ratio=1&rotation=0&showTitle=false&size=305172&status=done&style=none&title=&width=507.5)<br />**java.nio.ByteBuffer**
    
  • byte get()从当前位置获得一个字节,并将当前位置移动到下一个字节

  • ByteBuffer put(byte b) 向当前位置推入一个字节,并将当前位置移动到下一个字节。返回对这个缓冲区的引用

    Channel

    BIO中的stream是单向的,例如FileInputStream对象只能进行读取数据的操作,而NIO中的通道(Channel)是双向的,可以读操作,也可以写操作常见的Channel类有:FileChannel、DatagramChannel、ServerSocketChannel和SocketChannel。FileChannel用于文件的数据读写,DatagramChannel用于UDP的数据读写,ServerSocketChannel和SocketChannel用于TCP的数据读写

    FileChannel

    FileChannel是Java.nio提供用于处理文件的类,是一个文件读写、映射和操作的通道,使用它使我们可以访问内存映射,文件加锁以及文件之间数据快速传递等操作系统特性。同时它在并发环境下是线程安全的。
    在使用FileChannel时不能直接操作该文件,而是要通过NIO提供的Buffer类。
    java.nio.channels.FileChannel

  • static FileChannel open(Path path, OpenOption … opentions) 打开指定路径的文件通道,默认用于读入

    • options StandardOpenOption 枚举类中WRITE, APPEND, TRUNCATE_EXISTING CREATE
  • MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) 将文件的一个区域映射到内存中。
    • mode, FileChannel.MapMode类中的常量READ_ONLY,READ_WRITE或者PRIVATE之一
    • position 映射区域的起始位置
    • size 映射区域的大小
  • int read(ByteBuffer dst), 读入数据到指定Buffer中
  • int write(ByteBuffer dst), 将指定Buffer中的数据写出到FileChannel中 ```java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption;

/**

  • 测试JAVA NIO方式读取文件,写出内容到文件 / public class NIOTest {
public static void main(String[] args) {
    readNIO();
}
    /**
     * 最终确认,是因为UTF-8编码的时候,是变长的(可能1-4个字节),所以在
     * ByteBuffer bf = ByteBuffer.allocate(capacity);
     * byte[] bytes = bf.array();
     * 的时候,会出现数字英文和中文边界截断了的问题,所以导致出现测���java 文件操作这样的乱码。
     * 解决方案1:对这类文件不进行截断输出,整个输出
     * 解决方案2:截断输出的时候,判断编码边界。进行减长度操作,避免截断了中文。
     */
 public static void readNIO() {
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(new File("D:\\add0.txt"));
            FileChannel channel = fin.getChannel();

            int capacity = 1024;// 字节
            ByteBuffer bf = ByteBuffer.allocate(capacity);
            System.out.println("限制是:" + bf.limit() + ",容量是:" + bf.capacity() + " ,位置是:" + bf.position());
            int length = -1;

            while ((length = channel.read(bf)) != -1) {

                /*
                 * 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储
                 */
                bf.clear();
                byte[] bytes = bf.array();
                //System.out.println("start..............");
                String str = new String(bytes, 0, length,"UTF-8");
                System.out.println(str);
                //System.out.write(bytes, 0, length);

                //System.out.println("end................");

               System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity() + "位置是:" + bf.position());

            }
            //System.out.println(str);
            channel.close();

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

}

<a name="7OLe7"></a>
#### 内存映射

- MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) 将文件的一个区域映射到内存中。
   - mode, FileChannel.MapMode 类中的常量READ_ONLY,READ_WRITE或者PRIVATE之一
   - position 映射区域的起始位置
   - size 映射区域的大
```java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class NIOTest {

    public static void main(String[] args) {
        mmapTest();
    }

   /**
    * 使用直接缓冲区完成文件的复制(内存映射文件)
    * 耗费时间:142
    */
   private static void mmapTest() throws IOException {
       long startTime = System.currentTimeMillis();

       FileChannel inChannel = FileChannel.open(Paths.get("E:\\1.txt"), StandardOpenOption.READ);
       FileChannel outChennel = FileChannel.open(Paths.get("E:\\2.txt"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);

       //内存映射文件(什么模式 从哪开始 到哪结束)
       MappedByteBuffer inMappeBuf = inChannel.map(FileChannel.MapMode.READ_ONLY,0,inChannel.size());
       MappedByteBuffer outMappeBuf =  outChennel.map(FileChannel.MapMode.READ_WRITE,0,inChannel.size());

       //直接都缓冲区进行数据的读写操作
       byte[] dst = new byte[inMappeBuf.limit()];
       inMappeBuf.get(dst);
       outMappeBuf.put(dst);

       inChannel.close();
       outChennel.close();
       long end = System.currentTimeMillis();
       System.out.println("nioCopyTest2耗费时间:"+(end-startTime));
   }

}

文件锁定

java.io.channels.FileChannel

  • FileLock lock()

文件复制

使用FileChannel进行文件复制默认使用sendfile系统调用,如果系统内核不支持 Sendfile,则以 mmap 的零拷贝方式进行内存映射,这种情况下目的通道必须是 FileChannelImpl 或者 SelChImpl 类型。如果以上两步都失败了,基于传统的 I/O 方式完成读写。
java.io.channels.FileChannel

  • transferFrom
  • transferTo ```java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption;

public class NIOTest {

public static void main(String[] args) {
    readNIO();
}


/**
 *
 * 零拷贝模式
 *
 */

private static void nioCopyTest2() throws IOException { long startTime = System.currentTimeMillis();

   FileChannel inChannel = FileChannel.open(Paths.get("E:\\ 1.avi"), StandardOpenOption.READ);

   FileChannel outChennel = FileChannel.open(Paths.get("E:\\ 13.avi"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);

   outChennel.transferFrom(inChannel,0,inChannel.size());

   long end = System.currentTimeMillis();
   System.out.println("nioCopyTest3耗费时间:"+(end-startTime));

}

/**

*  非直接缓冲区 文件的复制
*  耗费时间:1417
*  @throws IOException
*/

private static void nioCopyTest1()throws IOException { long startTime = System.currentTimeMillis(); FileInputStream fileInputStream = new FileInputStream(new File(“E:\ 1.avi”)); FileOutputStream fileOutputStream = new FileOutputStream(“E:\ 11.avi”);

   //获取通道
   FileChannel inChannel = fileInputStream.getChannel();
   FileChannel outChanel = fileOutputStream.getChannel();

   //分配缓冲区的大小
   ByteBuffer buf = ByteBuffer.allocate(1024);

   //将通道中的数据存入缓冲区
   while (inChannel.read(buf) != -1) {
       buf.flip();//切换读取数据的模式
       outChanel.write(buf);
       buf.clear();
   }
   outChanel.close();
   inChannel.close();
   fileInputStream.close();
   fileOutputStream.close();
   long end = System.currentTimeMillis();
   System.out.println("nioCopyTest1耗费时间:"+(end-startTime));

} }




<a name="d2G9H"></a>
# 网络IO
[https://www.jianshu.com/p/da4a806e599b](https://www.jianshu.com/p/da4a806e599b)<br />Java网络编程:[https://www.liaoxuefeng.com/wiki/1252599548343744/1319099982413858](https://www.liaoxuefeng.com/wiki/1252599548343744/1319099982413858)

<a name="dXi0d"></a>
# 文件
`File`对象既可以表示文件,也可以表示目录。特别要注意的是,构造一个`File`对象,即使传入的文件或目录不存在,代码也不会出错,因为构造一个`File`对象,并不会导致任何磁盘操作。只有当我们调用`File`对象的某些方法的时候,才真正进行磁盘操作。**从Java7开始引入了path与Files类来操作文件,比之前的File类要方便的多。**
```java
package file;
import java.io.File;

public class TestFile {
    public static void main(String[] args) {
        File f = new File("/root/Test.java");
        System.out.println("Absolute path is:" + f.getAbsolutePath());
          System.out.println("Is file exist:" + f.exists());
          System.out.println("Is file Directory:"+f.isDirectory());
           System.out.println("Is file:" + f.isFile());

          f.setLastModified(0);
          System.out.println("File:" + f.lastModified());

        File[] fs = f.listFiles(); // 返回当前文件夹下文件
          String parentName = f.getParent(); // 返回当前文件目录
          f.mkdir(); // mkdir
          f.mkdirs(); // mkdir -p 
          f.createNewFile(); // create new file
    }
}

java.nio.file.Paths

  • static Path get(Srting first, String.. more) ,从给定的连接串创造一个Path

java.nio.file.Path

  • toFile() 从该路径中获取File对象

java.io.File

  • Path toPath() 从该文件创建一个File对象

java.nio.file.Files

  • 读写文件
  • 创建文件
  • 移动复制删除文件
  • 读取文件信息

随机访问文件

RandomAccessFile类可以在文件中任意位置查找或者写入数据,因为磁盘文件都是随机访问的,但是网络套接字却不是。
java.io.RandomAccessFile

  • RandomAccessFile(String file, String mode)
  • RandomAccessFile(Filefile, String mode)
    • file 要打开的文件
    • mode “r”表示只读模式, “rw”表示读写模式,”rws”对数据和元数据写磁盘操作进行同步的读写,”rwd” 仅对数据写磁盘操作进行同步的读写
  • long get FilePointer() 返回文件指针的当前位置
  • void seeklong(pos) 将文件指针设置到距文件开头pos个字节处
  • long length() 返回文件按照字节度量的长度

    ZIP文件

    ZIP文档通常以压缩格式存储了一个或者多个文件,每个zip文档都有一个头,包含诸如每个文件名字何所使用的压缩方法等信息。
    java.util.zip.ZipInputStream

  • ZipInputStream(InputStream in) 从给定的InputStream向其中填充数据

  • ZipEntry getNextEntry() 获取下一个ZipEntry对象

java.util.zip.ZipOutputStream

  • ZipInputStream(OutputStream out) 将一个压缩数据写到指定的ZipOutputStream

java.nio.file.FileSystems

  • 创建一个Zip文件系统来处理文件

参考
https://baijiahao.baidu.com/s?id=1652600456880754419&wfr=spider&for=pc