File object to byte array - android development - java

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().

Related

Unable to compress a CSV file Java

I'm trying to convert an existing CSV file to a gzip file.
I verified the CSV looks good. Once I run this code, I get a "failed to expand" error and tried an online decompression tool that also failed, so it seems the output zip is corrupt.
public void compressGzip(String input, String dest) throws IOException {
Path pathSource = Paths.get(input);
Path destSource = Paths.get(dest);
try (GZIPOutputStream gos = new GZIPOutputStream(
new FileOutputStream(destSource.toFile()));
FileInputStream fis = new FileInputStream(pathSource.toFile())) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
gos.write(buffer, 0, len);
}
}
}
Anything I could be missing here?

Put Inputstream containing multiple files into one ZipEntry

I want to zip an array of File to a zipfile and send it to the browser. The Inputstream of each File is a shapefile, and actually consists of multiple files (.shp, .dbf, .shx, ...).
When I send only one File with the following code, it works properly and a zipfile is returned with all the desired files in it.
Code to send a single file
FileInputStream is = new FileInputStream(files.get(0));
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + getCurrentUser(request).getNiscode() + ".zip");
while (is.available() > 0) {
response.getOutputStream().write(is.read());
}
is.close();
if (response.getOutputStream() != null) {
response.getOutputStream().flush();
response.getOutputStream().close();
}
When I try to send all the files together, a zipfile is returned with the desired folders, but in each folder only one element with just a .file extension is present. It has something to do with the entries of the ZipOutputStream?
Code to send all the files
byte[] zip = this.zipFiles(files, Ids);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename="test.zip");
response.getOutputStream().write(zip);
response.flushBuffer();
private byte[] zipFiles(ArrayList<File> files, String[] Ids) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
int count = 0;
for (File file : files) {
FileInputStream fis = new FileInputStream(file);
zos.putNextEntry(new ZipEntry(Ids[count] + "/"));
zos.putNextEntry(new ZipEntry(Ids[count] + "/" + file.getName()));
while (fis.available() > 0) {
zos.write(fis.read());
}
zos.closeEntry();
fis.close();
count ++;
}
zos.flush();
baos.flush();
zos.close();
baos.close();
return baos.toByteArray();
}
Based on your code, it seems like every file inside your files array is already a zip file
When you then later do zipFiles, you are making a zipfile that contains more zipfiles in its folders. You obviously don't want this, but you want a zipfile that has folders that contain the contents of all could zipfiles.
Basing on an existing an existing answer of Thanador located at "Reading data from multiple zip files and combining them to one" I devised the following solution to also include directories and proper stream handling:
/**
* Combine multiple zipfiles together
* #param files List of file objects pointing to zipfiles
* #param ids List of file names to use in the final output
* #return The byte[] object representing the final output
* #throws IOException When there was a problem reading a zipfile
* #throws NullPointerException When there either input is or contains a null value
*/
private byte[] zipFiles(ArrayList<File> files, String[] ids) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Buffer to copy multiple bytes at once, this is generally faster that just reading and writing 1 byte at a time like your previous code does
byte[] buf = new byte[16 * 1024];
int length = files.size();
assert length == ids.length;
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
for (int i = 0; i < length; i++) {
try (ZipInputStream inStream = new ZipInputStream(new FileInputStream(files.get(i))) {
ZipEntry entry;
while ((entry = inStream.getNextEntry()) != null) {
zos.putNextEntry(new ZipEntry(ids[i] + "/" + entry.getName()));
int readLength;
while ((readLength = inStream.read(buf)) > 0) {
zos.write(buf, 0, readLength);
}
}
}
}
}
return baos.toByteArray();
}
Technically, its faster and more memory efficient to directly write to the output stream you got from response.getOutputStream(), but I didn't do this in the above example, so you would have an easier time implementing the method in your code
If you close a stream, it automatically flushes it, I'm using try-with-resources to close them
try following solution:
private byte[] zipFiles(ArrayList<File> files, String[] Ids) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
for (File file : files) {
ZipEntry ze= new ZipEntry(file.getName());
zos.putNextEntry(ze);
FileInputStream fis = new FileInputStream(file);
int len;
while ((len = fis .read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
fis .close();
}
byte[] byteArray = baos.toByteArray();
zos.flush();
baos.flush();
zos.close();
baos.close();
return byteArray;
}
IDK why you put count variable and why you put twice zos.putNextEntry(new ZipEntry()).
public static void compressListFiles(List<Pair<String, String>> filePairList, ZipOutputStream zipOut) throws Exception {
for (Pair<String, String> pair : filePairList) {
File fileToZip = new File(pair.getValue());
String fileId = pair.getKey();
FileInputStream fis = new FileInputStream(fileToZip);
ZipEntry zipEntry = new ZipEntry(fileId + "/" + fileToZip.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
}
}

How to directly download a file from server,without saving it in any folder?

if(!ErmUtil.isNull(listOfActualFilePaths) && listOfActualFilePaths.size()>0){
FileOutputStream fos = new FileOutputStream("/smiles/wrk/attachments/ermWeb/taxation/testing.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
Iterator itrOnFNames = listOfActualFilePaths.iterator();
while (itrOnFNames.hasNext()) {
StringBuffer ActualPath = (StringBuffer) itrOnFNames.next();
addToZipFile(ActualPath.toString(), zos);
}
zos.close();//Closing Both Streams
fos.close();
}
public void addToZipFile(String fileName, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
int index = fileName.lastIndexOf("/");
String fileNameForZip = fileName.substring(index+1);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileNameForZip);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
I am using above code, to save zip-ed file on a specific location. But what i want to do is that, instead of saving that file, it get downloaded directly.
Edit 1
See If I want to download a zip file,then according to above code, on path /smiles/wrk/attachments/ermWeb/taxation/testing.zip it will be saved first,then from that folder, I(server) can send it to client(Computer).
But I don't want to save it on the specified path,Instead of "saving first to folder and then sending to client", I directly want to send it to client.

making zip process more optimized one

I have developed a method to zip a file that will take file path and filename as a parameter and will zip a file as shown below could you please advise how can I modify this method to be more efficient and more fast as I am a big fan of optimization..
public File generateZipForAFile(String folderPath, String reportFileName)
throws FileNotFoundException, IOException {
File inputFile = new File(folderPath + reportFileName);
FileInputStream in = new FileInputStream(inputFile);
File outputZipFile = new File(folderPath, reportFileName + ".zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputZipFile));
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(reportFileName ));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
out.close();
in.close();
return outputZipFile;
}
There is not much you can do in your code. Furthermore, most of the time is spent while actually doing the zip.
So even if you reduce the time spent in your part to 0 the overall gain will be very small.

Java copying a file out of a jar

I am trying to copy a file (Base.jar) to the same directory as the running jar file
I keep getting a corrupted jar file, that still holds the correct class structure when opened with winrar. What am I doing wrong? (I have also tried without the ZipInputStream, but that was no help) the byte[] is 20480 because that is size of it on the disk.
my code:
private static void getBaseFile() throws IOException
{
InputStream input = Resource.class.getResourceAsStream("Base.jar");
ZipInputStream zis = new ZipInputStream(input);
byte[] b = new byte[20480];
try {
zis.read(b);
} catch (IOException e) {
}
File dest = new File("Base.jar");
FileOutputStream fos = new FileOutputStream(dest);
fos.write(b);
fos.close();
input.close();
}
InputStream input = Resource.class.getResourceAsStream("Base.jar");
File fileOut = new File("your lib path");
OutputStream out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
and handle exceptions
No need to use ZipInputStream, unless you want to unzip the contents into memory and read.
Just use BufferedInputStream(InputStream) or BufferedReader(InputStreamReader(InputStream)).
did some more googling found this: (Convert InputStream to byte array in Java) worked for me
InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
(it looks very simular to the src for IOUtils.copy())
ZipInputStream is for reading files in the ZIP file format by entry. You need to copy the whole file (resource) that is you need to simply copy all bytes from InputStream no matter what format is. The best way to do it in Java 7 is this:
Files.copy(inputStream, targetPath, optionalCopyOptions);
see API for details

Categories