Unknown format (magic number 5153) - java

When I try to decompress my .gz file and overwrite the db file I get the Unknown format (magic number 5153). Here is my code for the decompression and overwrite.
InputStream fIn = c.getAssets().open("MyContacts");
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
FileOutputStream myOutput = new FileOutputStream(outFileName);
GZIPInputStream gz = new GZIPInputStream(fIn);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[10246];
int length;
while ((length = gz.read(buffer, 0,buffer.length)) != -1){
myOutput.write(buffer, 0, length);
}
//Close the streams
gz.close();
myOutput.flush();
myOutput.close();
fIn.close();

It is very likely that the asset is being decompressed on the fly before it gets to your code. The aapt has its own strong ideas about how to handle compressed asset files. The behavior depends in part (in ways that are undocumented as far as I can tell) on the asset file names. You are much better off placing uncompressed files in the assets directory and letting aapt compress them for you. It generally does an excellent job and relieves you of having to worry about this kind of thing.
See the blog post that zapl's comment points to.

Your asset is not compressed (or is being transparently decompressed), since it's finding the "SQ" at the beginning of "SQLite format" at the beginning of your file.

Related

Unzipped DB in Android not readable

I am trying to transfer a SQLite database into an app by downloading it and then unzipping it to the correct location. I was successful in transferring the DB when it was unzipped. The error I get is that it cannot find any of the tables I query. I have also been successful in unzipping and reading normal text files.
The DB has Hebrew and English, but that has not caused problems before. The bilingual DB was copied successfully when it was not zipped and bilingual texts have been successfully unzipped and read. Still, it is a possibility that there is an encoding problem going on. That seems weird to me, because as you can see below in the code, I'm just copying the bytes directly.
-EDIT-
Let's say the prezipped db is called test1.db. I zipped it, put it in the app, unzipped it and called that test2.db. when I ran a diff command on these two, there were no differences. So there must be a technical issue with the way android is reading the file / or maybe encoding issue on android that doesn't exist on pc?
I hate to do a code dump, but i will post both my copyDatabase() function (which works). That is what I used previously running it on an unzipped DB file. I put it here as comparison. Now I'm trying to use unzipDatabase() function (which doesn't work), and use it on a zipped DB file. The latter function was copied from How to unzip files programmatically in Android?
private void copyDatabase() throws IOException{
String DB_NAME = "test.db";
String DB_PATH = "/data/data/org.myapp.myappname/databases/";
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_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();
}
private boolean unzipDatabase(String path)
{
String DB_NAME = "test.zip";
InputStream is;
ZipInputStream zis;
try
{
String filename;
is = myContext.getAssets().open(DB_NAME);
zis = new ZipInputStream(is);
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null)
{
// write to a file
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
Log.d("yo",path + filename);
File fmd = new File(path + filename);
fmd.mkdirs();
continue;
}
OutputStream fout = new FileOutputStream(path + filename);
// reading and writing zip
while ((count = zis.read(buffer)) != -1)
{
fout.write(buffer, 0, count);
}
fout.flush();
fout.close();
zis.closeEntry();
}
zis.close();
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
So still don't know why, but the problem is solved if I first delete the old copy of the database (located at DB_PATH + DB_NAME) and then unzip the new one there. I didn't need to do this when copying it directly.
so yay, it was a file overwriting issue...If someone knows why, feel free to comment

Java : download file outside server context

