尝试使用流创建 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);
}
}
我曾经设法在我的项目中创建 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);
}
}