了解保存——我是只使用 Stream,还是同时使用 Formatter 和 Stream?

Understanding saving - do I only use Stream, or use both Formatter and Stream?

据我了解,Formatter 将可序列化对象转换为字节流,而 Stream(例如 FileStream)将这些字节实际写入文件。示例代码:

public static void SaveData(MySerializableData data)
{
    BinaryFormatter formatter = new BinaryFormatter();
    FileStream stream = new FileStream(SavePath, FileMode.Create);        
    formatter.Serialize(stream, data);
    stream.Close();
}

但在其他时候,我也会看到这种类型的代码:

void Save()
{
    string data = "Value 1";
    StreamWriter writer = new StreamWriter("MySaveFile.txt", true);
    writer.Write(data);
}

为什么在第二种情况下,我们放弃了两步保存的过程?为什么我们有时只使用 StreamWriter,而有时同时使用格式化程序和流对象?

谢谢!

BinaryFormatter 将 class 序列化为字节数组并将其写入流。当您想 save/load class 处理它的数据时,它很有用。序列化存储有关正在存储的 class 图的元数据。

StreamWriter 是一个流,具有将字符串写入文件的特定功能。

考虑这个例子:

MemoryStream mstr = new MemoryStream();

string datastr = "hello!";

BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(mstr, datastr);
mstr.Seek(0, SeekOrigin.Begin);

string resultString = Encoding.ASCII.GetString(mstr.ToArray());

如果您检查 resultString,您会发现它包含如下内容:

"[=11=]\u0001[=11=][=11=][=11=]????\u0001[=11=][=11=][=11=][=11=][=11=][=11=][=11=]\u0006\u0001[=11=][=11=][=11=]\u0006hello!\v"

好吧,这不是您希望在文本文件中包含的内容,对吧?如您所见,序列化并非旨在存储原始数据,而是 class 个实例。

现在检查一下:

MemoryStream mstr = new MemoryStream();
StreamWriter sw = new StreamWriter(mstr);
string datastr = "hello!";
sw.Write(datastr);
mstr.Seek(0, SeekOrigin.Begin);
sw.Close();

string resultString = Encoding.ASCII.GetString(mstr.ToArray());

如果您现在检查 resultString 它将包含:

"hello!"

如您所见,它非常不同,这就是您在文本文件中所期望的。

您还可以使用流存储原始二进制数据:

byte[] data = new byte[]{ 1,2,3,4 };
var fs = File.Create("out.dat"); //this creates a new file and creates a filestream
fs.Write(data, 0, data.Length);
fs.Close();

如果您现在使用二进制编辑器检查该文件,您将看到它包含:

0x01, 0x02, 0x03, 0x04

有许多类型的流具有不同的用途(例如,我在示例中使用的 MemoryStream,将其数据存储到内存中的数组中的二进制流)和大量 classes将流用于很多事情,在这种情况下,您混合了使用流的序列化和数据存储的概念,这是两个不同的东西。