How to create a zip file in Java

JavaZip

Java Problem Overview


I have a dynamic text file that picks content from a database according to the user's query. I have to write this content into a text file and zip it in a folder in a servlet. How should I do this?

Java Solutions


Solution 1 - Java

Look at this example:

StringBuilder sb = new StringBuilder();
sb.append("Test String");

File f = new File("d:\\test.zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
ZipEntry e = new ZipEntry("mytext.txt");
out.putNextEntry(e);

byte[] data = sb.toString().getBytes();
out.write(data, 0, data.length);
out.closeEntry();

out.close();

This will create a zip in the root of D: named test.zip which will contain one single file called mytext.txt. Of course you can add more zip entries and also specify a subdirectory like this:

ZipEntry e = new ZipEntry("folderName/mytext.txt");

You can find more information about compression with Java here.

Solution 2 - Java

Java 7 has ZipFileSystem built in, that can be used to create, write and read file from zip file.

Java Doc: ZipFileSystem Provider

Map<String, String> env = new HashMap<>();
// Create the zip file if it doesn't exist
env.put("create", "true");

URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
    Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt");
    Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");          
    // Copy a file into the zip file
    Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); 
}

Solution 3 - Java

To write a ZIP file, you use a ZipOutputStream. For each entry that you want to place into the ZIP file, you create a ZipEntry object. You pass the file name to the ZipEntry constructor; it sets the other parameters such as file date and decompression method. You can override these settings if you like. Then, you call the putNextEntry method of the ZipOutputStream to begin writing a new file. Send the file data to the ZIP stream. When you are done, call closeEntry. Repeat for all the files you want to store. Here is a code skeleton:

FileOutputStream fout = new FileOutputStream("test.zip");
ZipOutputStream zout = new ZipOutputStream(fout);
for all files
{
    ZipEntry ze = new ZipEntry(filename);
    zout.putNextEntry(ze);
    send data to zout;
    zout.closeEntry();
}
zout.close();

Solution 4 - Java

