我试图将List作为BLOB存储在sqlite数据库中,但是我在重建List时遇到了一些麻烦。我承认我对BinaryFormatter或MemoryStream的工作原理不太了解。
插入一行似乎工作正常:
public void InsertRow()
{
List<float> myList = new List<float>();
myList.Add(12);
myList.Add(13);
myList.Add(14);
myList.Add(15);
myList.Add(16);
var binFormatter = new BinaryFormatter();
var mStream = new MemoryStream();
binFormatter.Serialize(mStream, myList);
SQLiteCommand command = new SQLiteCommand(m_dbConnection);
byte[] data = mStream.ToArray();
command.CommandText = "insert into photos (photo) values (@photo)";
command.Parameters.Add("@photo", DbType.Binary, 237).Value = data;
command.ExecuteNonQuery();
}
Deserialize方法抛出System.Runtime.Serialization.SerializationException:解析完成之前遇到的End of Stream:
public void GetRow()
{
string sql = "select photo from photos where id = 1";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
byte[] buffer = GetBytes(reader);
var mStream = new MemoryStream();
var binFormatter = new BinaryFormatter();
mStream.Write(buffer, 0, 237);
mStream.Position = 0;
var myObject = binFormatter.Deserialize(mStream) as List<float>;
}
}
}
我在这里做错了什么?另外,为什么myList中的5个浮点数在序列化时会产生237个字节?
编辑:添加了GetBytes功能:
static byte[] GetBytes(SQLiteDataReader reader)
{
const int CHUNK_SIZE = 2 * 1024;
byte[] buffer = new byte[CHUNK_SIZE];
long bytesRead;
long fieldOffset = 0;
using (MemoryStream stream = new MemoryStream())
{
while ((bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, (int)bytesRead);
fieldOffset += bytesRead;
}
return stream.ToArray();
}
}
答案 0 :(得分:5)
您已经对序列化数据的大小进行了硬编码。 不要那样做!
List<float> myList = new List<float>();
myList.Add(12);
myList.Add(13);
myList.Add(14);
myList.Add(15);
myList.Add(16);
var binFormatter = new BinaryFormatter();
var mStream = new MemoryStream();
binFormatter.Serialize(mStream, myList);
Console.WriteLine(mStream.Length);
这输出238,而不是237.你丢失了一个字节,这就是为什么你在解析完成之前遇到“End of Stream”。
所以不要硬编码大小,使用流的所有字节。这也适用于反序列化。并且没有,这并不意味着你应该使用238,硬编码预期的大小是100%错误
此代码有效:
List<float> myList = new List<float>();
myList.Add(12);
myList.Add(13);
myList.Add(14);
myList.Add(15);
myList.Add(16);
var formatter = new BinaryFormatter();
var stream1 = new MemoryStream();
formatter.Serialize(stream1, myList);
var array = stream1.ToArray();
Console.WriteLine(array.Length);
var stream2 = new MemoryStream();
stream2.Write(array, 0, array.Length);
stream2.Position = 0;
foreach (var value in formatter.Deserialize(stream2) as List<float>)
Console.WriteLine(value);
和输出:
238
12
13
14
15
16
请注意,您可以在现有字节数组周围构造MemoryStream
,然后您不必重新定位它,以便上面示例中的反序列化可以缩短为:
var stream2 = new MemoryStream(array);
foreach (var value in formatter.Deserialize(stream2) as List<float>)
Console.WriteLine(value);
答案 1 :(得分:-1)
binFormatter.Serialize(mStream, myList);
mStream.Close(); // to be sure
byte[] data = mStream.ToArray();
command.Parameters.Add("@photo", DbType.Binary).Value = data; // don't specify (override) the size.