Copy Files from Internal Storage to external storage - java

Im trying to use Adobe reader to read pdf files downloaded from the server the problem is When i store it in the internal storage Other application can't read the file. Now i Want to know how can i Copy this file in the external storage(/sdcard/) so it can be viewed by pdf viewers.
Due to security reason I'm storing the files in the Internal Storage and would delete the one in external storage afterwards.
My question is How can i copy the file saved in the internal storage without using the raw or the assets to put in the inputstream.
InputStream myInput = getResources().openRawResource(R.raw.p13);
FileOutputStream fos = openFileOutput("sample", Context.MODE_PRIVATE);
// transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0)
{
fos.write(buffer, 0, length);
}
// Close the streams
fos.flush();
fos.close();
myInput.close();

at which path you are storing the pdf file ?
See below one to get file from android Assets and copy it to the specific sdcard location.
I will first check for the pdf file whether it is already available at desire path or not.
File file1 = new File("/sdcard/SampleProjectApp/WindsorONE_Mobile_Molding.pdf");
File file2 = new File("/sdcard/SampleProjectApp/WindsorONE_Mobile_PK.pdf");
File file3 = new File("/sdcard/SampleProjectApp/Alone.mp4");
if(!((file1.exists())) || !((file2.exists())) || !((file3.exists()))) {
ArrayList<String> files = new ArrayList<String>();
files.add("WindsorONE_Mobile_Molding.pdf");
files.add("WindsorONE_Mobile_PK.pdf");
files.add("Alone.mp4");
new myAsyncTask().execute(files);
}
Now, if the file is not present at that position then it will execute the myAsyncTask to copy file from assets to the SdCard.
// AsyncTass for the Progress Dialog and to do Background Process
private class myAsyncTask extends AsyncTask<ArrayList<String>, Void, Void> {
ArrayList<String> files;
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ListSample.this, "W1 SALES (beta)", "Loading...");
}
#Override
protected Void doInBackground(ArrayList<String>... params) {
files = params[0];
for (int i = 0; i < files.size(); i++) {
copyFileFromAssetsToSDCard(files.get(i));
} return null;
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
// Function to copy file from Assets to the SDCard
public void copyFileFromAssetsToSDCard(String fileFromAssets){
AssetManager is = this.getAssets();
InputStream fis;
try {
fis = is.open(fileFromAssets);
FileOutputStream fos;
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+"/SampleProjectApp", fileFromAssets));
byte[] b = new byte[8];
int i;
while ((i = fis.read(b)) != -1) {
fos.write(b, 0, i);
}
fos.flush();
fos.close();
fis.close();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
Updated
For your part:
replace
SampleProjectApp/WindsorONE_Mobile_Molding.pdf
with
Android/data/com.project.projectname/cache/YOUR_PDF_FILE.pdf
Hope it make sense.
Updated 2
Below code is copy file from one path to another path. You simply have to pass the path of the file where it is exist and the path where it has to be copy.
Code:
public static boolean copyFile(String from, String to) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(from);
if (oldfile.exists()) {
InputStream inStream = new FileInputStream(from);
FileOutputStream fs = new FileOutputStream(to);
byte[] buffer = new byte[1444];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
fs.write(buffer, 0, byteread);
}
inStream.close();
fs.close();
}
return true;
} catch (Exception e) {
return false;
}
}

you can use this method
boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if(isSDPresent)
{
InputStream in = null;
OutputStream out = null;
in = //Place your file in the inputstream
out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + filename);
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
}
else
{
Toast.makeText(getApplicationContext(), "SD Card not present", Toast.LENGTH_LONG).show();
}

Related

Unzip to folder in internal storage

I'm trying to create a folder in internal storage called "unzip" and then unzip a file into the internal storage "unzip folder". Not sure what i'm doing wrong? If you could please explain what's wrong it'd be great! Thanks
Edit: The issues is that I don't think the folder is being created and the file is also not being unzipped.
public void send(View view) {
try {
File mydir = this.getDir("unzip", Context.MODE_PRIVATE);//create folder in internal storage
unzip(getFilesDir().getAbsolutePath(), job_no, getFilesDir() + "/unzip/");
} catch (IOException e) {
}
}
public void unzip(String filepath, String filename, String unzip_path) throws IOException {
InputStream is = new FileInputStream(filepath + filename);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
try {
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
String filename_temp = ze.getName();
File fmd = new File(filepath + filename_temp);
if (!fmd.getParentFile().exists()) {
fmd.getParentFile().mkdirs();
}
FileOutputStream fout = new FileOutputStream(unzip_path + filename_temp);
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
//}
}
} finally {
zis.close();
}
}
This will get absolute storage device.
final static String MEDIA_PATH = Environment.getExternalStorageDirectory().getPath() + "/";