I need to save a file and download file in directory outside server context.
I am using Apache Tomacat
I am able to do this in directory present in webapps directory of application
If my directory structure is as follows,
--src
--WebContent
-- uploaddir
-- myfile.txt
Then I am able to download in by simply.
download
But, problem is when file is in some other directory say d:\\uploadedfile\\myfile.txt
then I wont be able to download it, as resource is not in server context as above.
I have file path to uuid mapping,
like,
d:\\uploadedfiles\\myfile.txt <-> some_uuid
then I want file should be downloaded, on click of following,
download
So, How to make file downloadable when it is outside the server context,
I heard about getResourceAsStream() method which would do this , But would any one help me on how to do this, probably with simple code snippet?
Try the below code which you can write in filedownloadservet. Fetch the file name from the request parameter and then read and write the file.
If you need to do some security checks then do that before processing the request.
File file = new File("/home/files", "file name which user wants to download");
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setContentLength(file.length());
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] buf = new byte[2048];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//log it
}
}
// do the same for input stream also
}
here i found the answer,
response.setContentType("application/msword");
response.setHeader("Content-Disposition","attachment;filename=downloadname.doc");
File file=new File("d:\\test.doc");
InputStream is=new FileInputStream(file);
int read=0;
byte[] bytes = new byte[BYTES_DOWNLOAD];
OutputStream os = response.getOutputStream();
while((read = is.read(bytes))!= -1){
os.write(bytes, 0, read);
}
os.flush();
os.close();
Base path will not work that is for HTML and it works if the base path is also exposed by your web server which does not look like case here.
To download an arbitary file you need to open the file using a FileInputStream (and surround it by a buffered input stream), read a byte, then send that byte from your servlet to the client.
Then there are security concerns, so should google that (basically not give access to any file but only file that is to be shared, audit download etc as needed.
Again in your servlet set the mime type etc and then open a input stream and write the bytes to the output stream to client

Decompressing zip files with accents

I'm using a Java mechanism to extract zip files. The mechanism works fine if there is no files in it with accents on title. Since I'm from portugal, chars like ã, ç, õ, é, etc. are usually used in my language. If any of this chars are in the filename, an IO exception occurs.
while (zipFileEntries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
File destFile = new File(unzipDestinationDirectory, currentEntry);
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is =
new BufferedInputStream(zip_file.getInputStream(entry));
int currentByte;
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
It crashes on while((currentByte = is.read(data, 0, BUFFER)) != -1)
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:134)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at parsers.ZipParser.decompressZipFile(ZipParser.java:83)
at poc.MainPOC.main(MainPOC.java:61)
Are you aware of any workaround to deal with this problem? Can I change the filename of a file inside a zip without decompressing it?
Since Java 7, there is a way new construcor to ZipInputStreamto specify a charset to use for the filename. See the documentation here.
So you would create your ZipInputStream with something like :
ZipInputStream zis = new ZipInputStream(new FileInputStream("your zip file"), Charset.forName("Encoding here"));
See Charset to have a bit more informations about how to use it.
It will not change the way you are reading the file, so you will need another workaround to read the content. But for more information, see this answer Java zip character encoding, you can probably re-use some of the code.
I think you must set the encoding properly when you compress and decompress. Did you make it UTF-8 when you created the ZIP file? If not, I'd recommend trying it.

How to convert a InputStream to ZIP format?

I am having a InputStream Object which is actually a zip file. I want to change it back to zip file and save it. I am using DWR's FileTransfer class object to receive the uploaded data from client.
FileTransfer have 3 methods, getInputStream() is one of them. It returns InputStream from FileTransfer object.
In my case, fileTransfer object holds zip file and as well as InputStream object too.
I have done, lot of searches in google. But i am not able to find one example, that illustrates InputStream to zip conversion.
Update
String zipName = file.getName();
String zipType = file.getMimeType();
InputStream zipStream = file.getInputStream();
ZipInputStream zis = new ZipInputStream(zipStream);
System.out.println("File Name: "+zipName+"\n"+"File Type: "+zipType);
int c;
File f2 = new File(DATA_STORE_LOC+dat+".zip");
path.setPath2(DATA_STORE_LOC+dat+".zip");
FileOutputStream fos = new FileOutputStream(f2);
ZipOutputStream zos = new ZipOutputStream(fos);
c = zis.read();
System.out.println(c);
while ((c = zis.read(BUFFER)) != -1) {
zos.write(BUFFER, 0, c);
}
zos.close();
zis.close();
I tried this code, by thought of a typical file copy program. I know it is false, just tried. It gives me java.util.zip.ZipException: ZIP file must have at least one entry.
Any suggestion would be really appreciative!!!!!
See the examples java2s, input and output. If you have more questions feel free to ask them :)
For clarity, in this input example you should do something like:
// FileInputStream fin = new FileInputStream(args[i]);
ZipInputStream zin = new ZipInputStream(ft.getInputStream());
As Don Roby correctly said, if you just want to copy you need not know the file structure and you could use for example static IOUtils.copy(in, out) to copy the file.
Further, if you do wish to extract the ZIP file contents, you should not plainly copy bytes. The ZIP file has a structure, and you extract Entries from the ZIP file, and not just bytes (see the example). Every Entry is a (compressed) file (or the data thereof) with the original name:
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
System.out.println("Unzipping " + ze.getName());
FileOutputStream fout = new FileOutputStream(ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
...
Please note the javadoc of getNextEntry():
Reads the next ZIP file entry and positions the stream at the beginning of the entry data.
This positioning is crucial to get to the zipped file contents, and not the metadata.
And I do believe that you accidentally remove the first int:
c = zis.read(); // removing the first
while ((c = zis.read(BUFFER)) != -1) { // so you start with the second?
I believe you mix 2 idioms:
c = zis.read();
while(c != -1) {
...
c = zis.read();
}
and:
int c;
while ((c = zis.read(BUFFER)) != -1) { // so you start with the second?
...
}
I think you can see the difference :)
If your input is a an InputStream from a zip file and your desired output is still a zip file with the same contents, you're just doing a file copy operation and shouldn't have to worry about zip at all. You just need to read from the InputStream and write to a FileOutputStream, more or less as you're doing, but without worrying about wrapping either stream in a zip-aware stream.
ZipInputStream is useful if you have to extract the contents of the zip file as separate files, i.e., to programmatically unzip. And on the other side, ZipOutputStream is used if your have the contents and need to combine them into a zip file.

Convert audio stream to WAV byte array in Java without temp file

Given an InputStream called in which contains audio data in a compressed format (such as MP3 or OGG), I wish to create a byte array containing a WAV conversion of the input data. Unfortunately, if you try to do this, JavaSound hands you the following error:
java.io.IOException: stream length not specified
I managed to get it to work by writing the wav to a temporary file, then reading it back in, as shown below:
AudioInputStream source = AudioSystem.getAudioInputStream(new BufferedInputStream(in, 1024));
AudioInputStream pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
AudioInputStream ulaw = AudioSystem.getAudioInputStream(AudioFormat.Encoding.ULAW, pcm);
File tempFile = File.createTempFile("wav", "tmp");
AudioSystem.write(ulaw, AudioFileFormat.Type.WAVE, tempFile);
// The fileToByteArray() method reads the file
// into a byte array; omitted for brevity
byte[] bytes = fileToByteArray(tempFile);
tempFile.delete();
return bytes;
This is obviously less desirable. Is there a better way?
The problem is that the most AudioFileWriters need to know the file size in advance if writing to an OutputStream. Because you can't provide this, it always fails. Unfortunatly, the default Java sound API implementation doesn't have any alternatives.
But you can try using the AudioOutputStream architecture from the Tritonus plugins (Tritonus is an open source implementation of the Java sound API): http://tritonus.org/plugins.html
I notice this one was asked very long time ago. In case any new person (using Java 7 and above) found this thread, note there is a better new way doing it via Files.readAllBytes API. See:
How to convert .wav file into byte array?
Too late, I know, but I was needed this, so this is my two cents on the topic.
public void UploadFiles(String fileName, byte[] bFile)
{
String uploadedFileLocation = "c:\\";
AudioInputStream source;
AudioInputStream pcm;
InputStream b_in = new ByteArrayInputStream(bFile);
source = AudioSystem.getAudioInputStream(new BufferedInputStream(b_in));
pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
File newFile = new File(uploadedFileLocation + fileName);
AudioSystem.write(pcm, Type.WAVE, newFile);
source.close();
pcm.close();
}
The issue is easy to solve if you prepare class which will create correct header for you. In my example Example how to read audio input in wav buffer data goes in some buffer, after that I create header and have wav file in the buffer. No need in additional libraries. Just copy the code from my example.
Example how to use class which creates correct header in the buffer array:
public void run() {
try {
writer = new NewWaveWriter(44100);
byte[]buffer = new byte[256];
int res = 0;
while((res = m_audioInputStream.read(buffer)) > 0) {
writer.write(buffer, 0, res);
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
public byte[]getResult() throws IOException {
return writer.getByteBuffer();
}
And class NewWaveWriter you can find under my link.
This is very simple...
File f = new File(exportFileName+".tmp");
File f2 = new File(exportFileName);
long l = f.length();
FileInputStream fi = new FileInputStream(f);
AudioInputStream ai = new AudioInputStream(fi,mainFormat,l/4);
AudioSystem.write(ai, Type.WAVE, f2);
fi.close();
f.delete();
The .tmp file is a RAW audio file, the result is a WAV file with header.

Categories