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.
Related
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();
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 have a FileOutputStream in java that is reading the contents of UDP packets and saving them to a file. At the end of reading them, I sometimes want to convert the encoding of the file. The problem is that currently when doing this, it just ends up doubling all the contents of the file. The only workaround that I could think to do would be to create a temp file with the new encoding and then save it as the original file, but this seems too hacky.
I must be just overlooking something in my code:
if(mode.equals("netascii")){
byte[] convert = new byte[(int)file.length()];
FileInputStream input = new FileInputStream(file);
input.read(convert);
String temp = new String(convert);
convert = Charset.forName("US-ASCII").encode(temp).array();
fos.write(convert);
}
JOptionPane.showMessageDialog(frame, "Read Successful!");
fos.close();
}
Is there anything suspect?
Thanks in advance for any help!
The problem is the array of bytes you've read from the InputStream will be converted as if its ascii chars, which I'm assuming its not. Specify the InputStream encoding when converting its bytes to String and you'll get a standard Java string.
I've assumed UTF-16 as the InputStream's encoding here:
byte[] convert = new byte[(int)file.length()];
FileInputStream input = new FileInputStream(file);
// read file bytes until EOF
int r = input.read(convert);
while(r!=-1) r = input.read(convert,r,convert.length);
String temp = new String(convert, Charset.forName("UTF-16"));
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 have a web service that I am re-writing from VB to a Java servlet. In the web service, I want to extract the body entity set on the client-side as such:
StringEntity stringEntity = new StringEntity(xml, HTTP.UTF_8);
stringEntity.setContentType("application/xml");
httppost.setEntity(stringEntity);
In the VB web service, I get this data by using:
Dim objReader As System.IO.StreamReader
objReader = New System.IO.StreamReader(Request.InputStream)
Dim strXML As String = objReader.ReadToEnd
and this works great. But I am looking for the equivalent in Java.
I have tried this:
ServletInputStream dataStream = req.getInputStream();
byte[] data = new byte[dataStream.toString().length()];
dataStream.read(data);
but all it gets me is an unintelligible string:
data = [B#68514fec
Please advise.
You need to use a ByteArrayOutputStream, like this:
ServletInputStream dataStream = req.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int r;
byte[] buffer = new byte[1024*1024];
while ((r = dataStream.read(data, 0, buffer.length)) != -1) {
baos.write(buffer, 0, r);
}
baos.flush();
byte[] data = baos.toByteArray();
You are confusing with printing of java arrays. When you print any java object it is transformed to its string representation by implicit invocation of toString() method. Array is an object too and its toString() implementation is not too user friendly: it creates string that contains [, then symbolic type definition (B for byte in your case, then the internal reference to the array.
If you want to print the array content use Arrays.toString(yourArray). This static method creates user-friendly string representation of array. This is what you need here.
And yet another note. You do not read your array correctly. Please take a look on #Petter`s answer (+1) - you have to implement a loop to read all bytes from the stream.