I am converting picture files into base64 Strings in order to store them in a .txt file and later retrieve them and re-convert them into images. In doing so, I discovered a funny misbehaviour on behalf of my StringBuilder
:
// **Example A, uses StringBuilder**
String[] filePaths = Directory.GetFiles(folderPath, "*.*");
StringBuilder sb = new StringBuilder();
ImageConverter converter = new ImageConverter();
StreamWriter sw = File.CreateText(filepathBase64);
foreach (String item in filePaths)
{
try
{
Bitmap picture = new Bitmap(item);
Byte[] byteArr = (Byte[])converter.ConvertTo(picture, typeof(Byte[]));
String base64 = Convert.ToBase64String(byteArr);
sb.AppendLine(base64);
}
catch { }
}
StreamWriter sw = File.CreateText(filepathBase64);
sw.Write(sb);
sw.Flush();
sw.Close();
That creates a .txt file containing lots of lines in base64 and one final empty line owed to the .AppendLine used with my Stringbuilder. When I later read these base64 Strings and convert them back into image objects, I have to be careful of this last line in order to avoid an exception, so I check for it like so:
//**Example A.1, checking for empty string
listBoxbilder.Items.Clear();
String[] myArr = File.ReadAllLines(filepathBase64);//last item will be empty string
foreach (String item in myArr)
{
if (item != String.Empty) //This is my validation
{
byte[] decodedFromBase64 = Convert.FromBase64String(item);
BitmapImage myImage = new BitmapImage();
myImage.BeginInit();
myImage.StreamSource = new MemoryStream(decodedFromBase64);
myImage.EndInit();
ListBoxItem bild = new ListBoxItem();
bild.Content = new System.Windows.Controls.Image() { Source = myImage };
listBoxbilder.Items.Add(bild);
}
}
Now, if I perform the same task with a slightly different build, using my StreamWriter
to write directly into my file, not bothering to use a StringBuilder
, the resulting .txt looks identical to the naked eye, but the code behaves differently. Here's the bit for creating the file:
//**Example B, just uses StreamWriter**
String[] filePaths = Directory.GetFiles(folderPath, "*.*");
ImageConverter converter = new ImageConverter();
StreamWriter sw = File.CreateText(filepathBase64);
foreach (String item in filePaths)
{
try
{
Bitmap picture = new Bitmap(item);
Byte[] byteArr = (Byte[])converter.ConvertTo(picture, typeof(Byte[]));
String base64 = Convert.ToBase64String(byteArr);
sw.WriteLine(base64);
}
catch{ }
}
sw.Flush();
sw.Close();
I still have an empty line at the end of my file, but when I read that file into an array using File.ReadAllLines, I do NOT get an array where the last position is an empty string. How comes? I can now use code without a check for emptyness, like so:
//**Example B.1, no checks
listBoxbilder.Items.Clear();
String[] myArr = File.ReadAllLines(filepathBase64);
foreach (String item in myArr)
{
byte[] decodedFromBase64 = Convert.FromBase64String(item);
BitmapImage myImage = new BitmapImage();
myImage.BeginInit();
myImage.StreamSource = new MemoryStream(decodedFromBase64);
myImage.EndInit();
ListBoxItem bild = new ListBoxItem();
bild.Content = new System.Windows.Controls.Image() { Source = myImage };
listBoxbilder.Items.Add(bild);
}
I don't get an exception, since the array resulting from File.ReadAllLines has no positions containing an empty string, yet the .txt source looks identical, having an empty line at the very end. What is the cause of this different behaviour?