Create text file, tar the file and put it into an inputstream? - java

I want to put a textfile containing just one string into a tar archive and put this tar file into an inputstream... I want to do this "on the fly", without saving any temporary files to the disk...
I tried out this snippet, where I end up with a file:
FileOutputStream fos = null;
try {
fos = new FileOutputStream ("helloworld.txt");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String config = "HelloWorld!";
byte[] b = config.getBytes();
try {
baos.write(b);
baos.writeTo(fos);
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And I had a look at the jtar library:
https://code.google.com/p/jtar/
So I would like to put that textfile directly into that tar, but I also don't need that new FileOutputStream( "c:/test/test.tar" ), instead I want to put it into an inputstream directly.
I'm a bit confused with all those inputstreams/outputstreams and I'm not sure if it's even possible to move around a bunch of those streams instead of creating temporary files to do this.
THX & BR

Just get rid of the FileOutputStream and the bos.writeTo(), and do:
ByteArrayInputStream bais = new ByteArrayInputStream (baos.toByteArray());
instead.

I'm not sure if this is the best way to do it, but this seems to work, but not exactly as I imagined:
File tempFile = File.createTempFile("config", ".properties");
BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile));
bw.write("Helloworld!!!!");
bw.close();
File tempTarFile = File.createTempFile("config", ".tar");
FileOutputStream dest = new FileOutputStream( tempTarFile );
TarOutputStream out = new TarOutputStream( new BufferedOutputStream( dest ) );
out.putNextEntry(new TarEntry(tempFile, "config.properties"));
BufferedInputStream origin = new BufferedInputStream(new FileInputStream( tempFile ));
int count;
byte data[] = new byte[2048];
while((count = origin.read(data)) != -1) {
out.write(data, 0, count);
}
out.flush();
origin.close();
out.close();
tempFile.delete();
tempTarFile.delete();
InputStream inputStream = new FileInputStream(tempTarFile);
//to check if it worked:
// OutputStream outputStream = null;
//
// try {
//
// // write the inputStream to a FileOutputStream
// outputStream =
// new FileOutputStream(new File("config.tar"));
//
// int read = 0;
// byte[] bytes = new byte[1024];
//
// while ((read = inputStream.read(bytes)) != -1) {
// outputStream.write(bytes, 0, read);
// }
//
// System.out.println("Done!");
//
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// if (inputStream != null) {
// try {
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// if (outputStream != null) {
// try {
// // outputStream.flush();
// outputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// }
// }

Related

Create zip archive from a list of ByteArrayInputStream and return byte[] array of the archive - JAVA

I want to archive some files that I am receiving from an external source. I receive each of this files as a ByteArrayInputStream. In the end I want my method to create the zip archive and return a byte[] array so that I can download it later.
I have successfully managed to do this, but the end result is an ZipOutputStream and not the byte[] array that I need.
Any ideeas are appreciated. Thanks!
FileOutputStream fos = null;
ZipOutputStream zipOut = null;
try {
fos = new FileOutputStream(archiveFileName.concat(ReportFormat.ZIP.getFileExtension()));
zipOut = new ZipOutputStream(new BufferedOutputStream(fos));
for (Map.Entry<?, ByteArrayInputStream> entry : mapInputStream.entrySet()) {
String fileFromInsiteArchiveName = (String) entry.getKey();
ByteArrayInputStream inputStream = entry.getValue();
ZipEntry zipEntry = new ZipEntry(fileFromInsiteArchiveName);
zipOut.putNextEntry(zipEntry);
byte[] tmp = new byte[4 * 1024];
int size = 0;
while ((size = inputStream.read(tmp)) != -1) {
zipOut.write(tmp, 0, size);
}
zipOut.flush();
inputStream.close();
}
zipOut.close();
return zipOut;
} catch (FileNotFoundException e) {
//handle this
} catch (IOException e) {
//handle this
} finally {
try {
if (fos != null) fos.close();
} catch (Exception ex) {
//handlethis
}
}
return zipOut;
}
Copy to ByteArrayOutputStream and then do baos.toByteArray() to get your byte[]

I'm confused about PDF files

