I have android app that downloads compressed files and then decompress it ..
it works fine with English name files..
but if the file with Arabic name it make error malformated
E/UncaughtException: java.lang.IllegalArgumentException: MALFORMED[1]
this is my code..
appreciate your help
Thanks
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;
}
Try
new ZipInputStream(new BufferedInputStream(is), Charset.forName("Windows-1256"));
as default is UTF-8 and that evidently did not work.
After feedback: evidently there is some Android API version problem.
You could inspect:
filename = ze.getName();
Sometimes one can "patch" the encoding. Very error prone, or even not feasible.
filename = new String(filename.getBytes("..."), "...");
where one might try different encodings:
Windows-1256
UTF-8
(Especially converting to UTF-8 might raise conversion errors, as UTF-8 requires the bytes to have a specific bit pattern for multibyte sequences.)
Related
The following unzip finction doesn't work for all zip files.
My zip file pattern is as follows-
The Zip file contains one xml file and one folder(name- "images").
The name of the xml file is same as the zip file name.
The folder("images") may or may not contain any files.
I have validated the xml file before putting it into the zip file.
It throws exception at this line for some zip files-
FileOutputStream fout = new ileOutputStream(path.substring(0,path.length()-4)+"/"+filename);
The function is:
public boolean unZip(String path)
{
InputStream is;
ZipInputStream zis;
try
{
String filename;
is = new FileInputStream(path);
zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null)
{
filename = ze.getName();
if (ze.isDirectory()) {
File fmd = new File(path.substring(0,path.length()-4)+"/"+filename);
fmd.mkdirs();
continue;
}
FileOutputStream fout = new FileOutputStream(path.substring(0,path.length()-4)+"/"+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;
}
This method works fine. It was a permission issue while creating the zips in Linux platform. But function starts working properly when I changed the file permission.
Here i have folder(ZipFilesFolder) in that it consist of 10 zip files say one.zip,two.zip,three.zip..ten.zip,i'm passing file every time from this folder to zipFileToUnzip as zipFilename.I need the result in the same folder(ZipFilesFolder)i need to unzip those files and instead of one.zip,two.zip,..one,two,three folder has to visible.
public static void zipFileToUnzip(File zipFilename) throws IOException {
try {
//String destinationname = "D:\\XYZ";
byte[] buf = new byte[1024];
ZipInputStream zipinputstream = null;
ZipEntry zipentry;
zipinputstream = new ZipInputStream(new FileInputStream(zipFilename));
zipentry = zipinputstream.getNextEntry();
while (zipentry != null) {
//for each entry to be extracted
String entryName = zipentry.getName();
System.out.println("entryname " + entryName);
int n;
FileOutputStream fileoutputstream;
File newFile = new File(entryName);
String directory = newFile.getParent();
if (directory == null) {
if (newFile.isDirectory()) {
break;
}
}
fileoutputstream = new FileOutputStream(
destinationname + entryName);
while ((n = zipinputstream.read(buf, 0, 1024)) > -1) {
fileoutputstream.write(buf, 0, n);
}
fileoutputstream.close();
zipinputstream.closeEntry();
zipentry = zipinputstream.getNextEntry();
}//while
zipinputstream.close();
} catch (IOException e) {
}
}
This is my code ,but it is not working,could anybody help me,how to get desired output.
There are a couple of problems with your code:
it does not compile since destinationname is commented, but referenced when opening the FileOutputStream
IOExceptions are caught and ignored. If you throw them you would get error messages that could help you diagnose the problem
when opening the FileOutputStream, you just concatenate two strings without adding a path-separator in between.
if the file to be created is in a directory, the directory is not created and thus FileOutputStream cannot create the file.
streams are not closed when exceptions occur.
If you do not mind using guava, which simplifies life when it comes to copying streams to files, you could use this code instead:
public static void unzipFile(File zipFile) throws IOException {
File destDir = new File(zipFile.getParentFile(), Files.getNameWithoutExtension(zipFile.getName()));
try(ZipInputStream zipStream = new ZipInputStream(new FileInputStream(zipFile))) {
ZipEntry zipEntry = zipStream.getNextEntry();
if(zipEntry == null) throw new IOException("Empty or no zip-file");
while(zipEntry != null) {
File destination = new File(destDir, zipEntry.getName());
if(zipEntry.isDirectory()) {
destination.mkdirs();
} else {
destination.getParentFile().mkdirs();
Files.asByteSink(destination).writeFrom(zipStream);
}
zipEntry = zipStream.getNextEntry();
}
}
}
Alternatively you might also use zip4j, see also this question.
I have a zip file file.zip that is compressed. Is there a way to change the compression level of the file to store (no compression).
I have written and tried the following code and it works, but I will be running this in an environment where memory and storage will be a limitation and there might not be enough space. I am using the zip4j library.
This code extracts the input zip to a folder, then rezips it with store compression level. The problem with this is that at one point in execution, there are 3 copies of the zip on storage, which is a problem because space is a limitation.
try {
String zip = "input.zip";
final ZipFile zipFile = new ZipFile(zip);
zipFile.extractAll("dir");
File file = new File("dir");
ZipParameters params = new ZipParameters();
params.setCompressionMethod(Zip4jConstants.COMP_STORE);
params.setIncludeRootFolder(false);
ZipFile output = new ZipFile(new File("out.zip"));
output.addFolder(file, params);
file.delete();
return "Done";
} catch (Exception e) {
e.printStackTrace();
return "Error";
}
So any suggestions on another way to approach this problem? Or maybe some speed or memory optimizations to my current code?
As an alternative we can read files from zip one by one in memory or into temp file, like here
ZipInputStream is = ...
ZipOutputStream os = ...
os.setMethod(ZipOutputStream.STORED);
int bSize = ... calculate max available size
byte[] buf = new byte[bSize];
for (ZipEntry e; (e = is.getNextEntry()) != null;) {
ZipEntry e2 = new ZipEntry(e.getName());
e2.setMethod(ZipEntry.STORED);
int n = is.read(buf);
if (is.read() == -1) {
// in memory
e2.setSize(n);
e2.setCompressedSize(n);
CRC32 crc = new CRC32();
crc.update(buf, 0, n);
e2.setCrc(crc.getValue());
os.putNextEntry(e2);
os.write(buf, 0, n);
is.closeEntry();
os.closeEntry();
} else {
// use tmp file
}
}
reading in memory is supposed to be faster
I finally got it after a few hours by playing around with input streams.
try {
final ZipFile zipFile = new ZipFile("input.zip");
File output = new File("out.zip");
byte[] read = new byte[1024];
ZipInputStream zis = new ZipInputStream(new FileInputStream(zip));
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(output));
ZipEntry ze;
zos.setLevel(ZipOutputStream.STORED);
zos.setMethod(ZipOutputStream.STORED);
while((ze = zis.getNextEntry()) != null) {
int l;
zos.putNextEntry(ze);
System.out.println("WRITING: " + ze.getName());
while((l = zis.read(read)) > 0) {
zos.write(read, 0, l);
}
zos.closeEntry();
}
zis.close();
zos.close();
return "Done";
} catch (Exception e) {
e.printStackTrace();
return "Error";
}
Thanks so much for your answer Evgeniy Dorofeev, I literally just got my answer when I read yours! However, I prefer my method as it only takes up a maximum of 1 MB in memory (Am I right?). Also, I tried executing your code and only the first file in the input zip was transferred.
I'm using the following method to compress a file into a zip file:
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public static void doZip(final File inputfis, final File outputfis) throws IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
final CRC32 crc = new CRC32();
crc.reset();
try {
fis = new FileInputStream(inputfis);
fos = new FileOutputStream(outputfis);
final ZipOutputStream zos = new ZipOutputStream(fos);
zos.setLevel(6);
final ZipEntry ze = new ZipEntry(inputfis.getName());
zos.putNextEntry(ze);
final int BUFSIZ = 8192;
final byte inbuf[] = new byte[BUFSIZ];
int n;
while ((n = fis.read(inbuf)) != -1) {
zos.write(inbuf, 0, n);
crc.update(inbuf);
}
ze.setCrc(crc.getValue());
zos.finish();
zos.close();
} catch (final IOException e) {
throw e;
} finally {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
}
}
My problem is that i have flat text files with the content N°TICKET for example, the zipped result gives some weired characters when uncompressed N° TICKET. Also characters such as é and à are not supported.
I guess it's due to the character encoding, but I don't know how to set it in my zip method to ISO-8859-1 ?
(I'm running on windows 7, java 6)
You are using streams which write exactly the bytes that they are given. Writers interpret character data and convert it to the corresponding bytes and Readers do the opposite. Java (at least in version 6) doesn't provide an easy way to to mix and match operations on zipped data and for writing characters.
This way will work though. It is, however, a little clunky.
File inputFile = new File("utf-8-data.txt");
File outputFile = new File("latin-1-data.zip");
ZipEntry entry = new ZipEntry("latin-1-data.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream(outputFile));
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(zipStream, Charset.forName("ISO-8859-1"))
);
zipStream.putNextEntry(entry);
// this is the important part:
// all character data is written via the writer and not the zip output stream
String line = null;
while ((line = reader.readLine()) != null) {
writer.append(line).append('\n');
}
writer.flush(); // i've used a buffered writer, so make sure to flush to the
// underlying zip output stream
zipStream.closeEntry();
zipStream.finish();
reader.close();
writer.close();
Afaik this is not available in Java 6.
But I do believe that http://commons.apache.org/compress/ can provide a solution.
Switching to Java 7 provides a new constructor that that encoding as an additional parameter.
https://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in
zipStream = new ZipInputStream(
new BufferedInputStream(new FileInputStream(archiveFile), BUFFER_SIZE),
Charset.forName("ISO-8859-1")
try to use org.apache.commons.compress.archivers.zip.ZipFile; not java's own library so you can give encoding like that:
import org.apache.commons.compress.archivers.zip.ZipFile;
ZipFile zipFile = new ZipFile(filepath,encoding);
Could you point me out to a code or url where I can find some examples how to use dropbox java api and upload binary files like, .doc files jpg and video files.
Current examples in the web only point to uploading a text file. But when I try to read files using java InputStream and convert them to byte array and pass into dropbox file upload functions files get corrupted. Same issue with downloading files as well. Thanks in Advance.
Regards,
Waruna.
EDIT--
Code Sample
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte [] buf = new byte[1024];
for(int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
System.out.println("read "+ readNum + "bytes,");
}
ByteArrayInputStream inputStream2 = new ByteArrayInputStream(bos.toByteArray());
Entry newEntry = mDBApi.putFile("/uploads/"+file.getName(), inputStream2, file.toString().length(), null, null);
System.out.println("Done. \nRevision of file: " + newEntry.rev + " " + newEntry.mimeType);
return newEntry.rev;
The 3rd argument of DropboxAPI.putFile() should be the number of bytes to read from the input stream - You are passing the length of the filename.
Instead of
Entry newEntry = mDBApi.putFile("/uploads/"+file.getName(), inputStream2,
file.toString().length(), null, null);
Use
Entry newEntry = mDBApi.putFile("/uploads/"+file.getName(), inputStream2,
bos.size(), null, null);
I don't think you need to convert to byte array, simply use FileInputStream is enough for a file, txt as well as binary. The following code works, I just tested with JPG.
DropboxAPI<?> client = new DropboxAPI<WebAuthSession>(session);
FileInputStream inputStream = null;
try {
File file = new File("some_pic.jpg");
inputStream = new FileInputStream(file);
DropboxAPI.Entry newEntry = client.putFile("/testing.jpg", inputStream,
file.length(), null, null);
System.out.println("The uploaded file's rev is: " + newEntry.rev);
} catch (DropboxUnlinkedException e) {
// User has unlinked, ask them to link again here.
System.out.println("User has unlinked.");
} catch (DropboxException e) {
System.out.println("Something went wrong while uploading.");
} catch (FileNotFoundException e) {
System.out.println("File not found.");
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}