Saving file to resource directory using Spring

I have this project structure:
/webapp
/res
/img
/profile.jpg
/WEB-INF
And I need to save file to res/img/ directory. This time I have this code:
public String fileUpload(UploadedFile uploadedFile) {
InputStream inputStream = null;
OutputStream outputStream = null;
MultipartFile file = uploadedFile.getFile();
String fileName = file.getOriginalFilename();
File newFile = new File("/res/img/" + fileName);
try {
inputStream = file.getInputStream();
if (!newFile.exists()) {
newFile.createNewFile();
}
outputStream = new FileOutputStream(newFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
return newFile.getAbsolutePath();
}
But it saving files to user.dir directory, which is ~/Work/Tomcat/bin/.
So how I can upload files to res directory?
You shouldn't really be uploading files there.
If you are using a war, redeploying will delete them. If they are intended to be temporary then use an os assigned temporary location.
If you intend to publish them afterwards then choose a location in which to store the files on your server, make this location known to the application and save and load files from the location.
If you are trying to replace resources dynamically such as an image which is referenced in the html or css templates, then consider publishing the external location separately, you can use mvc:resources for this e.g:
<mvc:resources mapping="/images/**" location="file:/absolute/path/to/image/dir"/>
and you would save your files to that location. This will make it more permanent between deployments.
To save an image to that location using your code you will need to add this into your bean definition (assuming you are using xml configuration without annotations):
<property name="imagesFolder" value="/absolute/path/to/image/dir"/>
and keeping your code as similar as possible change it to:
private String imagesFolder;
public void setImagesFolder(String imagesFolder) {
this.imagesFolder = imagesFolder;
}
public String fileUpload(UploadedFile uploadedFile) {
InputStream inputStream = null;
OutputStream outputStream = null;
MultipartFile file = uploadedFile.getFile();
String fileName = file.getOriginalFilename();
File newFile = new File(imagesFolder + fileName);
try {
inputStream = file.getInputStream();
if (!newFile.exists()) {
newFile.createNewFile();
}
outputStream = new FileOutputStream(newFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
return newFile.getAbsolutePath();
}
Please bear in mind that you need to change /absolute/path/to/image/dir to an actual path that exists, also I would recommend to look at the Spring Resources documentation for a better way to deal with files and resources.
Please refer FileUploadController from here to save file to the specified directory.
public String fileUpload(UploadedFile uploadedFile) {
InputStream inputStream = null;
OutputStream outputStream = null;
MultipartFile file = uploadedFile.getFile();
String rootPath = System.getProperty("user.dir");
File dir = new File(rootPath + File.separator + "webapp"+File.separator+"res"+File.separator+"img");
if (!dir.exists())
dir.mkdirs();
String fileName = file.getOriginalFilename();
File serverFile = new File(dir.getAbsolutePath() + File.separator + fileName);
try {
inputStream = file.getInputStream();
if (!newFile.exists()) {
newFile.createNewFile();
}
outputStream = new FileOutputStream(newFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
return newFile.getAbsolutePath();
}

Android - Copy assets to internal storage

Good day!
I have just started developing for android. In my app, I need to copy the items in my assets folder to the internal storage.
I have searched a lot on SO including this which copies it to the external storage.
How to copy files from 'assets' folder to sdcard?
This is what I want to achieve:
I have a directory already present in the internal storage as X>Y>Z. I need a file to be copied to Y and another to Z.
Can anyone help me out with a code snippet? I really don't have any idea how to go on about this.
Sorry for my bad English.
Thanks a lot.
Use
String out= Environment.getExternalStorageDirectory().getAbsolutePath() + "/X/Y/Z/" ;
File outFile = new File(out, Filename);
After Editing in your ref. Link Answer.
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
String outDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/X/Y/Z/" ;
File outFile = new File(outDir, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
I did something like this. This allows you to copy all the directory structure to copy from Android AssetManager.
public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException
{
File sd_path = Environment.getExternalStorageDirectory();
String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
File dest_dir = new File(dest_dir_path);
createDir(dest_dir);
AssetManager asset_manager = getApplicationContext().getAssets();
String[] files = asset_manager.list(arg_assetDir);
for (int i = 0; i < files.length; i++)
{
String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
String sub_files[] = asset_manager.list(abs_asset_file_path);
if (sub_files.length == 0)
{
// It is a file
String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
copyAssetFile(abs_asset_file_path, dest_file_path);
} else
{
// It is a sub directory
copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
}
}
return dest_dir_path;
}
public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException
{
InputStream in = getApplicationContext().getAssets().open(assetFilePath);
OutputStream out = new FileOutputStream(destinationFilePath);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
}
public String addTrailingSlash(String path)
{
if (path.charAt(path.length() - 1) != '/')
{
path += "/";
}
return path;
}
public String addLeadingSlash(String path)
{
if (path.charAt(0) != '/')
{
path = "/" + path;
}
return path;
}
public void createDir(File dir) throws IOException
{
if (dir.exists())
{
if (!dir.isDirectory())
{
throw new IOException("Can't create directory, a file is in the way");
}
} else
{
dir.mkdirs();
if (!dir.isDirectory())
{
throw new IOException("Unable to create directory");
}
}
}
try this below code
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(getExternalFilesDir(null), filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
This is my Kotlin solution with auto-closable streams to copy in internal app storage:
val copiedFile = File(context.filesDir, "copied_file.txt")
context.assets.open("original_file.txt").use { input ->
copiedFile.outputStream().use { output ->
input.copyTo(output, 1024)
}
}
My small solution on Kotlin, for copy data from assets to INTERNAL STORAGE
fun copy() {
val bufferSize = 1024
val assetManager = context.assets
val assetFiles = assetManager.list("")
assetFiles.forEach {
val inputStream = assetManager.open(it)
val outputStream = FileOutputStream(File(context.filesDir, it))
try {
inputStream.copyTo(outputStream, bufferSize)
} finally {
inputStream.close()
outputStream.flush()
outputStream.close()
}
}
}
public void addFilesToSystem(String sysName, String intFil, Context c){
//sysName is the name of the file we have in the android os
//intFil is the name of the internal file
file = new File(path, sysName + ".txt");
if(!file.exists()){
path.mkdirs();
try {
AssetManager am = c.getAssets();
InputStream is = am.open(intFil);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
Toast t = Toast.makeText(c, "Making file: " + file.getName() + ". One time action", Toast.LENGTH_LONG);
t.show();
//Update files for the user to use
MediaScannerConnection.scanFile(c,
new String[] {file.toString()},
null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
// TODO Auto-generated method stub
}
});
} catch (IOException e) {
Toast t = Toast.makeText(c, "Error: " + e.toString() + ". One time action", Toast.LENGTH_LONG);
t.show();
e.printStackTrace();
}
}
}
To add a file, call the addFilesToSystem("this_file_is_in_the_public_system", "this_file_is_in_the_assets_folder", context/this context is if you do not have the method in the Activity/
Hope it helps
You can use the Envrionment#getDataDirectory method for that. It'll give the path of the data directory of the internal storage memory. This is generally where all the app related data is stored.
Alternately, if you want to store in the root directory, you can use the Environment#getRootDirectory method for that.
If you need to copy any file from assets to the internal storage and do it only once:
public void writeFileToStorage() {
Logger.d(TAG, ">> writeFileToStorage");
AssetManager assetManager = mContext.getAssets();
if (new File(getFilePath()).exists()) {
Logger.d(TAG, "File exists, do nothing");
Logger.d(TAG, "<< writeFileToStorage");
return;
}
try (InputStream input = assetManager.open(FILE_NAME);
OutputStream output = new FileOutputStream(getFilePath())) {
Logger.d(TAG, "File does not exist, write it");
byte[] buffer = new byte[input.available()];
int length;
while ((length = input.read(buffer)) != -1) {
output.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Logger.e(TAG, "File is not found");
} catch (IOException e) {
e.printStackTrace();
Logger.d(TAG, "Error while writing the file");
}
Logger.d(TAG, "<< writeFileToStorage");
}
public String getFilePath() {
String filePath = mContext.getFilesDir() + "/" + FILE_NAME;
Logger.d(TAG, "File path: " + filePath);
return filePath;
}

How to unzip files programmatically in Android?

I need a small code snippet which unzips a few files from a given .zip file and gives the separate files according to the format they were in the zipped file. Please post your knowledge and help me out.
Had peno's version optimised a bit. The increase in performance is perceptible.
private boolean unpackZip(String path, String zipname)
{
InputStream is;
ZipInputStream zis;
try
{
String filename;
is = new FileInputStream(path + zipname);
zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null)
{
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
File fmd = new File(path + filename);
fmd.mkdirs();
continue;
}
FileOutputStream fout = new FileOutputStream(path + filename);
while ((count = zis.read(buffer)) != -1)
{
fout.write(buffer, 0, count);
}
fout.close();
zis.closeEntry();
}
zis.close();
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
Based on Vasily Sochinsky's answer a bit tweaked & with a small fix:
public static void unzip(File zipFile, File targetDirectory) throws IOException {
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(new FileInputStream(zipFile)));
try {
ZipEntry ze;
int count;
byte[] buffer = new byte[8192];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
FileOutputStream fout = new FileOutputStream(file);
try {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
} finally {
fout.close();
}
/* if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
*/
}
} finally {
zis.close();
}
}
Notable differences
public static - this is a static utility method that can be anywhere.
2 File parameters because String are :/ for files and one could not specify where the zip file is to be extracted before. Also path + filename concatenation > https://stackoverflow.com/a/412495/995891
throws - because catch late - add a try catch if really not interested in them.
actually makes sure that the required directories exist in all cases. Not every zip contains all the required directory entries in advance of file entries. This had 2 potential bugs:
if the zip contains an empty directory and instead of the resulting directory there is an existing file, this was ignored. The return value of mkdirs() is important.
could crash on zip files that don't contain directories.
increased write buffer size, this should improve performance a bit. Storage is usually in 4k blocks and writing in smaller chunks is usually slower than necessary.
uses the magic of finally to prevent resource leaks.
So
unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));
should do the equivalent of the original
unpackZip("/sdcard/", "pictures.zip")
This is my unzip method, which I use:
private boolean unpackZip(String path, String zipname)
{
InputStream is;
ZipInputStream zis;
try
{
is = new FileInputStream(path + zipname);
zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze;
while((ze = zis.getNextEntry()) != null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
String filename = ze.getName();
FileOutputStream fout = new FileOutputStream(path + filename);
// reading and writing
while((count = zis.read(buffer)) != -1)
{
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
zis.closeEntry();
}
zis.close();
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
The Kotlin way
//FileExt.kt
data class ZipIO (val entry: ZipEntry, val output: File)
fun File.unzip(unzipLocationRoot: File? = null) {
val rootFolder = unzipLocationRoot ?: File(parentFile.absolutePath + File.separator + nameWithoutExtension)
if (!rootFolder.exists()) {
rootFolder.mkdirs()
}
ZipFile(this).use { zip ->
zip
.entries()
.asSequence()
.map {
val outputFile = File(rootFolder.absolutePath + File.separator + it.name)
ZipIO(it, outputFile)
}
.map {
it.output.parentFile?.run{
if (!exists()) mkdirs()
}
it
}
.filter { !it.entry.isDirectory }
.forEach { (entry, output) ->
zip.getInputStream(entry).use { input ->
output.outputStream().use { output ->
input.copyTo(output)
}
}
}
}
}
Usage
val zipFile = File("path_to_your_zip_file")
file.unzip()
Android has build-in Java API. Check out java.util.zip package.
The class ZipInputStream is what you should look into. Read ZipEntry from the ZipInputStream and dump it into filesystem/folder. Check similar example to compress into zip file.
use the following class
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import android.util.Log;
public class DecompressFast {
private String _zipFile;
private String _location;
public DecompressFast(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zin.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
bufout.close();
zin.closeEntry();
fout.close();
}
}
zin.close();
Log.d("Unzip", "Unzipping complete. path : " +_location );
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
Log.d("Unzip", "Unzipping failed");
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}
}
How to use
String zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip file location
String unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; // destination folder location
DecompressFast df= new DecompressFast(zipFile, unzipLocation);
df.unzip();
Permissions
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
While the answers that are already here work well, I found that they were slightly slower than I had hoped for. Instead I used zip4j, which I think is the best solution because of its speed. It also allowed for different options for the amount of compression, which I found useful.
According to #zapl answer,Unzip with progress report:
public interface UnzipFile_Progress
{
void Progress(int percent, String FileName);
}
// unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));
public static void UnzipFile(File zipFile, File targetDirectory, UnzipFile_Progress progress) throws IOException,
FileNotFoundException
{
long total_len = zipFile.length();
long total_installed_len = 0;
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
try
{
ZipEntry ze;
int count;
byte[] buffer = new byte[1024];
while ((ze = zis.getNextEntry()) != null)
{
if (progress != null)
{
total_installed_len += ze.getCompressedSize();
String file_name = ze.getName();
int percent = (int)(total_installed_len * 100 / total_len);
progress.Progress(percent, file_name);
}
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
if (ze.isDirectory())
continue;
FileOutputStream fout = new FileOutputStream(file);
try
{
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
} finally
{
fout.close();
}
// if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
}
} finally
{
zis.close();
}
}
public class MainActivity extends Activity {
private String LOG_TAG = MainActivity.class.getSimpleName();
private File zipFile;
private File destination;
private TextView status;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status = (TextView) findViewById(R.id.main_status);
status.setGravity(Gravity.CENTER);
if ( initialize() ) {
zipFile = new File(destination, "BlueBoxnew.zip");
try {
Unzipper.unzip(zipFile, destination);
status.setText("Extracted to \n"+destination.getAbsolutePath());
} catch (ZipException e) {
Log.e(LOG_TAG, e.getMessage());
} catch (IOException e) {
Log.e(LOG_TAG, e.getMessage());
}
} else {
status.setText("Unable to initialize sd card.");
}
}
public boolean initialize() {
boolean result = false;
File sdCard = new File(Environment.getExternalStorageDirectory()+"/zip/");
//File sdCard = Environment.getExternalStorageDirectory();
if ( sdCard != null ) {
destination = sdCard;
if ( !destination.exists() ) {
if ( destination.mkdir() ) {
result = true;
}
} else {
result = true;
}
}
return result;
}
}
->Helper Class(Unzipper.java)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import android.util.Log;
public class Unzipper {
private static String LOG_TAG = Unzipper.class.getSimpleName();
public static void unzip(final File file, final File destination) throws ZipException, IOException {
new Thread() {
public void run() {
long START_TIME = System.currentTimeMillis();
long FINISH_TIME = 0;
long ELAPSED_TIME = 0;
try {
ZipInputStream zin = new ZipInputStream(new FileInputStream(file));
String workingDir = destination.getAbsolutePath()+"/";
byte buffer[] = new byte[4096];
int bytesRead;
ZipEntry entry = null;
while ((entry = zin.getNextEntry()) != null) {
if (entry.isDirectory()) {
File dir = new File(workingDir, entry.getName());
if (!dir.exists()) {
dir.mkdir();
}
Log.i(LOG_TAG, "[DIR] "+entry.getName());
} else {
FileOutputStream fos = new FileOutputStream(workingDir + entry.getName());
while ((bytesRead = zin.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
fos.close();
Log.i(LOG_TAG, "[FILE] "+entry.getName());
}
}
zin.close();
FINISH_TIME = System.currentTimeMillis();
ELAPSED_TIME = FINISH_TIME - START_TIME;
Log.i(LOG_TAG, "COMPLETED in "+(ELAPSED_TIME/1000)+" seconds.");
} catch (Exception e) {
Log.e(LOG_TAG, "FAILED");
}
};
}.start();
}
}
->xml layout(activity_main.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="#+id/main_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/hello_world" />
</RelativeLayout>
->permission in Menifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Here is a ZipFileIterator (like a java Iterator, but for zip files):
package ch.epfl.bbp.io;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipFileIterator implements Iterator<File> {
private byte[] buffer = new byte[1024];
private FileInputStream is;
private ZipInputStream zis;
private ZipEntry ze;
public ZipFileIterator(File file) throws FileNotFoundException {
is = new FileInputStream(file);
zis = new ZipInputStream(new BufferedInputStream(is));
}
#Override
public boolean hasNext() {
try {
return (ze = zis.getNextEntry()) != null;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
#Override
public File next() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int count;
String filename = ze.getName();
File tmpFile = File.createTempFile(filename, "tmp");
tmpFile.deleteOnExit();// TODO make it configurable
FileOutputStream fout = new FileOutputStream(tmpFile);
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
zis.closeEntry();
return tmpFile;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#Override
public void remove() {
throw new RuntimeException("not implemented");
}
public void close() {
try {
zis.close();
is.close();
} catch (IOException e) {// nope
}
}
}
Minimal example I used to unzip a specific file from my zipfile into my applications cache folder. I then read the manifest file using a different method.
private void unzipUpdateToCache() {
ZipInputStream zipIs = new ZipInputStream(context.getResources().openRawResource(R.raw.update));
ZipEntry ze = null;
try {
while ((ze = zipIs.getNextEntry()) != null) {
if (ze.getName().equals("update/manifest.json")) {
FileOutputStream fout = new FileOutputStream(context.getCacheDir().getAbsolutePath() + "/manifest.json");
byte[] buffer = new byte[1024];
int length = 0;
while ((length = zipIs.read(buffer))>0) {
fout.write(buffer, 0, length);
}
zipIs .closeEntry();
fout.close();
}
}
zipIs .close();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm working with zip files which Java's ZipFile class isn't able to handle. Java 8 apparently can't handle compression method 12 (bzip2 I believe). After trying a number of methods including zip4j (which also fails with these particular files due to another issue), I had success with Apache's commons-compress which supports additional compression methods as mentioned here.
Note that the ZipFile class below is not the one from java.util.zip.
It's actually org.apache.commons.compress.archivers.zip.ZipFile so be careful with the imports.
try (ZipFile zipFile = new ZipFile(archiveFile)) {
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
File entryDestination = new File(destination, entry.getName());
if (entry.isDirectory()) {
entryDestination.mkdirs();
} else {
entryDestination.getParentFile().mkdirs();
try (InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) {
IOUtils.copy(in, out);
}
}
}
} catch (IOException ex) {
log.debug("Error unzipping archive file: " + archiveFile, ex);
}
For Gradle:
compile 'org.apache.commons:commons-compress:1.18'
Based on zapl's answer, adding try() around Closeable's closes the streams automatically after use.
public static void unzip(File zipFile, File targetDirectory) {
try (FileInputStream fis = new FileInputStream(zipFile)) {
try (BufferedInputStream bis = new BufferedInputStream(fis)) {
try (ZipInputStream zis = new ZipInputStream(bis)) {
ZipEntry ze;
int count;
byte[] buffer = new byte[Constant.DefaultBufferSize];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
if (ze.isDirectory())
continue;
try (FileOutputStream fout = new FileOutputStream(file)) {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
}
}
}
}
} catch (Exception ex) {
//handle exception
}
}
Using Constant.DefaultBufferSize (65536) gotten from C# .NET 4 Stream.CopyTo from Jon Skeet's answer here:
https://stackoverflow.com/a/411605/1876355
I always just see posts using byte[1024] or byte[4096] buffer, never knew it can be much larger which improves performance and is still working perfectly normal.
Here is the Stream Source code:
https://referencesource.microsoft.com/#mscorlib/system/io/stream.cs
//We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
// The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
// improvement in Copy performance.
private const int _DefaultCopyBufferSize = 81920;
However, I dialed it back to 65536 which is also a multiple of 4096 just to be safe.
Password Protected Zip File
if you want to compress files with password you can take a look at this library that can zip files with password easily:
Zip:
ZipArchive zipArchive = new ZipArchive();
zipArchive.zip(targetPath,destinationPath,password);
Unzip:
ZipArchive zipArchive = new ZipArchive();
zipArchive.unzip(targetPath,destinationPath,password);
Rar:
RarArchive rarArchive = new RarArchive();
rarArchive.extractArchive(file archive, file destination);
The documentation of this library is good enough, I just added a few examples from there.
It's totally free and wrote specially for android.
Here is more concise version of #arsent solution:
fun File.unzip(to: File? = null) {
val destinationDir = to ?: File(parentFile, nameWithoutExtension)
destinationDir.mkdirs()
ZipFile(this).use { zipFile ->
zipFile
.entries()
.asSequence()
.filter { !it.isDirectory }
.forEach { zipEntry ->
val currFile = File(destinationDir, zipEntry.name)
currFile.parentFile?.mkdirs()
zipFile.getInputStream(zipEntry).use { input ->
currFile.outputStream().use { output -> input.copyTo(output) }
}
}
}
}

How to create a zip file in Java

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?
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.
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);
}
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();
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
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);
}
}
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();
}
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);
}
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");
}
}
}
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);
}
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();
}
}
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());
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:
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.
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);
}
}
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());
}
}
}
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);
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();
}

Categories

Resources