If I have my code this way round the PDF say's its invalid and cannot be opened, but if I swap them and have B before A it works fine? why is this and what would I have to do to get it working? TIA
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//A
String line = "";
StringBuilder builder = new StringBuilder();
try {
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
//B
File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File outputFile = new File(directory, "goo.pdf");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] buffer = new byte[1024];
int len1 = 0;//init length
while (true) {
try {
if (!((len1 = in.read(buffer)) != -1)) break;
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.write(buffer, 0, len1);
} catch (IOException e) {
e.printStackTrace();
}
}
An InputStream can only be read once.
In 'A', the stream is read and the contents are put in a StringBuilder.
In 'B', the stream (now empty) is read and piped to a file.
By having A first, the output file will always be empty.
Simply remove A as it's not doing anything for you here.

Move file without using renameTo()

In my Java program, I would like to display the progress of moving a file. I use the following snippet of code to copy files, which allows me to track the bytes copied and shows it in a progress bar. I was wondering if the code code be adapted to move files rather than just copy them?
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bis.close();
bos.close();
Okay, so a "move" operation is a copy with a "delete" at the end, for example...
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bos.close();
bis.close();
// You may want to verify that the file's are the same (ie the file size for example)
if (!sourceFile.delete()) {
throw new IOException("Failed to remove source file " + sourceFile);
}
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
bis.close();
} catch (Exception exp) {
}
try {
bos.close();
} catch (Exception exp) {
}
}

Problems reading a huge file of 12 MB (java.lang.OutOfMemoryError)

i need to open a file of 12 Megabytes, but actually i'm doing it creating a buffer of 12834566-byte, because the size of the file is 12MB and i am developing this app for Android mobile systems.
Then, i supose i have to read with blocks of 1024 Kbytes instead of one block of 12 Mbytes, with a for, but i don't know how to do it, i need a little help with it.
This is my actual code:
File f = new File(getCacheDir()+"/berlin.mp3");
if (!f.exists()) try {
InputStream is = getAssets().open("berlin.mp3");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) { throw new RuntimeException(e); }
Please, can someone tell me what i have to changue in this code to read blocks of 1024 Kbytes instead of one block of 12 Mbytes?
THanks!
Try copying 1 KB at a time.
File f = new File(getCacheDir()+"/berlin.mp3");
if (!f.exists()) try {
byte[] buffer = new byte[1024];
InputStream is = getAssets().open("berlin.mp3");
FileOutputStream fos = new FileOutputStream(f);
int len;
while((len = is.read(buffer)) > 0)
fos.write(buffer, 0, len);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.close(is); // utility to close the stream properly.
IOUtils.close(fos);
}
Does Android support symbolic or hand links like UNIX? If it does, this would be faster/more efficient.
File f = new File(getCacheDir()+"/berlin.mp3");
InputStream is = null;
FileOutputStream fos = null;
if (!f.exists()) try {
is = getAssets().open("berlin.mp3");
fos = new FileOutputStream(f);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
fos.write(buffer);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// proper stream closing
if (is != null) {
try { is.close(); } catch (Exception ignored) {} finally {
if (fos != null) {
try { fos.close(); } catch (Exception ignored2) {}
}
}
}
}
import org.apache.commons.fileupload.util.Streams;
InputStream in = getAssets().open("berlin.mp3");
OutputStream out = new FileOutputStream(f);
Streams.copy(in, out, true);

Zipentry is not streaming files in order in Android?

I am trying to stream files from a zip file using ZipEntry class in android, however I am not getting the files in alphabetical order.
Here is my code:
InputStream is = context.getResources().openRawResource(R.raw.file);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
try {
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
String filename = ze.getName();
byte[] bytes = baos.toByteArray();
int value = progress++;
task.doProgress(value);
Log.e(" -- zip process ---", "Filename: " + filename.toString());
// do something with 'filename' and 'bytes'...
}
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("Database Install", "Error: " + e.toString());
e.printStackTrace();
} finally {
try {
zis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am not sure what is wrong with the code.
ZipInputStream reads entries sequentially so they can't be in alphabetical order in general. If you want them to be in alphabetical order you should read them first using ZipFile.entries(), sort as you like and access entries using ZipFile.getEntry().

Categories