Unzip File in Android Assets - android

I put a zip file in the android assets. How do i extract the file in the android internal storage? I know how to get the file, but i don't know how to extract it. This is my code..
Util zip ;
zip = new Util();
zip.copyFileFromAsset(this, "myfile.zip", getExternalStorage()+
"/android/data/edu.binus.profile/");
Thanks for helping :D

This piece of code will help you....Just pass the zipfile location and the location where you want the extracted files to be saved to this class while making an object...and call unzip method...
public class Decompress {
private String zip;
private String loc;
public Decompress(String zipFile, String location) {
zip = zipFile;
loc = location;
dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(zip);
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(loc + ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
private void dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}
}

Based on Sreedev R solution,
I added the option to read the file from assets and use buffer:
package com.pixoneye.api.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import android.content.Context;
import android.util.Log;
public class Decompress {
private static final int BUFFER_SIZE = 1024 * 10;
private static final String TAG = "Decompress";
public static void unzipFromAssets(Context context, String zipFile, String destination) {
try {
if (destination == null || destination.length() == 0)
destination = context.getFilesDir().getAbsolutePath();
InputStream stream = context.getAssets().open(zipFile);
unzip(stream, destination);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unzip(String zipFile, String location) {
try {
FileInputStream fin = new FileInputStream(zipFile);
unzip(fin, location);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void unzip(InputStream stream, String destination) {
dirChecker(destination, "");
byte[] buffer = new byte[BUFFER_SIZE];
try {
ZipInputStream zin = new ZipInputStream(stream);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v(TAG, "Unzipping " + ze.getName());
if (ze.isDirectory()) {
dirChecker(destination, ze.getName());
} else {
File f = new File(destination, ze.getName());
if (!f.exists()) {
boolean success = f.createNewFile();
if (!success) {
Log.w(TAG, "Failed to create file " + f.getName());
continue;
}
FileOutputStream fout = new FileOutputStream(f);
int count;
while ((count = zin.read(buffer)) != -1) {
fout.write(buffer, 0, count);
}
zin.closeEntry();
fout.close();
}
}
}
zin.close();
} catch (Exception e) {
Log.e(TAG, "unzip", e);
}
}
private static void dirChecker(String destination, String dir) {
File f = new File(destination, dir);
if (!f.isDirectory()) {
boolean success = f.mkdirs();
if (!success) {
Log.w(TAG, "Failed to create folder " + f.getName());
}
}
}
}

Maybe you should try using a FileOutputStream in combination with an inputstream from the zip file. With a package file, this should work.
To quote #wordy from this question:
PackageManager pm = context.getPackageManager();
String apkFile = pm.getApplicationInfo(context.getPackageName(), 0).sourceDir;
ZipFile zipFile = new ZipFile(apkFile);
ZipEntry entry = zipFile.getEntry("assets/FILENAME");
myInput = zipFile.getInputStream(entry);
myOutput = new FileOutputStream(file);
byte[] buffer = new byte[1024*4];
int length;
int total = 0;
int counter = 1;
while ((length = myInput.read(buffer)) > 0) {
total += length;
counter++;
if (counter % 32 == 0) {
publishProgress(total);
}
myOutput.write(buffer, 0, length);
}
Looks like there may be problems with ProGuard but hopefully the code sample works for you.

I haven't tested yet,but while doing a project on OCR I came across this library,where there is method of unzipping a downloaded file from the net. The exact method for unzipping file is installZipFromAssets(String sourceFilename,File destinationDir,File destinationFile) found under this class.Hope this is what you are looking for

You can also make use of the zip4j external library that provides additional features like encryption. Also, it has functions to extract files to a particular location provided the path.

Related

Android - Unable to unzip downloaded zip file - UTFDataFormatException

I'm currently developing an android application in which I've to download a .zip archive and then unzip it. The download of the archive is done correctly. I'm able to unzip it manually directly on the phone or on my computer.
However, when I try to unzip programmatically the archive, I get a UTFDataFormatException. I tried to force the system encoding by adding :
System.setProperty("file.encoding", "UTF-8");
Or to process the names of the files :
filename = new String(ze.getName().getBytes("UTF-8"));
Did I miss something in my unzip function ?
private boolean unzip(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[4096];
int count;
while ((ze = zis.getNextEntry()) != null)
{
filename = ze.getName();
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;
}
Below the message of the exception :
java.io.UTFDataFormatException: bad byte at 72
After all, I used Zip4j library and it works very well. It's an old library which is not maintained and not callable thanks to gradle, but it fix my problem (http://www.lingala.net/zip4j/).
try
{
ZipFile zipFile = new ZipFile(sourceFile);
zipFile.extractAll(destinationPath);
}
catch (ZipException e)
{
e.printStackTrace();
}
Try this:
public static boolean unzip(String zipFile, String location) {
if (!location.endsWith("/")) {
location += "/";
}
if (!zipFile.endsWith(".zip") || !new File(location + zipFile).exists()) {
return false;
}
int size;
byte[] buffer = new byte[1024];
try {
File f = new File(location);
if (!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(location + zipFile), 1024));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = location + ze.getName();
File unzipFile = new File(path);
if (ze.isDirectory()) {
if (!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
} else {
// check for and create parent directories if they don't exist
File parentDir = unzipFile.getParentFile();
if (null != parentDir) {
if (!parentDir.isDirectory()) {
parentDir.mkdirs();
}
}
// unzip the file
FileOutputStream out = new FileOutputStream(unzipFile, false);
BufferedOutputStream fout = new BufferedOutputStream(out, 1024);
try {
while ((size = zin.read(buffer, 0, 1024)) != -1) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
} finally {
try {
fout.flush();
fout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
} finally {
try {
zin.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
Try this,
public class DecompressZip{
private static final int BUFFER_SIZE=8192;
private String _zipFile;
private String _location;
private byte[] _buffer;
/**
* Constructor.
*
* #param zipFile Fully-qualified path to .zip file
* #param location Fully-qualified path to folder where files should be written.
* Path must have a trailing slash.
*/
public DecompressZip(String zipFile, String location)
{
_zipFile = zipFile;
_location = location;
_buffer = new byte[BUFFER_SIZE];
dirChecker("");
}
public void unzip()
{
FileInputStream fin = null;
ZipInputStream zin = null;
OutputStream fout = null;
File outputDir = new File(_location);
File tmp = null;
try {
fin = new FileInputStream(_zipFile);
zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null)
{
Log.d("Decompress", "Unzipping " + ze.getName());
Log.d("Decompress", "FileSize " + ze.getSize());
Log.d("Decompress", "compressedSize " + ze.getCompressedSize());
if (ze.isDirectory())
{
dirChecker(ze.getName());
}
else
{
tmp = File.createTempFile( "decomp", ".tmp", outputDir );
fout = new BufferedOutputStream(new FileOutputStream(tmp));
DownloadFile.copyStream( zin, fout, _buffer, BUFFER_SIZE );
zin.closeEntry();
fout.close();
fout = null;
tmp.renameTo( new File(_location + ze.getName()) );
tmp = null;
}
}
zin.close();
zin = null;
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
if ( tmp != null ) { try { tmp.delete(); } catch (Exception ignore) {;} }
if ( fout != null ) { try { fout.close(); } catch (Exception ignore) {;} }
if ( zin != null ) { try { zin.closeEntry(); } catch (Exception ignore) {;} }
if ( fin != null ) { try { fin.close(); } catch (Exception ignore) {;} }
}
}
private void dirChecker(String dir)
{
File f = new File(_location + dir);
if (!f.isDirectory())
{
f.mkdirs();
}
}}
try this below code. I have done this to download zipped images.
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class MainActivity extends AppCompatActivity {
private ProgressDialog simpleWaitDialog;
private Bitmap table1,seat1,seat2,seat3,seat4,seat5,dummy;
private ImageView tableIv,seat1Iv,seat2Iv,seat3Iv,seat4Iv,seat5Iv,overlay;
File _zipFile;
InputStream _zipFileStream;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tableIv=(ImageView)findViewById(R.id.iv);
seat1Iv=(ImageView)findViewById(R.id.seat1IV);
seat2Iv=(ImageView)findViewById(R.id.seat2IV);
seat3Iv=(ImageView)findViewById(R.id.seat3IV);
seat4Iv=(ImageView)findViewById(R.id.seat4IV);
seat5Iv=(ImageView)findViewById(R.id.seat5IV);
overlay=(ImageView)findViewById(R.id.overlayIV);
///data/user/0/com.example.ayyappaboddupalli.zipperunzipper/app_zipper1/themeparts1.zip/dummy/6_player.jpg -location where files stored
ContextWrapper wrapper=new ContextWrapper(this);
File sd = wrapper.getDir("zipper1", MODE_PRIVATE);
File dest = new File(sd, "theme1.zip");
File target = new File(sd, "themeparts1.zip");
if(target.exists())
{
commonCaller(dest,target,sd);
}
else
{
new ImageDownloader().execute();
commonCaller(dest,target,sd);
}
}
private void uriToBitmap(Uri selectedFileUri, String name) {
try {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(selectedFileUri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
assignBitmapToView(image,name);
parcelFileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void assignBitmapToView(Bitmap image, String name) {
String toCompare=name.toString().substring(name.lastIndexOf("/")+1,name.lastIndexOf("."));
switch (toCompare)
{
case "dummy":
dummy=image;
overlay.setImageBitmap(dummy);
break;
case "6_player":
table1=image;
tableIv.setImageBitmap(table1);
break;
case "f1":
seat1=image;
seat1Iv.setImageBitmap(seat1);
break;
case "f2":
seat2=image;
seat2Iv.setImageBitmap(seat2);
break;
case "f3":
seat3=image;
seat3Iv.setImageBitmap(seat3);
break;
case "f4":
seat4=image;
seat4Iv.setImageBitmap(seat4);
break;
case "f5":
seat5=image;
seat5Iv.setImageBitmap(seat5);
break;
}
}
public void commonCaller(File dest,File target,File sd)
{
if(sd.exists()) {
// unzip(dest.getAbsolutePath(), target.getAbsolutePath());
try {
unzipFileIntoDirectory(dest,target);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*public void unzip(String _zipFile, String _targetLocation) {
//create target location folder if not exist
_dirChecker(_zipFile);
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
//create dir if required while unzipping
if (ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_targetLocation + ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
} catch (Exception e) {
System.out.println(e);
}
}*/
public void unzip() {
try {
ContextWrapper cws=new ContextWrapper(this);
File sd=cws.getDir("zipper1",MODE_PRIVATE);
File dest=new File(sd,"parts1");
dest.mkdirs();
// final String ROOT_LOCATION = "/sdcard";
Log.i("", "Starting to unzip");
InputStream fin = _zipFileStream;
if(fin == null) {
fin = new FileInputStream(_zipFile);
}
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(dest + "/" + ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(new File(sd.getPath(), ze.getName()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
// reading and writing
while((count = zin.read(buffer)) != -1)
{
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
zin.closeEntry();
}
}
zin.close();
Log.i("", "Finished unzip");
} catch(Exception e) {
Log.e("", "Unzip Error", e);
}
}
public void unzipFileIntoDirectory(File archive, File destinationDir)
throws Exception {
final int BUFFER_SIZE = 1024;
BufferedOutputStream dest = null;
FileInputStream fis = new FileInputStream(archive);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
File destFile;
while ((entry = zis.getNextEntry()) != null) {
destFile=new File(destinationDir,entry.getName());
uriToBitmap(Uri.fromFile(destFile),entry.getName());
// destFile = FilesystemUtils.combineFileNames(destinationDir, entry.getName());
if (entry.isDirectory()) {
destFile.mkdirs();
continue;
} else {
int count;
byte data[] = new byte[BUFFER_SIZE];
destFile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(destFile);
dest = new BufferedOutputStream(fos, BUFFER_SIZE);
while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
fos.close();
}
}
zis.close();
fis.close();
}
private void _dirChecker(String dir) {
File f = new File(dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}
private class ImageDownloader extends AsyncTask {
#Override
protected Object doInBackground(Object[] params) {
String url="testing/dummy.zip";
return downloadBitmap(url);
}
#Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
simpleWaitDialog = new ProgressDialog(MainActivity.this);
simpleWaitDialog.setMessage( "Downloading Image");
simpleWaitDialog.show();
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
simpleWaitDialog.dismiss();
}
private Bitmap downloadBitmap(String url) {
downloadImage(url);
return null;
}
}
public void downloadImage(String urlPart) {
URL url = null;
FileDescriptor fd;
try {
int count;
url = new URL(urlPart);
InputStream input = new BufferedInputStream(url.openStream());
ContextWrapper contextWrapper=new ContextWrapper(this);
File sd = contextWrapper.getDir("zipper1", MODE_PRIVATE);
File dest = new File(sd, "theme1.zip");
_zipFileStream=input;
// File file = new File(downloadLocation);
FileOutputStream output = new FileOutputStream(dest); //context.openFileOutput("content.zip", Context.MODE_PRIVATE);
fd = output.getFD();
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"success",Toast.LENGTH_LONG).show();
}
});
//old code
/* ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
String zipString = Base64.encodeToString(response, Base64.DEFAULT);
ContextWrapper contextWrapper=new ContextWrapper(this);
File sd = contextWrapper.getDir("zipper1", MODE_PRIVATE);
File dest = new File(sd, "theme1.zip");
FileOutputStream fos = new FileOutputStream(dest);
fos.write(zipString.getBytes());
fos.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"success",Toast.LENGTH_LONG).show();
}
});*/
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Unzip file in Android

I got following error when i try to unzip zip file
End-of-central-directory signature not found
I have also try 7zip lib, it works fine in simple java but in android platform.
I get a "dependent jar not found" error.
try {
// Initiate the ZipFile
ZipFile zipFile = new ZipFile(file);
String destinationPath = destPath;
// If zip file is password protected then set the password
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
//Get a list of FileHeader. FileHeader is the header information for all the
//files in the ZipFile
List fileHeaderList = zipFile.getFileHeaders();
// Loop through all the fileHeaders
for (int i = 0; i < fileHeaderList.size(); i++) {
FileHeader fileHeader = (FileHeader)fileHeaderList.get(i);
if (fileHeader != null) {
//Build the output file
String outFilePath = destinationPath + System.getProperty("file.separator") + fileHeader.getFileName();
File outFile = new File(outFilePath);
//Checks if the file is a directory
if (fileHeader.isDirectory()) {
//This functionality is up to your requirements
//For now I create the directory
outFile.mkdirs();
continue;
}
//Check if the directories(including parent directories)
//in the output file path exists
File parentDir = outFile.getParentFile();
if (!parentDir.exists()) {
parentDir.mkdirs();
}
//Get the InputStream from the ZipFile
is = zipFile.getInputStream(fileHeader);
//Initialize the output stream
os = new FileOutputStream(outFile);
int readLen = -1;
byte[] buff = new byte[BUFF_SIZE];
//Loop until End of File and write the contents to the output stream
while ((readLen = is.read(buff)) != -1) {
os.write(buff, 0, readLen);
}
//Please have a look into this method for some important comments
closeFileHandlers(is, os);
//To restore File attributes (ex: last modified file time,
//read only flag, etc) of the extracted file, a utility class
//can be used as shown below
UnzipUtil.applyFileAttributes(fileHeader, outFile);
System.out.println("Done extracting: " + fileHeader.getFileName());
} else {
System.err.println("fileheader is null. Shouldn't be here");
}
//File header always give error
You don't need 3rd party libraries when unzipping files in Android. Have a look at this:
http://www.jondev.net/articles/Unzipping_Files_with_Android_%28Programmatically%29
Its never too late i guess, using above caner unzipping is really too slow so i modified it
use following below class
package com.example.epubdemo;
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();
}
}
}
USAGE
// save zip file in your internal storage directly not in any sub folder( if using any sub folder give below path correctly)
String zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip name
String unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; //your unzip directory name
DecompressFast df= new DecompressFast(zipFile, unzipLocation);
df.unzip();
DONT FORGET TO GIVE READ AND WRITE PERMISSIONS
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

How to zip and unzip the files?

How to zip and unzip the files which are all already in DDMS : data/data/mypackage/files/ I need a simple example for that. I've already search related to zip and unzip. But, no one example available for me. Can anyone tell some example. Advance Thanks.
Take a look at java.util.zip.* classes for zip functionality. I've done some basic zip/unzip code, which I've pasted below. Hope it helps.
public static void zip(String[] files, String zipFile) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(files[i]);
origin = new BufferedInputStream(fi, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(files[i].substring(files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
}
finally {
out.close();
}
}
public static void unzip(String zipFile, String location) throws IOException {
try {
File f = new File(location);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = location + ze.getName();
if (ze.isDirectory()) {
File unzipFile = new File(path);
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
}
else {
FileOutputStream fout = new FileOutputStream(path, false);
try {
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
}
finally {
fout.close();
}
}
}
}
finally {
zin.close();
}
}
catch (Exception e) {
Log.e(TAG, "Unzip exception", e);
}
}
The zip function brianestey provided works well, but the unzip function is very slow due to reading one byte at a time. Here is a modified version of his unzip function that utilizes a buffer and is much faster.
/**
* Unzip a zip file. Will overwrite existing files.
*
* #param zipFile Full path of the zip file you'd like to unzip.
* #param location Full path of the directory you'd like to unzip to (will be created if it doesn't exist).
* #throws IOException
*/
public static void unzip(String zipFile, String location) throws IOException {
int size;
byte[] buffer = new byte[BUFFER_SIZE];
try {
if ( !location.endsWith(File.separator) ) {
location += File.separator;
}
File f = new File(location);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile), BUFFER_SIZE));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = location + ze.getName();
File unzipFile = new File(path);
if (ze.isDirectory()) {
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
} else {
// check for and create parent directories if they don't exist
File parentDir = unzipFile.getParentFile();
if ( null != parentDir ) {
if ( !parentDir.isDirectory() ) {
parentDir.mkdirs();
}
}
// unzip the file
FileOutputStream out = new FileOutputStream(unzipFile, false);
BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
try {
while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
}
finally {
fout.flush();
fout.close();
}
}
}
}
finally {
zin.close();
}
}
catch (Exception e) {
Log.e(TAG, "Unzip exception", e);
}
}
Using File instead of the file path String.
This answer is based off of #brianestey's excellent answer.
I have modified his zip method to accept a list of Files instead of file paths and an output zip File instead of a filepath, which might be helpful to others if that's what they're dealing with.
public static void zip( List<File> files, File zipFile ) throws IOException {
final int BUFFER_SIZE = 2048;
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for ( File file : files ) {
FileInputStream fileInputStream = new FileInputStream( file );
origin = new BufferedInputStream(fileInputStream, BUFFER_SIZE);
String filePath = file.getAbsolutePath();
try {
ZipEntry entry = new ZipEntry( filePath.substring( filePath.lastIndexOf("/") + 1 ) );
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
}
finally {
out.close();
}
}
This answer is based of brianestey, Ben, Giacomo Mattiuzzi, Joshua Pinter.
Functions rewritten to Kotlin and added functions for working with Uri.
import android.content.Context
import android.net.Uri
import java.io.*
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
private const val MODE_WRITE = "w"
private const val MODE_READ = "r"
fun zip(zipFile: File, files: List<File>) {
ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile))).use { outStream ->
zip(outStream, files)
}
}
fun zip(context: Context, zipFile: Uri, files: List<File>) {
context.contentResolver.openFileDescriptor(zipFile, MODE_WRITE).use { descriptor ->
descriptor?.fileDescriptor?.let {
ZipOutputStream(BufferedOutputStream(FileOutputStream(it))).use { outStream ->
zip(outStream, files)
}
}
}
}
private fun zip(outStream: ZipOutputStream, files: List<File>) {
files.forEach { file ->
outStream.putNextEntry(ZipEntry(file.name))
BufferedInputStream(FileInputStream(file)).use { inStream ->
inStream.copyTo(outStream)
}
}
}
fun unzip(zipFile: File, location: File) {
ZipInputStream(BufferedInputStream(FileInputStream(zipFile))).use { inStream ->
unzip(inStream, location)
}
}
fun unzip(context: Context, zipFile: Uri, location: File) {
context.contentResolver.openFileDescriptor(zipFile, MODE_READ).use { descriptor ->
descriptor?.fileDescriptor?.let {
ZipInputStream(BufferedInputStream(FileInputStream(it))).use { inStream ->
unzip(inStream, location)
}
}
}
}
private fun unzip(inStream: ZipInputStream, location: File) {
if (location.exists() && !location.isDirectory)
throw IllegalStateException("Location file must be directory or not exist")
if (!location.isDirectory) location.mkdirs()
val locationPath = location.absolutePath.let {
if (!it.endsWith(File.separator)) "$it${File.separator}"
else it
}
var zipEntry: ZipEntry?
var unzipFile: File
var unzipParentDir: File?
while (inStream.nextEntry.also { zipEntry = it } != null) {
unzipFile = File(locationPath + zipEntry!!.name)
if (zipEntry!!.isDirectory) {
if (!unzipFile.isDirectory) unzipFile.mkdirs()
} else {
unzipParentDir = unzipFile.parentFile
if (unzipParentDir != null && !unzipParentDir.isDirectory) {
unzipParentDir.mkdirs()
}
BufferedOutputStream(FileOutputStream(unzipFile)).use { outStream ->
inStream.copyTo(outStream)
}
}
}
}

How to copy files from 'assets' folder to sdcard?

I have a few files in the assets folder. I need to copy all of them to a folder say /sdcard/folder. I want to do this from within a thread. How do I do it?
If anyone else is having the same problem, this is how I did it
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);
}
if (files != null) 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);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
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);
}
}
Reference : Move file using Java
Based on your solution, I did something of my own to allow subfolders. Someone might find this helpful:
...
copyFileOrDir("myrootdir");
...
private void copyFileOrDir(String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path);
} else {
String fullPath = "/data/data/" + this.getPackageName() + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
dir.mkdir();
for (int i = 0; i < assets.length; ++i) {
copyFileOrDir(path + "/" + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String filename) {
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
String newFileName = "/data/data/" + this.getPackageName() + "/" + filename;
out = new FileOutputStream(newFileName);
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;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
The solution above did not work due to some errors:
directory creation did not work
assets returned by Android contain also three folders: images, sounds and webkit
Added way to deal with large files: Add extension .mp3 to the file in the assets folder in your project and during copy the target file will be without the .mp3 extension
Here is the code (I left the Log statements but you can drop them now):
final static String TARGET_BASE_PATH = "/sdcard/appname/voices/";
private void copyFilesToSdCard() {
copyFileOrDir(""); // copy all files in assets folder in my project
}
private void copyFileOrDir(String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
Log.i("tag", "copyFileOrDir() "+path);
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path);
} else {
String fullPath = TARGET_BASE_PATH + path;
Log.i("tag", "path="+fullPath);
File dir = new File(fullPath);
if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
if (!dir.mkdirs())
Log.i("tag", "could not create dir "+fullPath);
for (int i = 0; i < assets.length; ++i) {
String p;
if (path.equals(""))
p = "";
else
p = path + "/";
if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
copyFileOrDir( p + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String filename) {
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
String newFileName = null;
try {
Log.i("tag", "copyFile() "+filename);
in = assetManager.open(filename);
if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
newFileName = TARGET_BASE_PATH + filename.substring(0, filename.length()-4);
else
newFileName = TARGET_BASE_PATH + filename;
out = new FileOutputStream(newFileName);
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;
} catch (Exception e) {
Log.e("tag", "Exception in copyFile() of "+newFileName);
Log.e("tag", "Exception in copyFile() "+e.toString());
}
}
EDIT: Corrected a misplaced ";" that was throwing a systematic "could not create dir" error.
I know this has been answered but I have a slightly more elegant way to copy from asset directory to a file on the sdcard. It requires no "for" loop but instead uses File Streams and Channels to do the work.
(Note) If using any type of compressed file, APK, PDF, ... you may want to rename the file extension before inserting into asset and then rename once you copy it to SDcard)
AssetManager am = context.getAssets();
AssetFileDescriptor afd = null;
try {
afd = am.openFd( "MyFile.dat");
// Create new file to copy into.
File file = new File(Environment.getExternalStorageDirectory() + java.io.File.separator + "NewFile.dat");
file.createNewFile();
copyFdToFile(afd.getFileDescriptor(), file);
} catch (IOException e) {
e.printStackTrace();
}
A way to copy a file without having to loop through it.
public static void copyFdToFile(FileDescriptor src, File dst) throws IOException {
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
}
}
This would be concise way in Kotlin.
fun AssetManager.copyRecursively(assetPath: String, targetFile: File) {
val list = list(assetPath)
if (list.isEmpty()) { // assetPath is file
open(assetPath).use { input ->
FileOutputStream(targetFile.absolutePath).use { output ->
input.copyTo(output)
output.flush()
}
}
} else { // assetPath is folder
targetFile.delete()
targetFile.mkdir()
list.forEach {
copyRecursively("$assetPath/$it", File(targetFile, it))
}
}
}
try out this it is much simpler ,this will help u:
// Open your local db as the input stream
InputStream myInput = _context.getAssets().open(YOUR FILE NAME);
// Path to the just created empty db
String outFileName =SDCARD PATH + YOUR FILE NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Here is a cleaned up version for current Android devices, functional method design so that you can copy it to an AssetsHelper class e.g ;)
/**
*
* Info: prior to Android 2.3, any compressed asset file with an
* uncompressed size of over 1 MB cannot be read from the APK. So this
* should only be used if the device has android 2.3 or later running!
*
* #param c
* #param targetFolder
* e.g. {#link Environment#getExternalStorageDirectory()}
* #throws Exception
*/
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static boolean copyAssets(AssetManager assetManager,
File targetFolder) throws Exception {
Log.i(LOG_TAG, "Copying files from assets to folder " + targetFolder);
return copyAssets(assetManager, "", targetFolder);
}
/**
* The files will be copied at the location targetFolder+path so if you
* enter path="abc" and targetfolder="sdcard" the files will be located in
* "sdcard/abc"
*
* #param assetManager
* #param path
* #param targetFolder
* #return
* #throws Exception
*/
public static boolean copyAssets(AssetManager assetManager, String path,
File targetFolder) throws Exception {
Log.i(LOG_TAG, "Copying " + path + " to " + targetFolder);
String sources[] = assetManager.list(path);
if (sources.length == 0) { // its not a folder, so its a file:
copyAssetFileToFolder(assetManager, path, targetFolder);
} else { // its a folder:
if (path.startsWith("images") || path.startsWith("sounds")
|| path.startsWith("webkit")) {
Log.i(LOG_TAG, " > Skipping " + path);
return false;
}
File targetDir = new File(targetFolder, path);
targetDir.mkdirs();
for (String source : sources) {
String fullSourcePath = path.equals("") ? source : (path
+ File.separator + source);
copyAssets(assetManager, fullSourcePath, targetFolder);
}
}
return true;
}
private static void copyAssetFileToFolder(AssetManager assetManager,
String fullAssetPath, File targetBasePath) throws IOException {
InputStream in = assetManager.open(fullAssetPath);
OutputStream out = new FileOutputStream(new File(targetBasePath,
fullAssetPath));
byte[] buffer = new byte[16 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
}
Modified this SO answer by #DannyA
private void copyAssets(String path, String outPath) {
AssetManager assetManager = this.getAssets();
String assets[];
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path, outPath);
} else {
String fullPath = outPath + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
if (!dir.mkdir()) Log.e(TAG, "No create external directory: " + dir );
for (String asset : assets) {
copyAssets(path + "/" + asset, outPath);
}
}
} catch (IOException ex) {
Log.e(TAG, "I/O Exception", ex);
}
}
private void copyFile(String filename, String outPath) {
AssetManager assetManager = this.getAssets();
InputStream in;
OutputStream out;
try {
in = assetManager.open(filename);
String newFileName = outPath + "/" + filename;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
Preparations
in src/main/assets
add folder with name fold
Usage
File outDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
copyAssets("fold",outDir.toString());
In to the external directory find all files and directories that are within the fold assets
Using some of the concepts in the answers to this question, I wrote up a class called AssetCopier to make copying /assets/ simple. It's available on github and can be accessed with jitpack.io:
new AssetCopier(MainActivity.this)
.withFileScanning()
.copy("tocopy", destDir);
See https://github.com/flipagram/android-assetcopier for more details.
Copy all files and directories from assets to your folder!
for copying better use apache commons io
public void doCopyAssets() throws IOException {
File externalFilesDir = context.getExternalFilesDir(null);
doCopy("", externalFilesDir.getPath());
}
//THIS IS MAIN METHOD FOR COPY
private void doCopy(String dirName, String outPath) throws IOException {
String[] srcFiles = assets.list(dirName);//for directory
for (String srcFileName : srcFiles) {
String outFileName = outPath + File.separator + srcFileName;
String inFileName = dirName + File.separator + srcFileName;
if (dirName.equals("")) {// for first time
inFileName = srcFileName;
}
try {
InputStream inputStream = assets.open(inFileName);
copyAndClose(inputStream, new FileOutputStream(outFileName));
} catch (IOException e) {//if directory fails exception
new File(outFileName).mkdir();
doCopy(inFileName, outFileName);
}
}
}
public static void closeQuietly(AutoCloseable autoCloseable) {
try {
if(autoCloseable != null) {
autoCloseable.close();
}
} catch(IOException ioe) {
//skip
}
}
public static void copyAndClose(InputStream input, OutputStream output) throws IOException {
copy(input, output);
closeQuietly(input);
closeQuietly(output);
}
public static void copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int n = 0;
while(-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
}
Based on Rohith Nandakumar's solution, I did something of my own to copy files from a subfolder of assets (i.e. "assets/MyFolder"). Also, I'm checking if the file already exists in sdcard before trying to copy again.
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("MyFolder");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open("MyFolder/"+filename);
File outFile = new File(getExternalFilesDir(null), filename);
if (!(outFile.exists())) {// File does not exist...
out = new FileOutputStream(outFile);
copyFile(in, out);
}
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
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);
}
}
Based on Yoram Cohen answer, here is a version that supports non static target directory.
Invoque with copyFileOrDir(getDataDir(), "") to write to internal app storage folder /data/data/pkg_name/
Supports subfolders.
Supports custom and non-static target directory
Avoids copying "images" etc fake asset folders like
private void copyFileOrDir(String TARGET_BASE_PATH, String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
Log.i("tag", "copyFileOrDir() "+path);
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(TARGET_BASE_PATH, path);
} else {
String fullPath = TARGET_BASE_PATH + "/" + path;
Log.i("tag", "path="+fullPath);
File dir = new File(fullPath);
if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
if (!dir.mkdirs())
Log.i("tag", "could not create dir "+fullPath);
for (int i = 0; i < assets.length; ++i) {
String p;
if (path.equals(""))
p = "";
else
p = path + "/";
if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
copyFileOrDir(TARGET_BASE_PATH, p + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String TARGET_BASE_PATH, String filename) {
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
String newFileName = null;
try {
Log.i("tag", "copyFile() "+filename);
in = assetManager.open(filename);
if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
newFileName = TARGET_BASE_PATH + "/" + filename.substring(0, filename.length()-4);
else
newFileName = TARGET_BASE_PATH + "/" + filename;
out = new FileOutputStream(newFileName);
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;
} catch (Exception e) {
Log.e("tag", "Exception in copyFile() of "+newFileName);
Log.e("tag", "Exception in copyFile() "+e.toString());
}
}
You can do it in few steps using Kotlin, Here I am copying only few files instead of all from asstes to my apps files directory.
private fun copyRelatedAssets() {
val assets = arrayOf("myhome.html", "support.css", "myscript.js", "style.css")
assets.forEach {
val inputStream = requireContext().assets.open(it)
val nameSplit = it.split(".")
val name = nameSplit[0]
val extension = nameSplit[1]
val path = inputStream.getFilePath(requireContext().filesDir, name, extension)
Log.v(TAG, path)
}
}
And here is the extension function,
fun InputStream.getFilePath(dir: File, name: String, extension: String): String {
val file = File(dir, "$name.$extension")
val outputStream = FileOutputStream(file)
this.copyTo(outputStream, 4096)
return file.absolutePath
}
LOGCAT
/data/user/0/com.***.***/files/myhome.html
/data/user/0/com.***.***/files/support.css
/data/user/0/com.***.***/files/myscript.js
/data/user/0/com.***.***/files/style.css
There are essentially two ways to do this.
First, you can use AssetManager.open and, as described by Rohith Nandakumar and iterate over the inputstream.
Second, you can use AssetManager.openFd, which allows you to use a FileChannel (which has the transferTo and transferFrom methods), so you don't have to loop over the input stream yourself.
I will describe the openFd method here.
Compression
First you need to ensure that the file is stored uncompressed. The packaging system may choose to compress any file with an extension that is not marked as noCompress, and compressed files cannot be memory mapped, so you will have to rely on AssetManager.open in that case.
You can add a '.mp3' extension to your file to stop it from being compressed, but the proper solution is to modify your app/build.gradle file and add the following lines (to disable compression of PDF files)
aaptOptions {
noCompress 'pdf'
}
File packing
Note that the packager can still pack multiple files into one, so you can't just read the whole file the AssetManager gives you. You need to to ask the AssetFileDescriptor which parts you need.
Finding the correct part of the packed file
Once you've ensured your file is stored uncompressed, you can use the AssetManager.openFd method to obtain an AssetFileDescriptor, which can be used to obtain a FileInputStream (unlike AssetManager.open, which returns an InputStream) that contains a FileChannel. It also contains the starting offset (getStartOffset) and size (getLength), which you need to obtain the correct part of the file.
Implementation
An example implementation is given below:
private void copyFileFromAssets(String in_filename, File out_file){
Log.d("copyFileFromAssets", "Copying file '"+in_filename+"' to '"+out_file.toString()+"'");
AssetManager assetManager = getApplicationContext().getAssets();
FileChannel in_chan = null, out_chan = null;
try {
AssetFileDescriptor in_afd = assetManager.openFd(in_filename);
FileInputStream in_stream = in_afd.createInputStream();
in_chan = in_stream.getChannel();
Log.d("copyFileFromAssets", "Asset space in file: start = "+in_afd.getStartOffset()+", length = "+in_afd.getLength());
FileOutputStream out_stream = new FileOutputStream(out_file);
out_chan = out_stream.getChannel();
in_chan.transferTo(in_afd.getStartOffset(), in_afd.getLength(), out_chan);
} catch (IOException ioe){
Log.w("copyFileFromAssets", "Failed to copy file '"+in_filename+"' to external storage:"+ioe.toString());
} finally {
try {
if (in_chan != null) {
in_chan.close();
}
if (out_chan != null) {
out_chan.close();
}
} catch (IOException ioe){}
}
}
This answer is based on JPM's answer.
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
copyReadAssets();
}
private void copyReadAssets()
{
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
File fileDir = new File(strDir);
fileDir.mkdirs(); // crear la ruta si no existe
File file = new File(fileDir, "example2.pdf");
try
{
in = assetManager.open("example.pdf"); //leer el archivo de assets
out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");
startActivity(intent);
}
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);
}
}
}
change parts of code like these:
out = new BufferedOutputStream(new FileOutputStream(file));
the before example is for Pdfs, in case of to example .txt
FileOutputStream fos = new FileOutputStream(file);
Hi Guys I Did Something like this.
For N-th Depth Copy Folder and Files to copy.
Which Allows you to copy all the directory structure to copy from Android AssetManager :)
private void manageAssetFolderToSDcard()
{
try
{
String arg_assetDir = getApplicationContext().getPackageName();
String arg_destinationDir = FRConstants.ANDROID_DATA + arg_assetDir;
File FolderInCache = new File(arg_destinationDir);
if (!FolderInCache.exists())
{
copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);
}
} catch (IOException e1)
{
e1.printStackTrace();
}
}
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");
}
}
}
In the end Create a Asynctask:
private class ManageAssetFolders extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
manageAssetFolderToSDcard();
return null;
}
}
call it From your activity:
new ManageAssetFolders().execute();
Slight modification of above answer to copy a folder recursively and to accommodate custom destination.
public void copyFileOrDir(String path, String destinationDir) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path,destinationDir);
} else {
String fullPath = destinationDir + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
dir.mkdir();
for (int i = 0; i < assets.length; ++i) {
copyFileOrDir(path + "/" + assets[i], destinationDir + path + "/" + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String filename, String destinationDir) {
AssetManager assetManager = this.getAssets();
String newFileName = destinationDir + "/" + filename;
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
out = new FileOutputStream(newFileName);
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;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
new File(newFileName).setExecutable(true, false);
}
For those who are updating to Kotlin:
Following this steps to avoid FileUriExposedExceptions,
supposing user has granted WRITE_EXTERNAL_STORAGE permission and your file is in assets/pdfs/mypdf.pdf.
private fun openFile() {
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
try {
val file = File("${activity.getExternalFilesDir(null)}/$PDF_FILE_NAME")
if (!file.exists()) {
inputStream = activity.assets.open("$PDF_ASSETS_PATH/$PDF_FILE_NAME")
outputStream = FileOutputStream(file)
copyFile(inputStream, outputStream)
}
val uri = FileProvider.getUriForFile(
activity,
"${BuildConfig.APPLICATION_ID}.provider.GenericFileProvider",
file
)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/pdf")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
activity.startActivity(intent)
} catch (ex: IOException) {
ex.printStackTrace()
} catch (ex: ActivityNotFoundException) {
ex.printStackTrace()
} finally {
inputStream?.close()
outputStream?.flush()
outputStream?.close()
}
}
#Throws(IOException::class)
private fun copyFile(input: InputStream, output: OutputStream) {
val buffer = ByteArray(1024)
var read: Int = input.read(buffer)
while (read != -1) {
output.write(buffer, 0, read)
read = input.read(buffer)
}
}
companion object {
private const val PDF_ASSETS_PATH = "pdfs"
private const val PDF_FILE_NAME = "mypdf.pdf"
}
That is my personalized text extractor class, hope that will be usefull.
package lorenzo.morelli.platedetector;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import com.googlecode.tesseract.android.TessBaseAPI;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TextExtractor {
private final Context context;
private final String dirName;
private final String language;
public TextExtractor(final Context context, final String dirName, final String language) {
this.context = context;
this.dirName = dirName;
this.language = language;
}
public String extractText(final Bitmap bitmap) {
final TessBaseAPI tessBaseApi = new TessBaseAPI();
final String datapath = this.context.getFilesDir()+ "/tesseract/";
checkFile(new File(datapath + this.dirName + "/"), datapath, this.dirName, this.language);
tessBaseApi.init(datapath, this.language);
tessBaseApi.setImage(bitmap);
final String extractedText = tessBaseApi.getUTF8Text();
tessBaseApi.end();
return extractedText;
}
private void checkFile(final File dir, final String datapath, final String dirName, final String language) {
//directory does not exist, but we can successfully create it
if (!dir.exists()&& dir.mkdirs()) {
copyFiles(datapath, dirName, language);
} //The directory exists, but there is no data file in it
if(dir.exists()) {
final String datafilepath = datapath + "/" + dirName + "/" + language + ".traineddata";
final File datafile = new File(datafilepath);
if (!datafile.exists()) {
copyFiles(datapath, dirName, language);
}
}
}
private void copyFiles(final String datapath, final String dirName, final String language) {
try {
//location we want the file to be at
final String filepath = datapath + "/" + dirName + "/" + language + ".traineddata";
//get access to AssetManager
final AssetManager assetManager = this.context.getAssets();
//open byte streams for reading/writing
final InputStream instream = assetManager.open(dirName + "/" + language + ".traineddata");
final OutputStream outstream = new FileOutputStream(filepath);
//copy the file to the location specified by filepath
byte[] buffer = new byte[1024];
int read;
while ((read = instream.read(buffer)) != -1) {
outstream.write(buffer, 0, read);
}
outstream.flush();
outstream.close();
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
To use that you need traineddata file. You can download trainddata file from this link.
Once you’ve downloaded the traineddata file you want, you need to make an Android Resource directory named assets in your android project. In the newly created assets folder, you need to create a regular directory named “tessdata” where you can place your traineddata files.
Finally you have to init the "TextExtractor" class in your MainActivity.
final TextExtractor textExtractor = new TextExtractor(this, "tessdata", "eng");
First parameter is the context, the second one is the name of directory just created and the last one is the language of traineddata just downloaded.
To extract text you have to call the "extractText" method:
final String text = textExtractor.extractText(imageWithText);
Note that extractText need a BitMap image to work!!
You can create a BitMap image from your drawable file with this line:
final BitMap image = BitmapFactory.decodeResource(getResources(), R.drawable.test_image);
If you need more support, I suggest you to follow this usefull guide: https://github.com/SamVanRoy/Android_OCR_App
In Kotlin it can be done with one line!
Add extension fun to InputStream
fun InputStream.toFile(to: File){
this.use { input->
to.outputStream().use { out->
input.copyTo(out)
}
}
}
then use it
MainActivity.kt
assets.open("test.zip").toFile(File(filesDir,"test.zip"))
This is by far the best solution I have been able to find on the internet.
I've used the following link https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217, but it had a single error which I fixed and then it works like a charm.
Here's my code. You can easily use it as it is an independent java class.
public class CopyAssets {
public static void copyAssets(Context context) {
AssetManager assetManager = context.getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
out = new FileOutputStream(Environment.getExternalStorageDirectory()+"/www/resources/" + filename);
copyFile(in, out);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
in = null;
} catch (IOException e) {
}
}
if (out != null) {
try {
out.flush();
out.close();
out = null;
} catch (IOException e) {
}
}
}
}
}
public static 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);
}
}}
As you can see, just create an instance of CopyAssets in your java class which has an activity. Now this part is important, as far as my testing and researching on the internet, You cannot use AssetManager if the class has no activity . It has something to do with the context of the java class.
Now, the c.copyAssets(getApplicationContext()) is an easy way to access the method, where c is and instance of CopyAssets class.
As per my requirement, I allowed the program to copy all my resource files inside the asset folder to the /www/resources/ of my internal directory.
You can easily find out the part where you need to make changes to the directory as per your use.
Feel free to ping me if you need any help.
You can also use Guava's ByteStream to copy the files from the assets folder to the SD card. This is the solution I ended up with which copies files recursively from the assets folder to the SD card:
/**
* Copies all assets in an assets directory to the SD file system.
*/
public class CopyAssetsToSDHelper {
public static void copyAssets(String assetDir, String targetDir, Context context)
throws IOException {
AssetManager assets = context.getAssets();
String[] list = assets.list(assetDir);
for (String f : Objects.requireNonNull(list)) {
if (f.indexOf(".") > 1) { // check, if this is a file
File outFile = new File(context.getExternalFilesDir(null),
String.format("%s/%s", targetDir, f));
File parentFile = outFile.getParentFile();
if (!Objects.requireNonNull(parentFile).exists()) {
if (!parentFile.mkdirs()) {
throw new IOException(String.format("Could not create directory %s.",
parentFile));
}
}
try (InputStream fin = assets.open(String.format("%s/%s", assetDir, f));
OutputStream fout = new FileOutputStream(outFile)) {
ByteStreams.copy(fin, fout);
}
} else { // This is a directory
copyAssets(String.format("%s/%s", assetDir, f), String.format("%s/%s", targetDir, f),
context);
}
}
}
}
Use AssetManager, it allows to read the files in the assets. Then use regular Java IO to write the files to sdcard.
Google is your friend, search for an example.

