unzipping images into blobstore - java

in my app i need to do the following:
1. a zip file with images (jpgs only right now)and other stuff is uploaded into the BlobStore.
2. an app engine backend should read the entries from the uploaded zip and save all images found inside to the BlobStore as stand alone files.
i successfully upload, unzip and save files # blobstore, but the images seem to be broken.
when i download them from the BlobStore (simply blobstoreService.serve them) the images have wrong colors, or displayed partially, or broken in other ways. an attempt to use ImagesService also throws an exception. i checked the size of the images before they are zipped and the size of the files unzipped while written into the blobstore and they look the same. here is my code:
ZipInputStream zis = ...;
ZipEntry entry;
while ((entry =zis.getNextEntry()) !=null)
{
String fileName = entry.getName().toLowerCase();
if(fileName.indexOf(".jpg") != -1 || fileName.indexOf(".jpeg") != -1)
{
FileService fileService = FileServiceFactory.getFileService();
String mime = ctx.getMimeType(fileName);//getting mime from servlet context
AppEngineFile file = fileService.createNewBlobFile(mime, fileName);
boolean lock = true;
FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);
byte[] buffer = new byte[BlobstoreService.MAX_BLOB_FETCH_SIZE];
while(zis.read(buffer) >= 0)
{
ByteBuffer bb = ByteBuffer.wrap(buffer);
writeChannel.write(bb);
}
writeChannel.closeFinally();
BlobKey coverKey = fileService.getBlobKey(file);
....
}
}
thanks a lot for you time!
UPD: i found a work-around that works, but i still don't understand why the first solution failed.
int read;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((read = zis.read()) >= 0)
{
baos.write(read);
if(baos.size() == BlobstoreService.MAX_BLOB_FETCH_SIZE)
{
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
writeChannel.write(bb);
baos = new ByteArrayOutputStream();
}
}
if(baos.size() > 0)
{
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
writeChannel.write(bb);
}

Because of zis.read(buffer) may not fill the entire buffer.
Use following instead
int len;
while((len = zis.read(buffer)) >= 0){
ByteBuffer bb = ByteBuffer.wrap(buffer, 0, len);
writeChannel.write(bb);
}
Hope this help

Related

android copy mp3 file success but duration not change

i try to copy mp3 file in external storage and limit duration of new file. it work but when it started, although i run to limit time, it still display end time like old file.
private void copy(File in, File out) throws IOException {
FileInputStream is = null;
FileOutputStream os = null;
try {
is = new FileInputStream(in);
os = new FileOutputStream(out);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0 && out.length()<175642) {
os.write(buffer, 0, length);
}
} finally {
assert is != null;
is.close();
assert os != null;
os.close();
}
}
how can i fix it. i really expect your help. have a nice day,everyone!
You simply cut of the rest of the file. This leads to a kind of corrupted file because the data in the header-block (e.g. the length) is no longer correct.
For some information about the mp3 file format:
https://en.wikipedia.org/wiki/MP3
I highly recommend to adjust the header information after shortening the file.

'On the fly' unpackaging of files on Android

I need to package a few files (total upto 4 GB in size) which will be available online. An android app needs to download this 'on the fly' without saving the archive on to the device. So basically the device won't save the archive and then unpack, as it would require double the space. Which package format should I choose that will support it (eg. zip, tar.gz etc.)?
Use .zip! You can use ZipInputStream and ZipOutputStream to read and write from .zip files on the fly. No need to extract the files from the archive.
Link to documentation
And here is a quick example:
InputStream is =...
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
try {
// ZipEntry contains data about files and folders in the archive.
ZipEntry ze;
// This loops through the whole content of the archive
while ((ze = zis.getNextEntry()) != null) {
// Here we read the whole data of one ZipEntry
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
// The ZipEntry contains data about the file, like its filename
String filename = ze.getName();
// And that's the file itself as byte array
byte[] bytes = baos.toByteArray();
// Do something with the file
}
} finally {
zis.close();
}

File object to byte array - android development

I need to convert this File object to byte array:
File directory=new File(Environment.getExternalStorageDirectory() + "");
(I need only the names of folders and files on SDcard.)
I have already tried this:
byte[] send=null;
FileInputStream fis;
try {
fis = new FileInputStream(directory);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int readBytes = 0;
while(readBytes != -1)
{
readBytes = fis.read(buffer);
if(readBytes > 0)
{
bos.write(buffer, 0, readBytes);
}
else
break;
}
byte[] fileData = bos.toByteArray();
send=fileData;
But it returns this error:
java.io.FileNotFoundException: /mnt/sdcard (Is a directory)
You're trying to load the directory as if it were a file. It's not. What would you expect the contents of the byte array to be?
If you want to find the list of files in a directory, use File.listFiles().

Java most efficient way to retrieve something out of the middle of a ZIP

I am seeking for most efficient way (in terms of speed) to retrieve some file out of the middle of a ZIP file.
e.g. I have ZIP file, which includes 700 folders (tagged 1 to 700). Each folder equals picture and mp3 file. There is special folder called Info, which contains XML file. Problem is, I need to iterate through this ZIP file to find XML file and then I am displaying images from desired folders. I am using ZipFile approach (thus I am iterating through whole ZIP file, even if I want folder 666, I need to go through 665 items in ZIP file) -> selecting from ZIP file is extremely slow.
I would like to ask you, If you have faced similar issue, how have you solved this? Is there any approach in Java, which turns my ZIP file into virtual folder to browse it much more quicker? Is there any external library, which is the most efficient in terms of time?
Source Code snippet:
try {
FileInputStream fin = new FileInputStream(
"sdcard/external_sd/mtp_data/poi_data/data.zip");
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
// Log.d("ZE", ze.getName());
if (ze.getName().startsWith("body/665/")) {
// Log.d("FILE F", "soubor: "+ze.getName());
if (ze.getName().endsWith(".jpg")
|| ze.getName().endsWith(".JPG")) {
Log.d("OBR", "picture: " + ze.getName());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = zin.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
byte[] bytes = baos.toByteArray();
bmp = BitmapFactory.decodeByteArray(bytes, 0,
bytes.length);
photoField.add(bmp);
i++;
}
}
}
}
The ZipFile.getEntry() and ZipFile.getInputStream() methods can be used to access a specific file in a ZIP archive. For example:
ZipFile file = ...
ZipEntry entry = file.getEntry("folder1/picture.jpg");
InputStream in = file.getInputStream(entry);

Whats wrong with this zip method?

I have a method which zips up 5 files. It produces a zip file without error, but I cannot open it to examine the contents. I tried emailing it and gmail said it cannot send corrupt files. Trying to open with WinRAR in Windows results in an error stating:
The archive is either in unknown format or damaged
This is the method:
private void zipTestFiles() throws FileNotFoundException, IOException
{
File[] filenames = fileDir.listFiles(fileNameFilter(Constants.PAGE_MON_FILENAME_FILTER));
byte[] buf = new byte[1024];
String outFilename = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + Constants.PAGEMONITOR_ZIP;
DeflaterOutputStream out = new DeflaterOutputStream(new BufferedOutputStream(new FileOutputStream(outFilename)));
for (int i=0; i<filenames.length; i++)
{
FileInputStream in = new FileInputStream(filenames[i]);
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
in.close();
}
out.close();
}
You should use ZipOutputStream instead of DeflaterOutputStream. And do not forget to create entries. Read javadoc of ZipOutputStream before writing the implementation.
Try with ZipOutputStream which already exists in Java. DeflaterOutputStream only uses DEFLATE method to compress but doesn't put ZIP headers automatically.

Categories