我正在处理处理firebird数据库请求的c#windows服务。当我尝试在客户端应用程序上反序列化对象时,我的问题发生在随机时刻(有时在5分钟之后,有时仅在4次调用数据库之后)。它仅在特定位置发生(在54字节数组中停止在第18个字节处)。其余时间函数返回正确的结果。
我使用此功能序列化单个对象
public byte[] ObjectToByteArray(Object obj)
{
if (obj == null)
return null;
MemoryStream fs = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, obj);
fs.Seek(0, SeekOrigin.Begin);
byte[] rval = fs.ToArray();
fs.Close();
return rval;
}
我没有序列化任何自定义类,只有字符串和数字类型(firebird api将它们作为对象返回)。 我用它来反序列化:
public object ByteArrayToObject(Byte[] Buffer)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(Buffer);
stream.Position = 0;
object rval = formatter.Deserialize(stream); <--- this thing drives me nuts.
stream.Close();
return rval;
}
和客户端应用程序中的主要功能。抱歉丑陋的代码,
public List<object[]> ByteToList(byte[] data, int[] pomocnicza)
{
//pomocnicza table contains size of (original) particular column of list in bytes
int size_row = 0;
foreach (int i in pomocnicza)
{ size_row += i; }
List<object[]> result = new List<object[]>();
int iterator = 0;
for (int i = 0; i < data.Length / size_row ; i++)
{
object[] zxc = new object[3];
int l = pomocnicza.Length/4;
for (int j = 0; j < l; j++)
{
byte[] tmp = new byte[pomocnicza[j*4]];
System.Array.Copy(data, iterator, tmp, 0, pomocnicza[j*4]);
object ffs = ByteArrayToObject(tmp);
zxc[j] = ffs;
iterator += pomocnicza[j*4];
}
result.Add(zxc);
}
return result;
}
令我感到困惑的是,它在大多数情况下有效,但不可避免地会导致错误。它随机发生的事情使得难以定位。请帮忙。
@EDIT 这就是我阅读输入的方式:
public List<object[]> RetrieveSelectData(FbConnection dbConn, string SQLCommand)
{
using (var command = dbConn.CreateCommand())
{
command.CommandText = SQLCommand;
using (var reader = command.ExecuteReader())
{
var rows = new List<object[]>();
while (reader.Read())
{
var columns = new object[reader.FieldCount];
reader.GetValues(columns);
rows.Add(columns);
}
return rows;
}
}
}
然后使用此函数序列化
public byte[] ListToByte(List<object[]> lista, out int[] rozmiary)
{
int size= 0;
rozmiary = new int[lista[0].Length];
for (int i = 0; i < lista[0].Length; i++)
{
byte[] test = this.ObjectToByteArray(lista[0][i]);
size+= test.Length;
rozmiary[i] = test.Length;
}
size*= lista.Count;
byte[] result = new byte[size];
int index = 0;
for (int i = 0; i < lista.Count; i++)
{
for (int j = 0; j < lista[i].Length; j++)
{
byte[] tmp = this.ObjectToByteArray(lista[i][j]);
tmp.CopyTo(result, index);
index += tmp.Length;
}
}
return result;
}
答案 0 :(得分:1)
如果您使用上述反序列化方法&amp;从客户端流或其他流获取流时也调用它们....跳过它。尝试直接使用格式化程序的那些流。如下:
NetworkStream clientStream = client.GetStream();
Object src = (Object)formatter.Deserialize(clientStream);
答案 1 :(得分:0)
我找到了这个bug。上面的代码工作正常,但在某些情况下(!)需要关注编码,所以请随意使用它。 问题出现在程序的另一部分,我错误输入并发送4个字节但客户端应用程序被告知接收8,因此在大多数情况下,它用零填充它,但有时它从下一个数据包中得到它。
@Marc Gravell和他的博客让我一遍又一遍地寻找源头。