I am trying to add a file to a zip archive. I want to do something like this
public void zipFile(Path fileToZip, Path zipFile) {
ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile, CREATE, APPEND));
FileChannel outputChannel = new FileOutputStream(zipOut).getChannel() //How to go from zipoutputstream to FileChannel...
FileChannel inputChannel = FileChannel.open(zipFile, READ)
ZipEntry zipEntry = new ZipEntry(fileToZip.toString());
zipOut.putNextEntry(zipEntry);
inputChannel.transferTo (0, inputChannel.size(), outputChannel);
outputChannel.close();
inputChannel.close();
}
but ZipOutputStream doesn't have a getChannel() like FileOutputStream does. How can I create a zip file using channels?
You can turn any OutputStream into a Channel using the Channels.newChannel method.
Turns out, this is very very easy to do. Don't use channels or anything. Just create a zipfilesystem and copy the files over.
http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html
Related
The steps I followed are.
get all objects from recursive objects
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName).recursive(true).build());
Then getting all streams of matching the prefix
InputStream stream = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName).object(objectName).build());
the list of multiple stream got by the InputStream stream How do we convert it into zip file ?
tried the following code but it's (zipOut) coming as null.
downloading empty zip, How do we fix this ?
ByteArrayOutputStream fos = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(fos);
ZipEntry zipEntry1 = new ZipEntry(objectName);
zipEntry1.setSize(resource.contentLength());
zipEntry1.setTime(System.currentTimeMillis());
zipOut.putNextEntry(zipEntry1);
StreamUtils.copy(stream.readAllBytes(), zipOut);
zipOut.closeEntry();
Thanks in advance.
I have a simple code that is supposed to make txt file zipped, though txt file has some content, it's empty in a zip folder ( it has 89 bytes ( like buffer ) but all are just spaces.
The interesting part is that if I write
byte[] buffer = Files.readAllBytes(path);
my code is working.
I am new to java and would appreciate your help a lot. Because I trully don't understand what I am doing wroing.
public class Test {
public static void main(String[] args) throws IOException {
try (FileInputStream fis = new FileInputStream("C:\\Users\\10\\Desktop\\ds.txt");
ZipInputStream zis = new ZipInputStream(fis);
ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(Paths.get("C:\\Users\\10\\Desktop\\ds.zip")))) {
byte[] buffer = new byte[fis.available()];
zos.putNextEntry(new ZipEntry("ds.txt"));
zis.read(buffer);
zos.write(buffer);
zos.closeEntry();
}
Since the text file is not zipped yet, don't use a ZipInputStream to read it. Just use the FileInputStream, or even better the NIO.2 File API (you're using it already to create the ZipOutputStream but not to create the InputStream).
There is even a file system provider for the NIO.2 File API to read/ write to Zip files using the same API: https://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html (For Java 11+ the following module is required: https://docs.oracle.com/en/java/javase/11/docs/api/jdk.zipfs/module-summary.html)
Also make sure to use try-with-resources for the OutputStream as well, not just the InputStream, to properly close the stream in the finally block.
I have a webapp that allows users to select images and then download them. For a single image, I use HTML5's anchor download and it works beautifully. Now I need to allow them to select multiple images, and download them as a .zip file. I'm using an api to get each image as an InputStream and returning a Jersey Response.
I'm new to zipping and I'm a bit confused with how zipping with InputStream should work.
For single images, it works like so:
try {
InputStream imageInputStream = ImageStore.getImage(imageId);
if (imageInputStream == null) {
XLog.warnf("Unable to find image [%s].", imageId);
return Response.status(HttpURLConnection.HTTP_GONE).build();
}
Response.ResponseBuilder response = Response.ok(imageInputStream);
response.header("Content-Type", imageType.mimeType());
response.header("Content-Disposition", "filename=image.jpg");
return response.build();
}
It's not much, but here's the java I have so far for multiple images
public Response zipAndDownload(List<UUID> imageIds) {
try {
// TODO: instantiate zip file?
for (UUID imageId : imageIds) {
InputStream imageInputStream = ImageStore.getImage(imageId);
// TODO: add image to zip file (ZipEntry?)
}
// TODO: return zip file
}
...
}
I just don't know how to deal with multiple InputStreams, and it seems that I shouldn't have multiple, right?
An InputStream per image is ok. To zip the files you need to create a .zip file for them to live in and get a ZipOutputStream to write to it:
File zipFile = new File("/path/to/your/zipFile.zip");
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
For each image, create a new ZipEntry, add it to the ZipOutputSteam, then copy the bytes from your image's InputStream to the ZipOutputStream:
ZipEntry ze = new ZipEntry("PrettyPicture1.jpg");
zos.putNextEntry(ze);
byte[] bytes = new byte[1024];
int count = imageInputStream.read(bytes);
while (count > -1)
{
zos.write(bytes, 0, count);
count = imageInputStream.read(bytes);
}
imageInputStream.close();
zos.closeEntry();
After you add all the entries, close the ZipOutputStream:
zos.close();
Now your zipFile points to a zip file full of pictures you can do whatever you want with. You can return it like you do with a single image:
BufferedInputStream zipFileInputStream = new BufferedInputStream(new FileInputStream(zipFile));
Response.ResponseBuilder response = Response.ok(zipFileInputStream);
But the content type and disposition are different:
response.header("Content-Type", MediaType.APPLICATION_OCTET_STREAM_TYPE);
response.header("Content-Disposition", "attachment; filename=zipFile.zip");
Note: You can use the copy method from Guava's ByteStreams helper to copy the streams instead of copying the bytes manually. Simply replace the while loop and the 2 lines before it with this line:
ByteStreams.copy(imageInputStream, zos);
I have a chararray which holds coordinates in every index. I want to compress the array with zip algorithm and write the zipped version of the array to a file. My idea was that i run the chararray through a zip stream and write it afterwards directly to a file like test.txt. The problem is, that nothing is written to the file after the execution of the code. Can somebody please help me solve that problem?
Kind regards Lorenzo
Here my current code:
byte[] bytes = Charset.forName("UTF-8").encode(CharBuffer.wrap(sample)).array();
FileOutputStream out = new FileOutputStream(cscFile, true);
byte[] compressed = new byte[bytes.length];
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ZipInputStream zi = new ZipInputStream(bi);
ZipEntry entry = null;
while ((entry = zi.getNextEntry()) != null) {
zi.read(compressed);
for(int i = 0; i<bytes.length;i++){
out.write(compressed[i]);
}
out.flush();
out.close();
zi.closeEntry();
}
zi.close();
You will probably have to slightly modify your code with something like this:
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("your zip file name")));
ZipEntry entry = new ZipEntry("zipped file name");
entry.setSize(bytes.length);
zos.putNextEntry(entry);
zos.write(bytes);
zos.closeEntry();
zos.close();
Explanation:
To compress writen data, use ZipOutputStream and give created FileOutputStream as constructor argument. After that, create ZipEntry, which represents file inside your zip file and write contents of byte array into it.
Hope it helps.
See similar question here: https://stackoverflow.com/a/357892/3115098
I would like to create a zip file with Commons VFS2 library. I know how to copy a file when using file prefix but for zip files write and read are not implemented.
fileSystemManager.resolveFile("path comes here")-method fails when I try path zip:/some/file.zip when file.zip is an non-existing zip-file. I can resolve an existing file but non-existing new file fails.
So how to create that new zip file then? I cannot use createFile() because it is not supported and I cannot create the FileObject before this is to be called.
The normal way is to create FileObject with that resolveFile and then call createFile for the object.
The answer to my need is the following code snippet:
// Create access to zip.
FileSystemManager fsManager = VFS.getManager();
FileObject zipFile = fsManager.resolveFile("file:/path/to/the/file.zip");
zipFile.createFile();
ZipOutputStream zos = new ZipOutputStream(zipFile.getContent().getOutputStream());
// add entry/-ies.
ZipEntry zipEntry = new ZipEntry("name_inside_zip");
FileObject entryFile = fsManager.resolveFile("file:/path/to/the/sourcefile.txt");
InputStream is = entryFile.getContent().getInputStream();
// Write to zip.
byte[] buf = new byte[1024];
zos.putNextEntry(zipEntry);
for (int readNum; (readNum = is.read(buf)) != -1;) {
zos.write(buf, 0, readNum);
}
After this you need to close the streams and it works!
In fact, it is possible to create zip files uniquely from Commons-VFS by using the following idio :
destinationFile = fileSystemManager.resolveFile(zipFileName);
// destination is created as a folder, as the inner content of the zip
// is, in fact, a "virtual" folder
destinationFile.createFolder();
// then add files to that "folder" (which is in fact a file)
// and finally close that folder to have a usable zip
destinationFile.close();
// Exception handling is left at user discretion