So I have a program that is supposed to encode UTF-8 Base64, but is not. My Encoder code is as follows:
public class Encoder {
public static void Encode() throws IOException{
byte[] bytes = Base64.encodeBase64(readFile("C:\\Users\\Dragon\\Desktop\\Binary\\Diamond.png", StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8));
String binary = new String(bytes);
PrintWriter out = new PrintWriter("C:\\Users\\Dragon\\Desktop\\Binary\\Base64.txt");
out.println(binary);
out.close();
System.out.println("Your File has been saved at C:\\Users\\Dragon\\Desktop\\Binary\\Base64.txt");
}
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}
And when I decode it with this website (That has UTF-8 Functionality): http://www.base64decode.org/ I get:
Input (My code made this):
77+9UE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/vv73vv71hAAAAGHRFWHRBdXRob3IAbWluZWNyYWZ0aW5mby5jb23vv71mJ0sAAADvv71JREFUOO+/vWPvv73vv73vv70/AyUY77+9QAM877+9Bu+/ve+/vTHvv708XgNAGu+/vQHvv70hOA3vv71pXu+/ve+/vTkcX++/ve+/ve+/ve+/ve+/vSjvv71gNQDvv70Z77+9Ae+/vRkE77+977+9XgRj77+9De+/vWkEGQTvv70gA++/vV3vv71hAO+/ve+/vS/vv71Q77+977+977+9RhRX77+9NQBkIy4DYO+/ve+/vWkASO+/ve+/vdmNWA3vv73vv73vv70GY++/vQbvv70CDO+/vQEZ77+9DAVhEBvvv70B77+9QARpBu+/vQLvv70A77+9MDHvv71hADMA77+9R1wG77+9bCfvv73vv73vv73vv73vv73vv71077+977+9Mjbvv703KVPvv70b77+977+9AB0QYe+/vV4VTO+/vQAAAABJRU5E77+9QmDvv70=
Expected output from website:
‰PNG
IHDR óÿa tEXtAuthor minecraftinfo.comßf'K ²IDAT8Ëcøÿÿ?%Á#<æÿ‘1º<^#к!8
€i^ôí9_üõù¿Áí½(†`5 ¦¤¦¼Þ^c¢
€ià ]a ºæž/P°ÂÔFWà5 d#.`®Ài H³ÎÙX
®Îc¼À¤ƒa«°#iÙÓ Ã01œa 3 äG\Àl'˜Œît¢“26Œ7)SœÉÅ aÍ^L‹ IEND®B`‚
Actual output From website:
�PNG
IHDR��atEXtAuthorminecraftinfo.com�f'K�IDAT8�c���?%�#<���1�<^#��!8
�i^��9_�����(�`5�����^c�
�i� �]�a��/�P���FW�5d#.`��iH��ٍX
���c����a��#i���01�a3�G\�l'������t��26�7)S���a�^L�IEND�B`�
However, when I encode the same exact thing using this site and not my code, It DOES have UTF-8 Formatting and decodes correctly. So what am I doing wrong?
You Base64.encodeBase64 take byte[] as input. You should pass result of Files.readAllBytes(Paths.get(path)) to Base64.encodeBase64 directly.
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 want to encode a string in Base64 for later decoding it. I encode it doing this:
public static String encryptString(String string) {
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes());
return (new String(bytesEncoded));
}
Then, the encoded string is stored on disk using UTF-8. After restarting the application, the encoded string is readed from disk and I'm trying to decode the string using this:
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string);
return (new String(valueDecoded));
}
Something is wrong because it is giving me this exception:
java.lang.IllegalArgumentException: Illegal base64 character d
at java.base/java.util.Base64$Decoder.decode0(Base64.java:743)
at java.base/java.util.Base64$Decoder.decode(Base64.java:535)
at java.base/java.util.Base64$Decoder.decode(Base64.java:558)
This is a TRACE step by step
1º i encode this: {"configuration":{"shop":{"name":"","addressLine1":"","addressLine2":"","postalCode":"","city":"","country":"","phoneNumber":""}},"jointBets":[],"groups":[{"name":"Test","members":[]}]}
into this: eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IiIsImFkZHJlc3NMaW5lMSI6IiIsImFkZHJlc3NMaW5lMiI6IiIsInBvc3RhbENvZGUiOiIiLCJjaXR5IjoiIiwiY291bnRyeSI6IiIsInBob25lTnVtYmVyIjoiIn19LCJqb2ludEJldHMiOltdLCJncm91cHMiOlt7Im5hbWUiOiJUZXN0IiwibWVtYmVycyI6W119XX0=
2º i store it on disk in utf8
3º i retreive it from disk and it's this string:
eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IiIsImFkZHJlc3NMaW5lMSI6IiIsImFkZHJlc3NMaW5lMiI6IiIsInBvc3RhbENvZGUiOiIiLCJjaXR5IjoiIiwiY291bnRyeSI6IiIsInBob25lTnVtYmVyIjoiIn19LCJqb2ludEJldHMiOltdLCJncm91cHMiOlt7Im5hbWUiOiJUZXN0IiwibWVtYmVycyI6W119XX0=
4º i decode it and get the exception.
The old Base64 utility add linebreaks every 76 characters in Java8.
The result looks like that:
/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a
HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy
MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
...
It seems that this behaviour changed with some version. At least with Java11 the decoder is not accepting line-breaks anymore.
To avoid the problem you could change you method
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string.replace("\n","").replace("\r","");
return new String(valueDecoded);
}
Then, the encoded string is stored on disk using UTF-8. After
restarting the application, the encoded string is readed from disk and
I'm trying to decode the string using this:
This seems to be a point of failure. Most likely your problem is OS/JDK dependent Apparently the following code seems to work well for me (Win 7, latest JDK 1.8):
public static void main(String[] args) throws IOException {
String source = "{\"configuration\":{\"shop\":{\"name\":\"España\",\"addressLine1\":\"\",\"addressLine2\":\"\"," +
"\"postalCode\":\"\",\"city\":\"\",\"country\":\"\",\"phoneNumber\":\"\"}},\"jointBets\":[]," +
"\"groups\":[{\"name\":\"Test\",\"members\":[]}]}";
// Encode string
String encoded = encryptString(source);
System.out.println("Base64 encoded: " + encoded);
// Temp Dir
String tempDir = System.getProperty("java.io.tmpdir");
// Write to File
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempDir + "data.txt"))) {
writer.write(encoded);
}
// Read from File
Path path = Paths.get(tempDir + "data.txt");
Stream<String> lines = Files.lines(path);
String dataFromFile = lines.collect(Collectors.joining("\n"));
lines.close();
// Compare content
assert encoded.equals(dataFromFile);
// Decode string
String decoded = decryptString(dataFromFile);
System.out.println("Base64 decoded: " + decoded);
}
public static String encryptString(String string) {
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes(StandardCharsets.UTF_8));
return new String(bytesEncoded);
}
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string);
return new String(valueDecoded);
}
Base64 encoded:
eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IkVzcGHDsWEiLCJhZGRyZXNzTGluZTEiOiIiLCJhZGRyZXNzTGluZTIiOiIiLCJwb3N0YWxDb2RlIjoiIiwiY2l0eSI6IiIsImNvdW50cnkiOiIiLCJwaG9uZU51bWJlciI6IiJ9fSwiam9pbnRCZXRzIjpbXSwiZ3JvdXBzIjpbeyJuYW1lIjoiVGVzdCIsIm1lbWJlcnMiOltdfV19
Base64 decoded:
{"configuration":{"shop":{"name":"España","addressLine1":"","addressLine2":"","postalCode":"","city":"","country":"","phoneNumber":""}},"jointBets":[],"groups":[{"name":"Test","members":[]}]}
My guess is that you are not specifying a charset. Try running the below maybe with and without the charset specified for the String constructor to verify.
#Test
public void base64Test() throws Exception{
String string = "ABCDF";
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes());
String encodedStr = (new String(bytesEncoded,Charset.forName("ISO-8859-1")));
System.out.println(encodedStr);
byte[] valueDecoded = Base64.getDecoder().decode(encodedStr);
String decodedStr = (new String(valueDecoded,Charset.forName("ISO-8859-1")));
System.out.println(decodedStr);
}
Issues in converting base64 decoded byte array to String in java :
public static String decode(String strcontent) throws Exception
{
BASE64Decoder decoder = new BASE64Decoder();
byte[] imgBytes = decoder.decodeBuffer(strcontent);
return new String(imgBytes);
}
With the above code; was trying to create a string out of the Base 64 decoded byte array (imgBytes ) & input strcontent is base 64 encoded string. For text files it working fine , but for PDF and image files the string conversion is having issues. Have tried different encoding as UTF-8 , UTF 16 etc. But no use. The returned string is different than the original one.
When tried to write the byte array to a file like :
OutputStream out = new FileOutputStream(##path);
out.write(imgBytes);
out.close();
File is getting created properly without any issues.
I tried the below code:
byte[] imgBytes= ( new String(imgBytes1)).getBytes(); //Converting to String and back to bytes
OutputStream out = new FileOutputStream(##Filename);
out.write(imgBytes); out.close();
This time the image file is corrupted.
Please suggest.
Here i have a code which accept a file content in byte array, i want to check whether its in base64 format or not,before converting it to base64 and returning.. can anyone help me out here
import sun.misc.BASE64Encoder;
public static String encodeInByteArray(byte[] b)
{
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(b);
}
Below is the code which i tried to check for base64 format:
import sun.misc.BASE64Encoder;
import java.util.regex.Pattern;
public class Encoder
{
public static String encodeInByteArray(byte[] b)
{
String regex =
"([A-Za-z0-9+/]{4})*"+
"([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)";
Pattern patron = Pattern.compile(regex);
String s=b.toString();
if (!patron.matcher(s).matches()){
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(b);
}
else
return s;
}
public static void main(String [] args) throws FileNotFoundException
{
FileInputStream fs= new FileInputStream("Sample.pdf");
String s= fs.toString();
byte[] b = s.getBytes();
encodeInByteArray(b);
}
}
Calling b.toString() doesn't do what you might expect - the resulting string will be something like [B#106d69c, because arrays don't override toString. (In a similar vein, calling fs.toString() won't give you the contents of the file as a string).
To get a String from a byte[], use the constructor:
new String(b)
But you probably want to specify a particular charset, e.g.:
new String(b, StandardCharsets.ISO_8859_1)
otherwise you may get different results, depending upon your JVM's configuration.
First solution you could parse the file, or parse the file part way (to save resources) and determine if a line is base64 encoded. See this answer for the String base64 encoding check.
How to check whether the string is base64 encoded or not
A second solution would be is that if you have complete control over the file saving and encoding, you could place a byte at the head or tail of the file indicated if its base64 encoded or not, which should be faster then the above solution.
You can use Base64.isBase64(byte[] arrayOctet) from apache's commons-codec.
Be aware that whitespaces are valid at the moment as stated in the documentation.
I need some consulting here.
I'm writing a client/server software.
One requirement is to use an XML file to transfer information between the client and the server. This decision was made to allow clients to be created on any language. I know I could use json for simpler communication, but I needed a better Object to Text Mapping, so I ended up with XML. So, to diminish the XMl size problem, I decided to compress it before sending over socket. On top of it, I want to encrypt the data so it will be harder to be broken by some interceptor. I have read a lot about encrypting and encryption types, but for testing purposes I'll just use Base64 and generic compression just to join up all the technologies, than I'll specialize the specifics. I found a lot of code and good advice here on stack exchange, and now I'm having some trouble.
What I have:
In memory Objects;
Static methods to convert Objects to XML in memory;
No use for Serialization because the clients can be written on C, .net, perl, etc;
Avoid disk write to reduce disk I/O, keeping everything in-memory;
The need to work with punctuation chars (UTF-8);
The need to work with stronger encrypt on the future;
The process I idealized is:
Convert object to XML - OK
Establish Client/server communication - OK
Encode XML String to Base64 - OK (no compression)
3.1. Compress XML String and than encode to Base64 - OK
Transfer between client/server - OK
Decode Base64 String to XML String - OK
5.1. Uncompress transferred byte array and decode Base64 - NOT OK
So, I can't find where I'm getting wrong on the "Compress String -> Encode it to Base64 -> transmit -> decode Base64 to String -> uncompress it" process... Here is the snippet from my code "inspired" on stack overflow:
I'm using this answer (with .net compatibility) as a reference to compress/uncompress:
How can I Zip and Unzip a string using GZIPOutputStream that is compatible with .Net?
public class Compressor2 {
public static byte[] compress(String string) throws IOException {
byte[] blockcopy = ByteBuffer
.allocate(4)
.order(java.nio.ByteOrder.LITTLE_ENDIAN)
.putInt(string.length())
.array();
ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(string.getBytes());
gos.close();
os.close();
byte[] compressed = new byte[4 + os.toByteArray().length];
System.arraycopy(blockcopy, 0, compressed, 0, 4);
System.arraycopy(os.toByteArray(), 0, compressed, 4, os.toByteArray().length);
compressed = MyBase64.encode(new String(compressed)).getBytes();
return compressed;
}
public static String decompress(byte[] compressed) throws IOException {
compressed = MyBase64.decode(new String(compressed)).getBytes();
System.out.println(compressed);
System.out.println(new String(compressed));
final int BUFFER_SIZE = 32;
//ByteArrayInputStream is = new ByteArrayInputStream(compressed, 4, compressed.length - 4);
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}
from MyBase 64:
public static String encode(String text) throws UnsupportedEncodingException {
byte[] encodedBytes = Base64.encodeBase64(text.getBytes());
return new String(encodedBytes, "UTF-8");
}
public static String decode(String text) throws UnsupportedEncodingException {
byte[] decodedBytes = Base64.decodeBase64(text);
return new String(decodedBytes, "UTF-8");
}
and the test case:
/**
* Test of compress method, of class Compressor2.
*/
#Test
public void testCompress() throws Exception {
System.out.println("compress");
String string = "Hello all, how can I transfer this with punctuation? like á é í ó ú";
byte[] expResult = Compressor2.compress(string);
byte[] result = Compressor2.compress(string);
System.out.write(result);
System.out.print("\n");
System.out.println(new String(result));
assertArrayEquals(expResult, result);
for (byte character : result) {
System.out.print(String.valueOf(character));
}
System.out.print("\n");
for (byte character : result) {
System.out.print((character));
}
System.out.print("\n");
}
/**
* Test of decompress method, of class Compressor2.
*/
#Test
public void testDecompress() throws Exception {
System.out.println("decompress");
String expResult = "Hello all, how can I transfer this with punctuation? like á é í ó ú";
//String expResult = "The lazy dog ate an apple";
byte[] compressed = Compressor2.compress(expResult);
System.out.println(expResult);
System.out.write(compressed);
System.out.print("\n");
System.out.println("going to decompress");
String result = Compressor2.decompress(compressed);
System.out.println(result);
assertEquals(expResult, result);
// TODO punctuation errors?
}
System Out for checking the values:
compress
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
811196565656647118118554873656565656565656565658811811855511181185548785555435777651196955554357868852651001174347118101434711884721181185551118118554811170117434711882771085555435777103561086682851005555435770434347118875310655554357651087410055554357555543578267761181185548799850841181185551118118554871555543575555435777101434711884801181185551118118554999555543575555435785681079099837011712073785269101434711881471101105369788365656565656161
811196565656647118118554873656565656565656565658811811855511181185548785555435777651196955554357868852651001174347118101434711884721181185551118118554811170117434711882771085555435777103561086682851005555435770434347118875310655554357651087410055554357555543578267761181185548799850841181185551118118554871555543575555435777101434711884801181185551118118554999555543575555435785681079099837011712073785269101434711881471101105369788365656565656161
decompress
Hello all, how can I transfer this with punctuation? like á é í ó ú
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
going to decompress
[B#19f9bdc4
C
Sorry for the long post, I'm trying to give you something to work on to check where I'm getting this wrong. I Appreciate any help...
Edit.: Forgot to say, if you take the "MyBase64.decode or encode" line from the Compressor2 Classe, it works like a charm...