3

In my C# application, I am having a Bitmap encoded to a base64 string sent over from an android application, then I decode it and set it equal to a byte array.

I get this exception though:

"A first chance exception of type 'System.FormatException' occurred in mscorlib.dll".

Android Side:

byte[] iconByteArray = null; 
ByteArrayOutputStream baos = new ByteArrayOutputStream();  
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baos); //Bitmap bitmap created elsewhere
iconByteArray = baos.toByteArray();
encodedIcon = Base64.encodeToString(iconByteArray, Base64.DEFAULT);
return encodedIcon;

C# Side:

byte[] arr = System.Convert.FromBase64String(encodedIcon); //this throws that exception

Does anyone know of the cause? I'm guessing the format of the Base64 string in Java is not able to be decoded so simply by the C# application? It looks like I may have to do something like this and replace some characters? I tried this solution and got the same exception.

The string sent through Android looks like this

"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK\nCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU\nFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABgAGADASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD8qq2t\nG8EeIvENqbrStC1PUrYMUM1pZyyoGHUZVSM8jj3rFr9av2Ipl+Gf7PHh+xn1qfzNQL6rttY5AsYm\nCsEPzDJAHJx3roo4atiW1QjzNHBi8fhcBFSxU+VPRaN/kmfl9/wqrxp/0KWu/wDgsn/+Io/4VV40\n/wChS13/AMFk/wD8RX7cj4m"

Community
  • 1
  • 1
parameter
  • 894
  • 2
  • 18
  • 35
  • Have you tried to decode the base64 string with any other tools? What class is `Base64` in Java? – David Conrad Sep 09 '14 at 22:42
  • Assuming `android.util.Base64`. Does the data really have those literal "\n" sequences in it instead of newlines? – David Conrad Sep 09 '14 at 22:45
  • Did you compare the encodedIcon string that was received in the C# app to the one that was sent from the Android app? Are they the same or different? – Russ Sep 09 '14 at 22:46
  • @DavidConrad yes it does...maybe I should try to replace those on the C# side with a different character? – parameter Sep 09 '14 at 22:46
  • @Russ yea they're the same on both sides – parameter Sep 09 '14 at 22:46
  • actually the C# may have automatically included the \n's, testing now – parameter Sep 09 '14 at 22:50
  • 1
    I replaced them with newlines and tried to decode it with the command line base64 utility in Cygwin, and it almost worked, but I had to removed the last three characters "j4m", so it seems like maybe it is also truncated? But perhaps you truncated what you posted here in order to just give a sample. – David Conrad Sep 09 '14 at 22:50
  • @DavidConrad "_I had to removed the last three characters_" You could add `=` instead. – AlexD Sep 09 '14 at 23:33
  • @AlexD Yes, realized that after reading your answer, although it is still truncated (doesn't represent a complete JPEG). – David Conrad Sep 09 '14 at 23:36

2 Answers2

4

Try

encodedIcon = encodedIcon.Replace(@"\n", "");
if(encodedIcon.Length % 4 != 0)
    // we may have 0, 1 or 2 padding '='
    encodedIcon += new string('=', 4 - encodedIcon.Length % 4);
byte[] arr = System.Convert.FromBase64String(encodedIcon);

According to Base64:

After encoding the non-padded data, if two octets of the 24-bit buffer are padded-zeros, two "=" characters are appended to the output; if one octet of the 24-bit buffer is filled with padded-zeros, one "=" character is appended. This signals the decoder that the zero bits added due to padding should be excluded from the reconstructed data. This also guarantees that the encoded output length is a multiple of 4 bytes.

AlexD
  • 32,156
  • 3
  • 71
  • 65
  • 1
    this seems to have done the track, but as you said, there's no promise that i'll only need one '=' sign...so is the surefire solution to find the modulus of my string's length/4 and then add that many = signs to it? – parameter Sep 09 '14 at 23:00
  • @user2739431 Are you sure that you do not have `=` in the encoded string? According to http://developer.android.com/reference/android/util/Base64.html, `NO_PADDING` is OFF by default. – AlexD Sep 09 '14 at 23:29
  • your fix worked, NO_PADDING on the android side would require me to pad it on the C# side, right? That's what I did and it fixed the issue. None of the outputs were padded from the Android side – parameter Sep 09 '14 at 23:34
  • 1
    @user2739431 Seems to be. But according to the documentation, `NO_PADDING` is OFF if you use `DEFAULT`. So I'd expect `=` padding. In addition, you can try `NO_WRAP` on Android side to get rid of `\n`s. – AlexD Sep 09 '14 at 23:37
0

In this line

encodedIcon = Base64.encodeToString(iconByteArray, Base64.DEFAULT);

you can change Base64.DEFAULT to Base64.NOWRAP

It removing \n from the encoded string.

Bob
  • 8,392
  • 12
  • 55
  • 96