0

I'm trying to read an EmbeddedResource (a default config file) and write it to a File. After that I should read the file and to make things easier I decided to do that in a single step.

    private string CreateDefaultFile()
    {
        using (var stream = Shelter.Assembly.GetManifestResourceStream($@"Mod.Resources.Config.{_file}"))
        {
            if (stream == null)
                throw new NullReferenceException(); //TODO
            using (var ms = new MemoryStream())
            {
                using (var fs = new FileStream(Shelter.ModDirectory + _file, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    byte[] buffer = new byte[512];

                    int bytesRead;
                    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, bytesRead);
                        fs.Write(buffer, 0, bytesRead);
                    }

                    fs.Flush();
                    ms.Flush();

                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
        }
    }

This does create the file but the return value doesn't seem to work as it should. The content seems correct but JSON.Net cannot parse it with this error: JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0.. Using File.ReadAllText(...) instead of Encoding.UTF8.GetString(ms.ToArray()) seems to work so I'm guessing this is a problem with how I load the stream into a string.

Also the chunking part is not needed as the file is small in size, I've read in multiple places that is better use so I'd prefer it.

(Targeting .NET Framework 3.5)

Hawk
  • 13
  • 3
  • So, if you *print* that return value with `Debug.WriteLine` or similar, do the contents look sensible? – Damien_The_Unbeliever Aug 16 '18 at 13:13
  • We should probably also see the JSON bit if it's the bit raising an error too. If the file contents are small, can you add that into the question also (with any secrets redacted) – Damien_The_Unbeliever Aug 16 '18 at 13:19
  • The return value is a json string and printing it displays the same as the `JSON Data` link @Damien_The_Unbeliever – Hawk Aug 16 '18 at 16:58
  • Your byte array must have a [BOM](https://en.wikipedia.org/wiki/Byte_order_mark) at the beginning. To process it correctly use a `StreamReader` as shown in [Encoding.UTF8.GetString doesn't take into account the Preamble/BOM](https://stackoverflow.com/q/11701341/3744182) and [How do I ignore the UTF-8 Byte Order Marker in String comparisons?](https://stackoverflow.com/a/2915239/3744182). – dbc Aug 16 '18 at 22:31

1 Answers1

0

Thanks to dbc comment and Tergiver answer I fixed the issue.

The code:

private string CreateDefaultFile()
{
    using (var stream = Shelter.Assembly.GetManifestResourceStream($@"Mod.Resources.Config.{_file}"))
    {
        if (stream == null)
            throw new NullReferenceException(); //TODO
        using (var ms = new MemoryStream())
        {
            using (var fs = File.Open(Shelter.ModDirectory + _file, FileMode.Create, FileAccess.Write, FileShare.Read))
            {
                byte[] buffer = new byte[512];

                int bytesRead;
                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, bytesRead);
                    fs.Write(buffer, 0, bytesRead);
                }

                fs.Flush();
                ms.Flush();

                byte[] content = ms.ToArray();
                if (content.Length >= 3 && content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF)
                    return Encoding.UTF8.GetString(content, 3, content.Length - 3);
                return Encoding.UTF8.GetString(content);
            }
        }
    }
}
Hawk
  • 13
  • 3