Here is an example code to compress a Whole Directory(including sub files and sub directories), it's using the walk file tree feature of Java NIO.

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCompress {
    public static void compress(String dirPath) {
        final Path sourceDir = Paths.get(dirPath);
        String zipFileName = dirPath.concat(".zip");
        try {
            final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
            Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) {
                    try {
                        Path targetFile = sourceDir.relativize(file);
                        outputStream.putNextEntry(new ZipEntry(targetFile.toString()));
                        byte[] bytes = Files.readAllBytes(file);
                        outputStream.write(bytes, 0, bytes.length);
                        outputStream.closeEntry();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

To use this, just call

ZipCompress.compress("target/directoryToCompress");

and you'll get a zip file directoryToCompress.zip

Solution 5 - Java

Single file:

String filePath = "/absolute/path/file1.txt";
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    File fileToZip = new File(filePath);
    zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
    Files.copy(fileToZip.toPath(), zipOut);
}

Multiple files:

List<String> filePaths = Arrays.asList("/absolute/path/file1.txt", "/absolute/path/file2.txt");
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    for (String filePath : filePaths) {
        File fileToZip = new File(filePath);
        zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
        Files.copy(fileToZip.toPath(), zipOut);
    }
}

Solution 6 - Java

Spring boot controller, zip the files in a directory, and can be downloaded.

@RequestMapping(value = "/files.zip")
@ResponseBody
byte[] filesZip() throws IOException {
    File dir = new File("./");
    File[] filesArray = dir.listFiles();
    if (filesArray == null || filesArray.length == 0)
        System.out.println(dir.getAbsolutePath() + " have no file!");
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ZipOutputStream zipOut= new ZipOutputStream(bo);
    for(File xlsFile:filesArray){
        if(!xlsFile.isFile())continue;
        ZipEntry zipEntry = new ZipEntry(xlsFile.getName());
        zipOut.putNextEntry(zipEntry);
        zipOut.write(IOUtils.toByteArray(new FileInputStream(xlsFile)));
        zipOut.closeEntry();
    }
    zipOut.close();
    return bo.toByteArray();
}

Solution 7 - Java

This is how you create a zip file from a source file:

String srcFilename = "C:/myfile.txt";
String zipFile = "C:/myfile.zip";

try {
	byte[] buffer = new byte[1024];
	FileOutputStream fos = new FileOutputStream(zipFile);
	ZipOutputStream zos = new ZipOutputStream(fos);			
	File srcFile = new File(srcFilename);
	FileInputStream fis = new FileInputStream(srcFile);
	zos.putNextEntry(new ZipEntry(srcFile.getName()));			
	int length;
	while ((length = fis.read(buffer)) > 0) {
		zos.write(buffer, 0, length);
	}
	zos.closeEntry();
	fis.close();
	zos.close();			
}
catch (IOException ioe) {
	System.out.println("Error creating zip file" + ioe);
}

Solution 8 - Java

public static void main(String args[])
{
    omtZip("res/", "omt.zip");
}
public static void omtZip(String path,String outputFile)
{
    final int BUFFER = 2048;
    boolean isEntry = false;
    ArrayList<String> directoryList = new ArrayList<String>();
    File f = new File(path);
    if(f.exists())
    {
    try {
            FileOutputStream fos = new FileOutputStream(outputFile);
            ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
            byte data[] = new byte[BUFFER];

            if(f.isDirectory())
            {
               //This is Directory
                do{
                    String directoryName = "";
                    if(directoryList.size() > 0)
                    {
                        directoryName = directoryList.get(0);
                        System.out.println("Directory Name At 0 :"+directoryName);
                    }
                    String fullPath = path+directoryName;
                    File fileList = null;
                    if(directoryList.size() == 0)
                    {
                        //Main path (Root Directory)
                        fileList = f;
                    }else
                    {
                        //Child Directory
                        fileList = new File(fullPath);
                    }
                    String[] filesName = fileList.list();

                    int totalFiles = filesName.length;
                    for(int i = 0 ; i < totalFiles ; i++)
                    {
                        String name = filesName[i];
                        File filesOrDir = new File(fullPath+name);
                        if(filesOrDir.isDirectory())
                        {
                            System.out.println("New Directory Entry :"+directoryName+name+"/");
                            ZipEntry entry = new ZipEntry(directoryName+name+"/");
                            zos.putNextEntry(entry);
                            isEntry = true;
                            directoryList.add(directoryName+name+"/");
                        }else
                        {
                            System.out.println("New File Entry :"+directoryName+name);
                            ZipEntry entry = new ZipEntry(directoryName+name);
                            zos.putNextEntry(entry);
                            isEntry = true;
                            FileInputStream fileInputStream = new FileInputStream(filesOrDir);
                            BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, BUFFER);
                            int size = -1;
                            while(  (size = bufferedInputStream.read(data, 0, BUFFER)) != -1  )
                            {
                                zos.write(data, 0, size);
                            }
                            bufferedInputStream.close();
                        }
                    }
                    if(directoryList.size() > 0 && directoryName.trim().length() > 0)
                    {
                        System.out.println("Directory removed :"+directoryName);
                        directoryList.remove(0);
                    }

                }while(directoryList.size() > 0);
            }else
            {
                //This is File
                //Zip this file
                System.out.println("Zip this file :"+f.getPath());
                FileInputStream fis = new FileInputStream(f);
                BufferedInputStream bis = new BufferedInputStream(fis,BUFFER);
                ZipEntry entry = new ZipEntry(f.getName());
                zos.putNextEntry(entry);
                isEntry = true;
                int size = -1 ;
                while(( size = bis.read(data,0,BUFFER)) != -1)
                {
                    zos.write(data, 0, size);
                }
            }               

            //CHECK IS THERE ANY ENTRY IN ZIP ? ----START
            if(isEntry)
            {
              zos.close();
            }else
            {
                zos = null;
                System.out.println("No Entry Found in Zip");
            }
            //CHECK IS THERE ANY ENTRY IN ZIP ? ----START
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }else
    {
        System.out.println("File or Directory not found");
    }
 }    

}

Solution 9 - Java

Given exportPath and queryResults as String variables, the following block creates a results.zip file under exportPath and writes the content of queryResults to a results.txt file inside the zip.

URI uri = URI.create("jar:file:" + exportPath + "/results.zip");
Map<String, String> env = Collections.singletonMap("create", "true");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
  Path filePath = zipfs.getPath("/results.txt");
  byte[] fileContent = queryResults.getBytes();

  Files.write(filePath, fileContent, StandardOpenOption.CREATE);
}

Solution 10 - Java

