title: How to create compressed Zip archive using ZipOutputStream so that method getSize() of ZipEntry returns correct size?
body: <p>Consider the code example that put a single file <code>test_file.pdf</code> into zip archive <code>test.zip</code> and then read this archive:</p>
  
  <pre><code>import java.io.*;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipInputStream;
  import java.util.zip.ZipOutputStream;
  
  public class Main {
      public static void main(String[] args) {
          File infile = new File("test_file.pdf");
          try (
                  FileInputStream fis = new FileInputStream(infile);
                  ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("test.zip"));
          ) {
              int bytesRead;
              byte[] buffer = new byte[1024];
              ZipEntry entry = new ZipEntry("data");
              entry.setSize(infile.length());
  
              zos.putNextEntry(entry);
              while ((bytesRead = fis.read(buffer)) &gt;= 0)
              {
                  zos.write(buffer, 0, bytesRead);
              }
              zos.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          try (
                  ZipInputStream zis = new ZipInputStream(new BufferedInputStream(
                          new FileInputStream(new File("test.zip"))));
          ) {
              ZipEntry entry = zis.getNextEntry();
              System.out.println("Entry size: " + entry.getSize());
              zis.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
      }
  }
  </code></pre>
  
  <p>Output:
  <code>Entry size: -1</code></p>
  
  <p>But if create uncompressed zip archive (method <code>ZipEntry.STORED</code>), getSize() returns correct size:</p>
  
  <pre><code>import java.io.*;
  import java.util.zip.CRC32;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipInputStream;
  import java.util.zip.ZipOutputStream;
  
  public class Main {
      public static void main(String[] args) {
          File infile = new File("test_file.pdf");
          try (
                  FileInputStream fis = new FileInputStream(infile);
                  ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("test.zip"));
          ) {
              int bytesRead;
              byte[] buffer = new byte[1024];
              CRC32 crc = new CRC32();
              try (
                      BufferedInputStream bis = new BufferedInputStream(new FileInputStream(infile));
               ) {
                  crc.reset();
                  while ((bytesRead = bis.read(buffer)) != -1) {
                      crc.update(buffer, 0, bytesRead);
                  }
              }
              ZipEntry entry = new ZipEntry("data");
              entry.setMethod(ZipEntry.STORED);
              entry.setCompressedSize(infile.length());
              entry.setSize(infile.length());
              entry.setCrc(crc.getValue());
  
              zos.putNextEntry(entry);
              while ((bytesRead = fis.read(buffer)) &gt;= 0)
              {
                  zos.write(buffer, 0, bytesRead);
              }
              zos.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          try (
                  ZipInputStream zis = new ZipInputStream(new BufferedInputStream(
                          new FileInputStream(new File("test.zip"))));
          ) {
              ZipEntry entry = zis.getNextEntry();
              System.out.println("Entry size: " + entry.getSize());
              zis.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
      }
  }
  </code></pre>
  
  <p>Output (for example but correct):
  <code>Entry size: 9223192</code></p>
  
  <p>Compressed zip archives with correct <code>entry.getSize()</code> exists (e.g. zip archives by Ark program). </p>
  
  <p>So <strong>question</strong>: how to create <strong>compressed</strong> (<code>ZipEntry.DEFLATED</code> or another if exists) zip archive that returns correct size of the entry using only the standard libraries?</p>
  
  <p>I tried <a href="https://stackoverflow.com/questions/4169370/why-zipinputstream-cant-read-the-output-of-zipoutputstream">this recommendation</a> but it also does not work:</p>
  
  <pre><code>import java.io.*;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipInputStream;
  import java.util.zip.ZipOutputStream;
  
  public class Main {
      public static void main(String[] args) {
          File infile = new File("test_file.pdf");
          try (
                  FileInputStream fis = new FileInputStream(infile);
                  ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("test.zip"));
          ) {
              int bytesRead;
              byte[] buffer = new byte[1024];
              ZipEntry entry = new ZipEntry("data");
              entry.setSize(infile.length());
  
              zos.putNextEntry(entry);
              while ((bytesRead = fis.read(buffer)) &gt;= 0)
              {
                  zos.write(buffer, 0, bytesRead);
              }
              zos.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          try (
                  ZipInputStream zis = new ZipInputStream(new BufferedInputStream(
                          new FileInputStream(new File("test.zip"))));
          ) {
              ZipEntry entry = zis.getNextEntry();
              byte[] buffer = new byte[1];
              zis.read(buffer);
              System.out.println("Entry size: " + entry.getSize());
              zis.closeEntry();
  
          } catch (IOException e) {
              e.printStackTrace();
          }
  
      }
  }
  </code></pre>
  
  <p>Output:
  <code>Entry size: -1</code></p>