尝试使用流创建bin文件

时间:2017-04-10 13:51:18

标签: c# stream binaryformatter

我onced设法在我的项目中创建bin文件。我将主键从int更改为Guid,并将代码从Main移到我的类Quote。目前我只能在所述文件中添加新条目。如果我删除它,当我尝试提供文件dummy-data时,会创建一个新文件(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;
    }
}

2 个答案:

答案 0 :(得分:1)

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

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

在尝试从中反序列化之前,也应该将流返回到开头。

stream.Seek(0, SeekOrigin.Begin);

FileStreams有一个“头”,所有的读写操作都在这里进行。在写入新流时,头部始终在最后,任何从末尾读取的尝试都将失败。某些流(例如NetworkStream)表现不同,根本不允许搜索。

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

确保Quote类标记为[Serializable]

答案 1 :(得分:1)

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

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

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

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);               
   }
}