I am base64 encoding an excel file, send it somewhere where it is saved. Apparently after this, excel complains that the file is incorrect and if I want to attept a restore. The code I am doing (actually I did a quick test main method) is:
public static void main(String[] args) throws IOException {
Path p = Paths.get("C:\\VariousJunk\\excel-test", "test.xlsx");
ByteArrayOutputStream base64StringOutputStream = new ByteArrayOutputStream();
OutputStream base64EncodingStream = Base64.getEncoder().wrap(base64StringOutputStream);
Files.copy(p, base64EncodingStream);
base64StringOutputStream.close();
String b64 = base64StringOutputStream.toString();
byte[] data = Base64.getDecoder().decode(b64);
FileOutputStream fos = new FileOutputStream("C:\\VariousJunk\\excel-test\\test-backup.xlsx");
fos.write(data);
fos.close();
}
Now I have compared binary data of both files and it appears, that the output file is only missing one last byte with value 0. I have added the last bit for the test
fos.write(data);
fos.write(0);
fos.close();
And it works fine. The problem is I will be using this for any other type of data, and so I am not sure whether hardcoding a last byte is a good idea, possibly it might crash other filetypes. Is this a feature of this Base64 encoding method or am I doing something wrong?
Apparently the missing bit was base64EncodingStream.close() just after Files.copy()
OutputStream base64EncodingStream = Base64.getEncoder().wrap(base64StringOutputStream);
Files.copy(p, base64EncodingStream);
base64EncodingStream.close();
String b64 = base64StringOutputStream.toString();
Related
I have a byte array file with me which I am trying to convert into human readable. I tried below ways :
public static void main(String args[]) throws IOException
{
//System.out.println("Platform Encoding : " + System.getProperty("file.encoding"));
FileInputStream fis = new FileInputStream("<Path>");
// Using Apache Commons IOUtils to read file into byte array
byte[] filedata = IOUtils.toByteArray(fis);
String str = new String(filedata, "UTF-8");
System.out.println(str);
}
Another approach :
public static void main(String[] args) {
File file = new File("<Path>");
readContentIntoByteArray(file);
}
private static byte[] readContentIntoByteArray(File file) {
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
try {
FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
for (int i = 0; i < bFile.length; i++) {
System.out.print((char) bFile[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}
These codes are compiling but its not yielding output file in a human readable fashion. Excuse me if this is a repeated or basic question.
Could someone please correct me where I am going wrong here?
Your code (from the first snippet) for decoding a byte file into a UTF-8 text file looks correct to me (assuming FileInputStream fis = new FileInputStream("Path") is yielding the correct fileInputStream) .
If you're expecting a text file format but are not sure which encoding the file format is in (perhaps it's not UTF-8) , you can use a library like the below to find out.
https://code.google.com/archive/p/juniversalchardet/
or just explore some of the different Charsets in the Charset library and see what they produce in your String initialization line and what you produce:
new String(byteArray, Charset.defaultCharset()) // try other Charsets here.
The second method you show has associated catches with byte to char conversion , depending on the characters, as discussed here (Byte and char conversion in Java).
Chances are, if you cannot find a valid encoding for this file, it is not human readable to begin with, before byte conversion, or the byte array file being passed to you lost something that makes it decodeable along the way.
I'm trying to write the data from a picture I am encoding through Base64 to byte array then to the file that will be read by a plc program later on
This is meant to be used by a plc program later. (The plc is attached to a laser cutter.) I've tried to use FileOutputStream() as a way to write the data which with my current method did not turn out too dandy.
public static void main(String[] args)throws Exception {
File file = new File("$PATH");
File outputFile = new File("$OutputFilePath");
String encodeString = encodeFile(file);
System.out.println(encodeString);
}
private static String encodeFile(File file) throws Exception{
FileInputStream fileReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileReader.read(bytes);
return new String(Base64.getEncoder().encode(bytes), "UTF-8");
}
The code above does not provide my current attempts of making my program work the intended way but I am lost as of now but i was hoping that you might be able to shed some light on what I should do to end up in the right direction.
Requirement: compress a byte[] to get another byte[] using java.util.zip.ZipOutputStream BUT without using any files on disk or in-memory(like here https://stackoverflow.com/a/18406927/9132186). Is this even possible?
All the examples I found online read from a file(.txt) and write to a file(.zip). ZipOutputStream needs a ZipEntry to work with and that ZipEntry needs a file.
However, my use case is as follows: I need to compress a chunk (say 10MB) of a file at a time using a zip format and append all these compressed chunks to make a .zip file. But, when I unzip the .zip file then it is corrupted.
I am using in-memory files as suggested in https://stackoverflow.com/a/18406927/9132186 to avoid files on disk but need a solution without these files also.
public void testZipBytes() {
String infile = "test.txt";
FileInputStream in = new FileInputStream(infile);
String outfile = "test.txt.zip";
FileOutputStream out = new FileOutputStream(outfile);
byte[] buf = new byte[10];
int len;
while ((len = in.read(buf)) > 0) {
out.write(zipBytes(buf));
}
in.close();
out.close();
}
// ACTUAL function that compresses byte[]
public static class MemoryFile {
public String fileName;
public byte[] contents;
}
public byte[] zipBytesMemoryFileWORKS(byte[] input) {
MemoryFile memoryFile = new MemoryFile();
memoryFile.fileName = "try.txt";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry(memoryFile.fileName);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.finish();
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
Scenario 1:
if test.txt has small amount of data (less than 10 bytes) like "this" then unzip test.txt.zip yeilds try.txt with "this" in it.
Scenario 2:
if test.txt has larger amount of data (more than 10 bytes) like "this is a test for zip output stream and it is not working" then unzip test.txt.zip yields try.txt with broken pieces of data and is incomplete.
this 10 bytes is the buffer size in testZipBytes and is the amount of data that is compressed at a time by zipBytes
Expected (or rather desired):
1. unzip test.txt.zip does not use the "try.txt" filename i gave in the MemoryFile but rather unzips to filename test.txt itself.
2. unzipped data is not broken and yields the input data as is.
3. I have done the same with GzipOutputStream and it works perfectly fine.
Requirement: compress a byte[] to get another byte[] using java.util.zip.ZipOutputStream BUT without using any files on disk or in-memory(like here https://stackoverflow.com/a/18406927/9132186). Is this even possible?
Yes, you've already done it. You don't actually need MemoryFile in your example; just delete it from your implementation and write ZipEntry entry = new ZipEntry("try.txt") instead.
But you can't concatenate the zips of 10MB chunks of file and get a valid zip file for the combined file. Zipping doesn't work like that. You could have a solution which minimizes how much is in memory at once, perhaps. But breaking the original file up into chunks seems unworkable.
I need to encode/decode pdf file into Base64 format.
So I read file from disk into String(because I will receive file in String Base64 format in future);
String pdfString = IOUtils.toString(new FileInputStream(new
File("D:\\vrpStamped.pdf")));
byte[] encoded = Base64.encodeBase64(pdfString.getBytes());
byte[] newPdfArray = Base64.decodeBase64(encoded);
FileOutputStream imageOutFile = new FileOutputStream(
"D:\\1.pdf");
imageOutFile.write(newPdfArray);
imageOutFile.close();
imageOutFile.flush();
So my D:\\1.pdf doesnt opens in AdobeReader, but if I read file straight to byte array, using IOUtils.toByteArray(..) instead ,all works fine and my D:\\1.pdf file sucessfuly opens in Adobe Reader:
byte[] encoded = Base64.encodeBase64(IOUtils.toByteArray(new FileInputStream(new File("D:\\vrpStamped.pdf"))););
It seems to me thath IOUtils.toString(..) change something inside file content. So how can I convert file to String with not content breaking?
How to encode a pdf...
byte[] bytes = IOUtils.toByteArray(new FileInputStream(new File("/home/fschaetz/test.pdf")));
byte[] encoded = Base64.encode(bytes);
String str = new String(encoded);
...now do something with this encoded String, for example, send it via a Rest service.
And now, if you receive an encoded String, you can decode and save it like this...
byte[] decoded = Base64.decode(str.getBytes());
FileOutputStream output = new FileOutputStream(new File("/home/fschaetz/result.pdf"));
output.write(decoded);
output.close();
Works perfectly fine with all files, not limited to images or pdfs.
What your example is doing is...
Read the pdf into a String (which pretty much destroys the data, since you are reading binary data into a String)
Encode this spring (which is in all likelyhood not a valid representation of the original pdf anymore)
Decode it and save it to disk
I am trying to save a base64 decoded string into a zip file using the mentioned code:
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("/home/wemohamm/Desktop/test.zip")));
out.write(decodedString);
out.close();
Here decodedString contains base64 decoded string and I can output it.
I am running the code in rhel6 with Java 1.6. When I try to open the zip, it says error occurred while opening file.
The same code if I use with Windows 7 Java 1.6 with path c:\\test\test.zip is working fine.
Is the zip not getting saved correctly in rhel6 or if there is any code modifications I need to do?
Don't create a string from your byte array (String decodedString = new String(byteArray);), to then use an OutputStreamWriter to write the string, because then you are running the risk of introducing encoding issues that are platform dependent.
Just use FileOutputStream to write out the byte array (byte[] byteArray) directly to file.
Something like:
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("/home/wemohamm/Desktop/test.zip"), 4096)) {
out.write(byteArray);
}
Actually, the above requires java 1.7+, because of the new try-with-resources statement.
For Java 1.6, you can do this:
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream("/home/wemohamm/Desktop/test.zip"), 4096);
out.write(byteArray);
} finally {
if (out != null) {
out.close();
}
}
That won't work. You are writing to a ordinary file without packing the content. Use the java zip library with ZipOutputStream, ZipEntry and so on.