You have mainly to create two functions. First is writeToZipFile() and second is createZipfileForOutPut .... and then call the createZipfileForOutPut('file name of .zip')` …

 public static void writeToZipFile(String path, ZipOutputStream zipStream)
        throws FileNotFoundException, IOException {

    System.out.println("Writing file : '" + path + "' to zip file");

    File aFile = new File(path);
    FileInputStream fis = new FileInputStream(aFile);
    ZipEntry zipEntry = new ZipEntry(path);
    zipStream.putNextEntry(zipEntry);

    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zipStream.write(bytes, 0, length);
    }

    zipStream.closeEntry();
    fis.close();
}

public static void createZipfileForOutPut(String filename) {
    String home = System.getProperty("user.home");
   // File directory = new File(home + "/Documents/" + "AutomationReport");
    File directory = new File("AutomationReport");
    if (!directory.exists()) {
        directory.mkdir();
    }
    try {
        FileOutputStream fos = new FileOutputStream("Path to your destination" + filename + ".zip");
        ZipOutputStream zos = new ZipOutputStream(fos);

        writeToZipFile("Path to file which you want to compress / zip", zos);

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

Solution 11 - Java

There is another option by using zip4j at https://github.com/srikanth-lingala/zip4j

Creating a zip file with single file in it / Adding single file to an existing zip

new ZipFile("filename.zip").addFile("filename.ext"); Or

new ZipFile("filename.zip").addFile(new File("filename.ext"));

Creating a zip file with multiple files / Adding multiple files to an existing zip

new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));

Creating a zip file by adding a folder to it / Adding a folder to an existing zip

new ZipFile("filename.zip").addFolder(new File("/user/myuser/folder_to_add"));

Creating a zip file from stream / Adding a stream to an existing zip new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

Solution 12 - Java

I know this question is answered but if you have a list of strings and you want to create a separate file for each string in the archive, you can use the snippet below.

public void zipFileTest() throws IOException {

    Map<String, String> map = Map.ofEntries(
            new AbstractMap.SimpleEntry<String, String>("File1.txt", "File1 Content"),
            new AbstractMap.SimpleEntry<String, String>("File2.txt", "File2 Content"),
            new AbstractMap.SimpleEntry<String, String>("File3.txt", "File3 Content")
    );

    createZipFileFromStringContents(map, "archive.zip");

}

public void createZipFileFromStringContents(Map<String, String> map, String zipfilePath) throws IOException {

    FileOutputStream fout = new FileOutputStream(zipfilePath);
    ZipOutputStream zout = new ZipOutputStream(fout);

    for (Map.Entry<String, String> entry : map.entrySet()) {
        String fileName = entry.getKey();
        ZipEntry zipFile = new ZipEntry(fileName);
        zout.putNextEntry(zipFile);
        String fileContent = entry.getValue();
        zout.write(fileContent.getBytes(), 0, fileContent.getBytes().length);
        zout.closeEntry();
    }

    zout.close();
}

It will create a zip file with the structure as in the below image:

zip file structure

Solution 13 - Java

Here is my working solution:

public static byte[] createZipFile(Map<String, FileData> files) throws IOException {
	try(ByteArrayOutputStream tZipFile = new ByteArrayOutputStream()) {
		try (ZipOutputStream tZipFileOut = new ZipOutputStream(tZipFile)) {
			for (Map.Entry<String, FileData> file : files.entrySet()) {
		        ZipEntry zipEntry = new ZipEntry(file.getValue().getFileName());
		        tZipFileOut.putNextEntry(zipEntry);
		        tZipFileOut.write(file.getValue().getBytes());
			}
		}

		return tZipFile.toByteArray();
	}
}

public class FileData {
   	private String fileName;
	private byte[] bytes;

	public String getFileName() {
		return this.fileName;
	}

	public byte[] getBytes() {
		return this.bytes;
	}
}

This will create byte[] of ZIP file which contains one or more compressed files. I've used this method inside controller method and write bytes[] of ZIP file into response to download ZIP file(s) from server.

Solution 14 - Java

If you want decompress without software better use this code. Other code with pdf files sends error on manually decompress

byte[] buffer = new byte[1024]; 	
	try
	{	
		FileOutputStream fos = new FileOutputStream("123.zip");
		ZipOutputStream zos = new ZipOutputStream(fos);
		ZipEntry ze= new ZipEntry("file.pdf");
		zos.putNextEntry(ze);
		FileInputStream in = new FileInputStream("file.pdf");
		int len;
		while ((len = in.read(buffer)) > 0) 
		{
			zos.write(buffer, 0, len);
		}
		in.close();
		zos.closeEntry();
		zos.close();
	}
	catch(IOException ex)
	{
	   ex.printStackTrace();
	}

Solution 15 - Java

Since it took me a while to figure it out, I thought it would be helpful to post my solution using Java 7+ ZipFileSystem

 openZip(runFile);
 
 addToZip(filepath); //loop construct;  
 
 zipfs.close();

 private void openZip(File runFile) throws IOException {
	Map<String, String> env = new HashMap<>();
	env.put("create", "true");
	env.put("encoding", "UTF-8");
	Files.deleteIfExists(runFile.toPath());
	zipfs = FileSystems.newFileSystem(URI.create("jar:" + runFile.toURI().toString()), env);	
 }

 private void addToZip(String filename) throws IOException {
	Path externalTxtFile = Paths.get(filename).toAbsolutePath();
	Path pathInZipfile = zipfs.getPath(filename.substring(filename.lastIndexOf("results"))); //all files to be stored have a common base folder, results/ in my case
	if (Files.isDirectory(externalTxtFile)) {
		Files.createDirectories(pathInZipfile);
        try (DirectoryStream<Path> ds = Files.newDirectoryStream(externalTxtFile)) {
            for (Path child : ds) {
            	addToZip(child.normalize().toString()); //recursive call
            }
        }
	} else {
		// copy file to zip file
		Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); 			
	}
 }

Solution 16 - Java

public static void zipFromTxt(String zipFilePath, String txtFilePath) {
    Assert.notNull(zipFilePath, "Zip file path is required");
    Assert.notNull(txtFilePath, "Txt file path is required");
    zipFromTxt(new File(zipFilePath), new File(txtFilePath));
}

public static void zipFromTxt(File zipFile, File txtFile) {
    ZipOutputStream out = null;
    FileInputStream in = null;
    try {
        Assert.notNull(zipFile, "Zip file is required");
        Assert.notNull(txtFile, "Txt file is required");
        out = new ZipOutputStream(new FileOutputStream(zipFile));
        in = new FileInputStream(txtFile);
        out.putNextEntry(new ZipEntry(txtFile.getName()));
        int len;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
    } catch (Exception e) {
        log.info("Zip from txt occur error,Detail message:{}", e.toString());
    } finally {
        try {
            if (in != null) in.close();
            if (out != null) {
                out.closeEntry();
                out.close();
            }
        } catch (Exception e) {
            log.info("Zip from txt close error,Detail message:{}", e.toString());
        }
    }
}

Solution 17 - Java

Using Jeka https://jeka.dev JkPathTree, it's quite straightforward.

Path wholeDirToZip = Paths.get("dir/to/zip");
Path zipFile = Paths.get("file.zip");
JkPathTree.of(wholeDirToZip).zipTo(zipFile);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAshish AgarwalView Question on Stackoverflow
Solution 1 - JavaChrisView Answer on Stackoverflow
Solution 2 - JavaSivabalanView Answer on Stackoverflow
Solution 3 - JavaWiseGeekView Answer on Stackoverflow
Solution 4 - JavaOwen CaoView Answer on Stackoverflow
Solution 5 - JavaPavelView Answer on Stackoverflow
Solution 6 - JavaYuiffyView Answer on Stackoverflow
Solution 7 - Javalive-loveView Answer on Stackoverflow
Solution 8 - JavaDhiral PandyaView Answer on Stackoverflow
Solution 9 - JavaCamilo SilvaView Answer on Stackoverflow
Solution 10 - JavaTarpan PatelView Answer on Stackoverflow
Solution 11 - Javasendon1982View Answer on Stackoverflow
Solution 12 - JavaTevfik KizilorenView Answer on Stackoverflow
Solution 13 - JavadkeroView Answer on Stackoverflow
Solution 14 - JavacmujicaView Answer on Stackoverflow
Solution 15 - JavaSiraj KView Answer on Stackoverflow
Solution 16 - Java鄒成立View Answer on Stackoverflow
Solution 17 - JavaJerome AngibaudView Answer on Stackoverflow