I have a byte array representation of a tar.gz file. I want to get the byte array representation of a new tar.gz file after adding a new config file. I wanted to do this entirely in the code itself without creating any files to the local disk.
Below is my code in java
InputStream fIn = new ByteArrayInputStream(inputBytes);
BufferedInputStream in = new BufferedInputStream(fIn);
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in);
TarArchiveInputStream tarInputStream = new TarArchiveInputStream(gzIn);
ByteArrayOutputStream fOut = new ByteArrayOutputStream();
BufferedOutputStream buffOut = new BufferedOutputStream(fOut);
GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(buffOut);
TarArchiveOutputStream tarOutputStream = new TarArchiveOutputStream(gzOut);
ArchiveEntry nextEntry;
while ((nextEntry = tarInputStream.getNextEntry()) != null) {
tarOutputStream.putArchiveEntry(nextEntry);
IOUtils.copy(tarInputStream, tarOutputStream);
tarOutputStream.closeArchiveEntry();
}
tarInputStream.close();
createTarArchiveEntry("config.json", configData, tarOutputStream);
tarOutputStream.finish();
// Convert tarOutputStream to byte array and return
private static void createTarArchiveEntry(String fileName, byte[] configData, TarArchiveOutputStream tOut)
throws IOException {
ByteArrayInputStream baOut1 = new ByteArrayInputStream(configData);
TarArchiveEntry tarEntry = new TarArchiveEntry(fileName);
tarEntry.setSize(configData.length);
tOut.putArchiveEntry(tarEntry);
byte[] buffer = new byte[1024];
int len;
while ((len = baOut1.read(buffer)) > 0) {
tOut.write(buffer, 0, len);
}
tOut.closeArchiveEntry();
}
How to convert tarOuputStream to byte array?
You have opened the several OutputStream instances, but you haven't closed them yet. Or more precisely, you haven't "flushed" the content, specially the BufferedOutputStream instance.
BufferedOutputStream is using an internal buffer to "wait" for the data written to the target OutputStream. It does so until there is a reason to do so. One of these "reasons" is to call the BufferedOutputStream.flush() method:
public void flush() throws IOException
Flushes this buffered output stream. This forces any buffered output bytes to be written out to the
underlying output stream.
One other "reason" is to close the stream so it will write the remaining bytes before closing the stream.
In your case the bytes being written are still stored in the internal buffer. Depending on your code structure, you can simply close all the OutputStream instances you have, so the bytes finally gets written to the ByteArrayOutputStream:
tarInputStream.close();
createTarArchiveEntry("config.json", configData, tarOutputStream);
tarOutputStream.finish();
// Convert tarOutputStream to byte array and return
tarOutputStream.close();
gzOut.close();
buffOut.close();
fOut.close();
byte[] content = fOut.toByteArray();
Related
I've got a String array that contains the content for a downloadable file. I am converting it to a Stream for the download but there are some random values in the downloadfile. I don't know if it is due to the encoding and if yes, how can I change it?
var downloadButton = new DownloadLink(btn, "test.csv", () -> {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
for (int i = 0; i < downloadContent.size(); i++) {
objectOutputStream.writeUTF(downloadContent.get(i));
}
objectOutputStream.flush();
objectOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.close();
return new ByteArrayInputStream(byteArray);
This is the DownloadLink class.
public class DownloadLink extends Anchor {
public DownloadLink(Button button, String fileName, InputStreamFactory fileProvider) {
super(new StreamResource(fileName, fileProvider), "");
getElement().setAttribute("download", fileName);
add(button);
getStyle().set("display", "contents");
}
}
this is the output file
ObjectOutputStream is part of the Java serialization system. In addition to the data itself, it also includes metadata about the original Java types and such. It's only intended for writing data that will later be read back using ObjectInputStream.
To create a file for others to download, you could instead use a PrintWriter that wraps the original output stream. On the other hand, you're using the output stream to create a byte[] which means that a more straightforward, but slightly less efficient, way would be to create a concatenated string from all the array elements and then use getBytes(StandardCharsets.UTF_8) on it to directly get a byte array.
I am writing a web service in JAVA using Apache CXF.
So, I have a method whose prototype is following:
public Response upload(#Multipart("id") int Id,
#Multipart("file") Attachment attachment) {
Now, I want to convert this attachment to byte[] . How can I do it?
Here is how you can read the content of the attachment and store it inside a byte array. Alternatively you can write directly to an OutputStream and skip the conversion to byte[].
DataHandler dataHandler = attachment.getDataHandler();
final byte[] data;
try (InputStream inputStream = dataHandler.getInputStream()) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final byte[] buffer = new byte[4096];
for (int read = inputStream.read(buffer); read > 0; read = inputStream.read(buffer)) {
outputStream.write(buffer, 0, read);
}
data = outputStream.toByteArray();
}
//todo write data to BLOB
If you want to be more memory efficient or if the attachment does not fit into memory, you can write directly to the blob's output stream. Just replace the ByteArrayOutputStream with OutputStream outputStream = blob.setBinaryStream(1);
I'm writing my byte array to a file:
PrintWriter pw = new PrintWriter(new FileOutputStream(fileOutput, true));
pw.write(new String(cryptogram, Charset.defaultCharset()));
pw.close();
Then, I am reading it from the file like this:
String cryptogramString = new String();
while (scPriv.hasNext()) {
linePriv = scPriv.nextLine();
cryptogramString += linePriv;
}
But I don't know how to make byte[] from cryptogramString. I'am trying this:
byte[] b = cryptogramString.getBytes(Charset.defaultCharset());
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(cryptogram));
But it doesn't return the same values. Does anyone have an idea how to make this right?
You should decide whether you are writing text or binary.
Encrypted data is always binary which means you shouldn't be using Reader/Writer/String classes.
try (FileOutputstream out = new FileOutputStream(filename)) {
out.write(bytes);
}
to read back in
byte[] bytes = new byte[(int) (new File(filename).length())];
try (FileInputstream in = new FileInputStream(filename)) {
in.read(bytes);
}
I have a file that contains xml and then plain text, so i cant read a file as a whole
You also can't write binary into a text file. You can encode it using base64.
Storing base64 data in XML?
I am using this approach for storing data in a file from responce of Server.
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
response.getEntity().writeTo(outstream);
byte[] responseBody = outstream.toByteArray();
String data = new String(responseBody);
FileOutputStream out = new FileOutputStream(new File(my_path));
out.write(data.getBytes());
out.flush();
out.close();
It's working fine and my file gets created and size of it is 3786 bytes.
Now consider this ,
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
response.getEntity().writeTo(outstream);
byte[] responseBody = outstream.toByteArray();
FileOutputStream out = new FileOutputStream(new File(my_path));
out.write(responseBody);
out.flush();
out.close();
it gives filesize of 1993 bytes.
Can anybody help me understand this , Does this new String(responseBody) do something to responcebytes like some encoding ?
Any help would be appreciated.
Yes, constructing a String from bytes decodes the bytes according to the current default character encoding (if one is not explicitly specified). Also String.getBytes() does the same in reverse (and may not necessarily produce the same sequence of bytes that was used to create it).
A String holds text. If your data is raw binary data and is intended to be treated as such, you should not be storing it in a String, you should be storing it in a byte[].
There is no need to have String data at all in that first bit, just write the byte[] to the file:
byte[] responseBody = outstream.toByteArray();
String data = new String(responseBody);
...
out.write(data.getBytes());
Can just be:
byte[] responseBody = outstream.toByteArray();
...
out.write(responseBody);
I tried to compress a string with DeflaterOutputStream and converted the output with base64 to save the result in another string
public static String compress(String str) throws IOException {
byte[] data = str.getBytes("UTF-8");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
java.util.zip.Deflater compresser = new java.util.zip.Deflater(java.util.zip.Deflater.BEST_COMPRESSION, true);
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(stream, cozmpresser);
deflaterOutputStream.write(data);
deflaterOutputStream.close();
byte[] output = stream.toByteArray();
return Base64Coder.encodeLines(output);
}
Now i wish to try ZipOutputStream. i tried
public static String compress(String str) throws IOException {
byte[] data = str.getBytes("UTF-8");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ZipOutputStream deflaterOutputStream = new ZipOutputStream(stream);
deflaterOutputStream.setMethod(ZipOutputStream.DEFLATED);
deflaterOutputStream.setLevel(8);
deflaterOutputStream.write(data);
deflaterOutputStream.close();
byte[] output = stream.toByteArray();
return Base64Coder.encodeLines(output);
}
But dont work. ZipOutputStream seems orientated to a structure of folders and files
how can I do?
ZipOutputStream is intended to produce a Zip file, which, as you noticed, is generally used as a container for files and folders (a "compressed folder" or "compressed directory tree", in other words).
If you merely want to compress a string and then convert it to some printable form, ZipOutputStream isn't really the right choice. GZIPOutputStream is more appropriate to that purpose, in my opinion.
Since you marked this question with an android tag, note the comment here: http://developer.android.com/reference/java/util/zip/GZIPOutputStream.html
Using GZIPOutputStream is a little easier than ZipOutputStream because GZIP is only for compression, and is not a container for multiple files.