I encode data of images in base64 using python before sending it to the server which is written in C#. The data that is received is identical to the data that is being sent. However, when I decode the encoded string I get a different result.
Here is the code that takes a screenshot and encodes it in base64:
screen_shot_string_io = StringIO.StringIO()
ImageGrab.grab().save(screen_shot_string_io, "PNG")
screen_shot_string_io.seek(0)
return base64.b64encode(screen_shot_string_io.getvalue())
it is sent as is to the server and the server receives the encoded string correcetly with no data corruption.
Here is the c# code that decodes the string:
byte[] decodedImg = new byte[bytesReceived];
FromBase64Transform transfer = new FromBase64Transform();
transfer.TransformBlock(encodedImg, 0, bytesReceived, decodedImg, 0);
So does anyone know why when the data is decoded the result is incorrect?
If it was me I would simply use the Convert.FromBase64String() and not mess with the FromBase64Transform. You don't have all the details here, so I had to improvise.
In Python I took a screen shot, encoded it, and wrote to file:
# this example converts a png file to base64 and saves to file
from PIL import ImageGrab
from io import BytesIO
import base64
screen_shot_string_io = BytesIO()
ImageGrab.grab().save(screen_shot_string_io, "PNG")
screen_shot_string_io.seek(0)
encoded_string = base64.b64encode(screen_shot_string_io.read())
with open("example.b64", "wb") as text_file:
text_file.write(encoded_string)
And in C# I decoded the file contents are wrote the binary:
using System;
using System.IO;
namespace Base64Decode
{
class Program
{
static void Main(string[] args)
{
byte[] imagedata = Convert.FromBase64String(File.ReadAllText("example.b64"));
File.WriteAllBytes("output.png",imagedata);
}
}
}
If you have a properly encoded byte array, then convert the array to string and then decode the string.
public static void ConvertByteExample()
{
byte[] imageData = File.ReadAllBytes("example.b64");
string encodedString = System.Text.Encoding.UTF8.GetString(imageData); //<-- do this
byte[] convertedData = Convert.FromBase64String(encodedString);
File.WriteAllBytes("output2.png", convertedData);
}
Related
Sorry in advance if you have a duplicate or a simple question! I can't find the answer.
I'm working with a dll made in Delphi. Data can be sent to the device using a DLL. However, at the time the data is sent, some strings are not accepted or are written blank. The data sent to the device is stored in a txt file. It was generated using txt file third party program.
That is, I think the string is in an indefinite format. If I send in utf-8 format, it receives all the information. But some strings at the time ???? ???? remains.
Many of my texts are in the Cyrillic alphabet.
What I did:
// string that send to device
[MarshalAsAttribute(UnmanagedType.LPStr, SizeConst = 36)]
public string Name;
When I did this, the device received only 10 out of 100 data.
If i encoding with UTF-8:
byte[] bytes = Encoding.Default.GetBytes(getDvsName[1].ToString());
string res = Encoding.UTF8.GetString(bytes);
Got all the data this way but too many strings are became as ??? ????.
Also i tried like this:
static private string Win1251ToUTF8(string source)
{
Encoding utf8 = Encoding.GetEncoding(«utf-8»);
Encoding win1251 = Encoding.GetEncoding(«windows-1251»);
byte[] utf8Bytes = win1251.GetBytes(source);
byte[] win1251Bytes = Encoding.Convert(win1251, utf8, utf8Bytes);
source = win1251.GetString(win1251Bytes);
return source;
}
All of the above methods did not help. How can I receive incoming information in the correct format? Are there other ways?
hi there here is what went wrong you did encode the string to default instead of utf8.
string tom = "ටොම් හැන්ක්ස්";
byte[] bytes = Encoding.UTF8.GetBytes(tom);
string res = Encoding.UTF8.GetString(bytes);
I am using C# and .NET to encode and decode base64 string. The following are snippets of my code:
Base64 encoding:
using (var stream = new MemoryStream())
…...
return Convert.ToBase64String(stream.ToArray());
}
Base64 decoding
byte[] bytes = Convert.FromBase64String(messageBody);
My code fails 99% of the time with 1% chance to succeed though. The stack trace is as follows:
5xx Error Returned:System.FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. at System.Convert.FromBase64_ComputeResultLength(Char inputPtr, Int32 inputLength) at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) at System.Convert.FromBase64String(String s)*
Does anyone know what can cause base64 decoding to fail? My encoding and decoding methods are symmetric and I am really confused about what can be the root cause for this issue?
Thanks for all your replies.
It turned out there were still some old messages in Json format that previously failed in getting delivered and kept retrying in our system; however the new code change of our receiving side got deployed and our receiving side starts to expect messages in protobuf format which results in Deserialization failure when receiving old Json format messages.
In order to debug an issue like this I usually write some tests or create a console app to watch the variables as they change from function to function.
One of the possible scenario's for base64 decoding to fail is if the decoder input is HTMLEncoded. This is common when you pass an encrypted string into a URL for example. It will automatically be HTML encoded and then it sometimes can and sometimes can't be decoded depending on the characters that the encoded output has.
Here's a simple console app to demonstrate this.
class Program
{
static void Main(string[] args)
{
string input = "testaa";
TestEncodeDecode("test");
TestEncodeDecode("testa");
TestEncodeDecode("testaa");
Console.ReadLine();
}
private static void TestEncodeDecode(string input)
{
string encoded = Encode(input);
Console.WriteLine($"Encoded: {encoded}");
string htmlEncoded = WebUtility.UrlEncode(encoded);
Console.WriteLine($"htmlEncoded: {htmlEncoded}");
string decodedString = Decode(htmlEncoded);
Console.WriteLine($"Decoded: {decodedString}");
Console.WriteLine();
}
private static string Decode(string htmlEncoded)
{
try
{
byte[] decoded = Convert.FromBase64String(htmlEncoded);
return Encoding.ASCII.GetString(decoded);
}
catch(Exception)
{
return "Decoding failed";
}
}
private static string Encode(string input)
{
byte[] bytes = Encoding.ASCII.GetBytes(input);
using (var stream = new MemoryStream())
{
stream.Write(bytes);
return Convert.ToBase64String(stream.ToArray());
}
}
}
You'll see that the first two arguments ("test" and "testa") fail to decode, but the third ("testaa") will succeed.
In order to "fix" this, change the Decode method as follows:
private static string Decode(string htmlEncoded)
{
try
{
string regularEncodedString = WebUtility.UrlDecode(htmlEncoded);
byte[] decoded = Convert.FromBase64String(regularEncodedString);
return Encoding.ASCII.GetString(decoded);
}
catch(Exception)
{
return "Decoding failed";
}
}
I am creating a Voice Authentication system, for that I am using third party API which stores my wav file and when I call GET, it returns the RIFF format encoded string in response.
I am not able to figure out a way to convert this RIFF into a wav file.
I tried below code, it is creating wav file but the wav is currupted:
using (var response = await httpClient.GetAsync(""))
{
string responseData = await response.Content.ReadAsStringAsync();
using (BinaryWriter writer = new BinaryWriter(System.IO.File.Open(#"C:\wavFile.wav", FileMode.Create)))
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(responseData);
writer.Write(data);
}
}
I tried ASCII along with UTF8 but same result. Can anyone help?
You should not read the response as a string. A wave file is binary data which may contain byte sequences which are not valid for strings.
The WebClient (MSDN) can directly download binary data without need of converting it.
using (var webClient = new WebClient())
{
byte[] wave = webClient.DownloadData("...");
}
If i read byte array from a file and write it using below code
byte[] bytes = File.ReadAllBytes(filePath);
File.WriteAllBytes(filePath, byteArr);
works perfectly fine.I can open and view the written file properly.
But if i read file contents into a string and then convert it to byte array using below function
string s = File.ReadAllText(filePath);
var byteArr = System.Text.Encoding.UTF8.GetBytes(s);
the size of byte array is more than the previous array read directly from file and the values are also different, hence if i write the file using this array the cannot be read when opened
Note:- File is utf-8 encoded
i found out that using below code
using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8, true))
{
reader.Peek(); // you need this!
var encoding = reader.CurrentEncoding;
}
Unable to understand why both the array differs??
I was using the below attached image for converting and then writing
With
using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8, true))
{
reader.Peek(); // you need this!
var encoding = reader.CurrentEncoding;
}
your var encoding will just echo the Encoding.UTF8 parameter. You are deceiving yourself there.
A binary file just has no text encoding.
Need to save a file may be anything an image or a text
Then just use ReadAllBytes/WriteAllBytes. A text file is always also a byte[], but not all file types are text. You would need Base64 encoding first and that just adds to the size.
The safest way to convert byte arrays to strings is indeed encoding it in something like base64.
Like:
string s= Convert.ToBase64String(bytes);
byte[] bytes = Convert.FromBase64String(s);
i am practicing encryption and decryption.
After i have decrypted some data, i convert the bytes to base64string and store it in a textfile.
After some time i want to decrypt it again, but for that to work i have to convert the content from base64string to bytes again.
I tried with this:
string path = #"C:\encrypt.txt";
string myfile = File.ReadAllText(path);
byte[] convertion = Convert.FromBase64String(myfile);
That will give me an error because the text is actually not a base64string.
Is there anyway to do an convertion?
you can use the following functions for saveing and read base64 strings
public static void WriteAllBase64Text(string path, string text)
{
File.WriteAllText(path, Convert.ToBase64String(Encoding.UTF8.GetBytes(text)));
}
public static string ReadAllBase64Text(string path)
{
var bytes=File.ReadAllText(path);
var encoded = System.Convert.FromBase64String(bytes);
return System.Text.Encoding.UTF8.GetString(encoded);
}