Why does this not write the correct bytes to the file?
Here is my test to 开发者_运维技巧write to a file:
[Test]
public void CanWriteManifestToFile()
{
byte[] data = new byte[] { 0x00, 0x01, 0x80, 0x1f };
MemoryStream ms = new MemoryStream(data);
var mg = new ManifestGeneratorV1();
mg.WriteManifestFile(ms, "TestManifest.mnf");
Assert.IsTrue(File.Exists("TestManifest.mnf"));
Assert.AreEqual(data, GetDataFromFile("TestManifest.mnf"));
}
Here is the WriteManifestFile method that actually does the writing:
public void WriteManifestFile(MemoryStream ms, string filePath)
{
using (StreamWriter sw = new StreamWriter(filePath, false))
{
ms.Seek(0, 0);
using (StreamReader sr = new StreamReader(ms))
{
sw.Write(sr.ReadToEnd());
}
}
}
My test fails. The result is the following byte array {00,01,ef,bf,bd,1f}
. Now if I change the 80 to something that doesn't start with f
or 8
everything works correctly. What could cause the 80
to get changed to efbfbd
?
You are using string methods on non-string data; ReadToEnd
and Write(string)
. That is invalid; the corruption is a direct result of this (i.e. running arbitrary data through a text Encoding
). Use the raw Stream
API instead:
using(var file = File.Create(filePath))
{
ms.Position = 0;
ms.CopyTo(file);
}
or just:
File.WriteAllBytes(filePath, ms.ToArray());
StreamReader.ReadToEnd()
returns a string. That means that it needs to interpret the bytes in the stream it reads from. For this interpretation it uses an encoding, UTF-8 in your case, I guess. This is wrong, because your bytes don't represent text.
You really want to read the bytes and write them to the file without any interpretation. Something like this.
var bytes = new byte[ms.Length];
ms.Read(bytes, 0, bytes.Length);
using(var fileStream = new FileStream(...))
{
fileStream.Write(bytes, 0, bytes.Length);
}
精彩评论