File operation in android

I am new to android platform. I need to create a text file in android. Please let me know how to perform this task in android. I have written a code that is working fine in java but not in android. Please help me on this....the sample code that ihave written is :-
try
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("test.txt", true));
dos.writeBytes(dataLine);
dos.close();
}
catch (FileNotFoundException ex) {}
the above code snippet is working fine in java but not in android :(
Thanks,
Ashish
The Android Dev Guide explains it nicely:
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
If you want the files you create to be visible to the outside world, use external storage. But as I said in the comment, make sure you're "being a good citizen". These files stick around even after the user uninstalls your app.
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
/**
* Static methods used for common file operations.
*
* #author Carl Hartung (carlhartung#gmail.com)
*/
public class FileUtils {
private final static String t = "FileUtils";
// Used to validate and display valid form names.
public static final String VALID_FILENAME = "[ _\\-A-Za-z0-9]*.x[ht]*ml";
// Storage paths
public static final String FORMS_PATH = Environment.getExternalStorageDirectory() + "/odk/forms/";
public static final String INSTANCES_PATH = Environment.getExternalStorageDirectory() + "/odk/instances/";
public static final String CACHE_PATH = Environment.getExternalStorageDirectory() + "/odk/.cache/";
public static final String TMPFILE_PATH = CACHE_PATH + "tmp.jpg";
public static ArrayList<String> getValidFormsAsArrayList(String path) {
ArrayList<String> formPaths = new ArrayList<String>();
File dir = new File(path);
if (!storageReady()) {
return null;
}
if (!dir.exists()) {
if (!createFolder(path)) {
return null;
}
}
File[] dirs = dir.listFiles();
for (int i = 0; i < dirs.length; i++) {
// skip all the directories
if (dirs[i].isDirectory())
continue;
String formName = dirs[i].getName();
formPaths.add(dirs[i].getAbsolutePath());
}
return formPaths;
}
public static ArrayList<String> getFoldersAsArrayList(String path) {
ArrayList<String> mFolderList = new ArrayList<String>();
File root = new File(path);
if (!storageReady()) {
return null;
}
if (!root.exists()) {
if (!createFolder(path)) {
return null;
}
}
if (root.isDirectory()) {
File[] children = root.listFiles();
for (File child : children) {
boolean directory = child.isDirectory();
if (directory) {
mFolderList.add(child.getAbsolutePath());
}
}
}
return mFolderList;
}
public static boolean deleteFolder(String path) {
// not recursive
if (path != null && storageReady()) {
File dir = new File(path);
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
if (!file.delete()) {
Log.i(t, "Failed to delete " + file);
}
}
}
return dir.delete();
} else {
return false;
}
}
public static boolean createFolder(String path) {
if (storageReady()) {
boolean made = true;
File dir = new File(path);
if (!dir.exists()) {
made = dir.mkdirs();
}
return made;
} else {
return false;
}
}
public static boolean deleteFile(String path) {
if (storageReady()) {
File f = new File(path);
return f.delete();
} else {
return false;
}
}
public static byte[] getFileAsBytes(File file) {
byte[] bytes = null;
InputStream is = null;
try {
is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
if (length > Integer.MAX_VALUE) {
Log.e(t, "File " + file.getName() + "is too large");
return null;
}
// Create the byte array to hold the data
bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int read = 0;
try {
while (offset < bytes.length && read >= 0) {
read = is.read(bytes, offset, bytes.length - offset);
offset += read;
}
} catch (IOException e) {
Log.e(t, "Cannot read " + file.getName());
e.printStackTrace();
return null;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
try {
throw new IOException("Could not completely read file " + file.getName());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
return bytes;
} catch (FileNotFoundException e) {
Log.e(t, "Cannot find " + file.getName());
e.printStackTrace();
return null;
} finally {
// Close the input stream
try {
is.close();
} catch (IOException e) {
Log.e(t, "Cannot close input stream for " + file.getName());
e.printStackTrace();
return null;
}
}
}
public static boolean storageReady() {
String cardstatus = Environment.getExternalStorageState();
if (cardstatus.equals(Environment.MEDIA_REMOVED)
|| cardstatus.equals(Environment.MEDIA_UNMOUNTABLE)
|| cardstatus.equals(Environment.MEDIA_UNMOUNTED)
|| cardstatus.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
return false;
} else {
return true;
}
}
public static String getMd5Hash(File file) {
try {
// CTS (6/15/2010) : stream file through digest instead of handing it the byte[]
MessageDigest md = MessageDigest.getInstance("MD5");
int chunkSize = 256;
byte[] chunk = new byte[chunkSize];
// Get the size of the file
long lLength = file.length();
if (lLength > Integer.MAX_VALUE) {
Log.e(t, "File " + file.getName() + "is too large");
return null;
}
int length = (int) lLength;
InputStream is = null;
is = new FileInputStream(file);
int l = 0;
for (l = 0; l + chunkSize < length; l += chunkSize) {
is.read(chunk, 0, chunkSize);
md.update(chunk, 0, chunkSize);
}
int remaining = length - l;
if (remaining > 0) {
is.read(chunk, 0, remaining);
md.update(chunk, 0, remaining);
}
byte[] messageDigest = md.digest();
BigInteger number = new BigInteger(1, messageDigest);
String md5 = number.toString(16);
while (md5.length() < 32)
md5 = "0" + md5;
is.close();
return md5;
} catch (NoSuchAlgorithmException e) {
Log.e("MD5", e.getMessage());
return null;
} catch (FileNotFoundException e) {
Log.e("No Cache File", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Problem reading from file", e.getMessage());
return null;
}
}
}
Try this
final File sdcard=Environment.getExternalStorageDirectory();
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0) {
File path=new File(sdcard,"textfile.txt");
try {
BufferedWriter wr=new BufferedWriter(new FileWriter(path));
wr.write("Your Text Here");
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Also you need to add following permission to your manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Categories

Resources