0

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?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
HerrMetik
  • 63
  • 1
  • 7
  • 2
    I'd *start* by removing those empty catch blocks. Next, find out what the *actual* differences in the file are. Write a small console app to write to two files, one in each way. No need for base64, no need for any UI etc... just write to the file. Compare those files really carefully, e.g. with a binary file editor. – Jon Skeet Sep 06 '16 at 12:37
  • What is the value of _filepathBase64_ this should be the name of a file but in this way you could put the bytes of more than one file in a single file. Is this correct? – Steve Sep 06 '16 at 12:45
  • For comparison I'd first use ready utilities like hexdump (GNU) and compare the output for the two files with a diff tool. – grenix Sep 06 '16 at 12:48
  • 3
    By the way, tried both your examples with a single image and the two resulting base64 files are identical – Steve Sep 06 '16 at 12:49
  • 1
    Not sure about the exact source of your problem, but if you just want to exclude the empty line I suggest that you use `string.IsNullOrWhiteSpace(item)` for your validation, which works robustly. – Georg Patscheider Sep 06 '16 at 12:53
  • Well, there's not really a problem, per se. I'm just puzzled why in example A, I get an array with an empty string at the last position, and with Example B, I don't. And I can't see what the reason for that is. That's why references to the value of the path-variable or the use of catch are, well, a bit tangential. :) The real puzzle to me is: Why do I get an empty string in the array of example A, and I do not get one in example B? – HerrMetik Sep 06 '16 at 13:38

1 Answers1

0

The effect has vanished. I do not know what black magic, cosmic radiation, or simple oversight one my part has caused that erratic behaviour before, it does not occur anymore. The resulting files have identical amounts of bytes and identical checksums, and they behave identical when I use them in my program.

HerrMetik
  • 63
  • 1
  • 7
  • must be some misunderstanding, it happens, imp thing to remember in programming is that if you add 1 to 1 you will ALWAYS get 2, if you are getting anything other then whats logical, its you who is doing something wrong, there is no magic, everything is justified to its last bits. If you hold this belief close to your heart, you will always catch the problem fast instead of thinking some supernatural magic is happening. – user734028 Sep 06 '16 at 19:05
  • Should I use more emoticons in the future when I'm being light-hearted about my own shortcomings? ;-) Anyway, thank you for your comment. It is appreciated. – HerrMetik Sep 08 '16 at 07:22