0

I have a C# Windows Phone 7.1 app that downloads a PDF file from a foreign web server and then (tries) to save it to the isolated storage area as a file. I have tried several different ways to get this done, but the file always ends up about 30% too large and when I open it up in a text editor, instead of seeing the USUAL 'PDF' characters at the start of the file followed by the encoded characters, I see basically junk. The test file I'm using is supposed to be 161k but when I view the file with the Isolated Storage Explorer, it's 271k.

First I download the file to a string. I inspected the string at this point in the debugger and it does contain the proper values and it is the correct length. The trouble happens when I try to write it to the isolated storage area. I tried both StreamWriter & BinaryWriter with identical invalid results. The contents of the resulting file appears to be a long stream of junk characters. Note, I am deleting the file if it exists just in case, before writing out the contents. Below is my code using the BinaryWriter version. What is wrong?

async public static Task URLToFileAsync(
                                string strUrl, 
                                string strDestFilename, 
                                IProgress<int> progress, 
                                CancellationToken cancelToken)
{
    strUrl = strUrl.Trim();

    if (String.IsNullOrWhiteSpace(strUrl))
        throw new ArgumentException("(Misc::URLToFileAsync) The URL is empty.");

    strDestFilename = strDestFilename.Trim();

    if (String.IsNullOrWhiteSpace(strDestFilename))
        throw new ArgumentException("(Misc::URLToFileAsync) The destination file name is empty.");

    // Create the isolated storage file.
    // FileStream fs = Misc.CreateIsolatedStorageFileStream(strDestFilename);
    IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();

    // Delete the file first.
    if (isoStorage.FileExists(strDestFilename))
        isoStorage.DeleteFile(strDestFilename);

    IsolatedStorageFileStream theIsoStream = isoStorage.OpenFile(strDestFilename, FileMode.Create);

    FileStream fs = theIsoStream;

    // If the stream writer is NULL, then the file could not be created.
    if (fs == null)
        throw new System.IO.IOException("(Misc::URLToFileAsync) Error creating or writing to the file named: " + strDestFilename);

    BinaryWriter bw = new BinaryWriter(fs);

    try
    {

        // Call URLToStringAsync() to get the web file as a string first.
        string strFileContents = await URLToStringAsync(strUrl, progress, cancelToken);

        // >>>> NOTE: strFileContents looks correct and is the correct size.

        // Operation cancelled?
        if (!safeCancellationCheck(cancelToken))
        {
            // Note.  BinaryWriter does not have an Async method so we take the hit here
            //  to do a synchronous operation.
            //  See this Stack Overflow post.
            // http://stackoverflow.com/questions/10315316/asynchronous-binaryreader-and-binarywriter-in-net

            // >>>> NOTE: strFileContents.ToCharArray() looks correct and is the correct length.
            bw.Write(strFileContents.ToCharArray(), 0, strFileContents.Length);
        } // if (safeCancellationCheck(cancelToken))
    }
    finally
    {
        // Make sure the file is cleaned up.
        bw.Flush();
        bw.Close();

        // Make sure the file is disposed.
        bw.Dispose();
    } // try/finally

    // >>>> NOTE: output file in Isolated Storage Explorer is the wrong size and contains apparently junk.
} // async public static void URLToFileAsync
Robert Oschler
  • 14,153
  • 18
  • 94
  • 227

1 Answers1

1

You cannot download a binary into a string. The result will not be correct, as you have found out.

See this answer, which demonstrates how to download a binary file to isolated storage: https://stackoverflow.com/a/6909201/1822514

Community
  • 1
  • 1
chue x
  • 18,573
  • 7
  • 56
  • 70
  • @chue_x. Thanks. That worked but I would like to know why, especially since the length of the string is identical to the size of the web file. The only reason for the difference I can think of is that C#/.NET stores strings with multi-byte encoding or some other encoding in the string memory itself, something that at least non-.NET C, C++, and Delphi does not do. – Robert Oschler Apr 09 '13 at 03:47
  • 2
    @RobertOschler **All strings in .NET are encoded in UTF-16**. So when reading a string, the runtime will try to convert the characters into that encoding. When unable to find out which encoding the source has used, it will default to UTF-8. So basically, in your case, .NET thought your PDF file was an UTF-8 encoded text, and converted it to UTF-16. Since both encoding do not have the same binary representation, it explains why your data got corrupted. – Kevin Gosse Apr 09 '13 at 05:07
  • @KooKiz - That explains it, thanks. I've switched everything to byte arrays and all is well now. – Robert Oschler Apr 09 '13 at 05:15