尝试使用流创建 bin 文件

Trying to create a bin-file using stream

我曾经设法在我的项目中创建 bin 文件。我将主键从 int 更改为 Guid,并将代码从 Main 移至我的 class 引用。目前我只能在所述文件中添加新条目。如果我删除它,则会创建一个新文件(0 字节),并且当我尝试提供文件虚拟数据时,流会得到 ArgumentException。我正在尝试使用 if 循环来处理 stream.Lenght == 0.

public static List<Quote> readBinaryToList()        //Crashes if binfile is 0 bytes long
{
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new FileStream(@"C:\Users\xxxxxx\Desktop\quotes.bin", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
    if (stream.Length == 0)
    {
        Quote q = new Quote(Guid.NewGuid(), "Quote dummy", false);
        List<Quote> quoteList = new List<Quote>();
        quoteList.Add(q);
        var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        bformatter.Serialize(stream, quoteList);

        bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        List<Quote> quoteListTmp = (List<Quote>)bformatter.Deserialize(stream);

        return quoteList;
    }
    else
    {
        List<Quote> quoteList = (List<Quote>)formatter.Deserialize(stream);
        stream.Close();
        return quoteList;
    }
}

文件正在以只读方式打开,序列化到文件将需要写权限。

Stream stream = new FileStream(@"C:\temp\quotes.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);

在尝试对其进行反序列化之前,还应将流返回到开头。

stream.Seek(0, SeekOrigin.Begin);

FileStreams 有一个 "head",所有读写操作都在其中进行。在写入新流时,头部始终在末尾,任何从末尾读取的尝试都将失败。一些流(例如 NetworkStream)的行为不同,根本不允许搜索。

此外,FileStream 的初始位置取决于文件的打开方式(基于指定的 FileMode)。问题中指定的 FileMode 将导致流位置从文件的开头开始,因此 else 块中不需要这样做。

并确保引用 class 标记为 [Serializable]

正如前面的答案所指出的,你必须给你的文件流写权限,这可以在它的构造函数中完成,然后你还应该将流的位置设置回 0,你可以通过使用流的位置 属性.

您正在创建许多不必要的对象,这些对象实际上对方法的目的没有贡献,我在下面省略了这些对象。这样做时,将流 Position 属性 设置为 0 是多余的,但我将其留在评论中以说明其完成方式。

其他一些需要考虑的事情:在 using 语句中声明文件流,以便在方法结束时将其释放,这意味着您可以省略 else 语句中的手动关闭。你的一些代码可以写得更简洁,这只是个人喜好,但我认为最好内联你的一些代码以尽可能多地消除噪音。在 C# 中,对方法使用 PascalCase 也是惯例。

public static List<Quote> ReadBinaryToList(){
  using(Stream stream = new FileStream(@"quotes.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
       IFormatter formatter = new BinaryFormatter();

        if (stream.Length == 0) {
           List<Quote> quoteList = new List<Quote> {new Quote(Guid.NewGuid(), "Quote dummy", false)};
           formatter.Serialize(stream, quoteList);
           //stream.Position = 0;
           return quoteList;
        }
        else return (List<Quote>)formatter.Deserialize(stream);               
   }
}