資料庫同步專案中,使用 BinaryFormatter 將泛型集合序列化為二進制流透過 TCP 傳輸,服務端反序列化寫入資料庫。本文記錄實際遇到的 MemoryStream 位置未重置導致反序列化失敗的問題與解決方案。
List<DiagramInfo> → BinaryFormatter.Serialize(MemoryStream) → stream.ToArray() → TCP 發送。MemoryStream → BinaryFormatter.Deserialize(MemoryStream)。private byte[] Serialize(List<DiagramInfo> diagrams)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, diagrams);
return stream.ToArray(); // 取得完整位元組陣列
}
}
var memStream = new MemoryStream();
do
{
bytesRead = stream.Read(responseBuffer, 0, bufferSize);
memStream.Write(responseBuffer, 0, bytesRead);
} while (bytesRead > 0);
// ❌ 錯誤:MemoryStream.Position 位於資料流末尾,Deserialize 會讀取空資料
var formatter = new BinaryFormatter();
var diagrams = (List<DiagramInfo>)formatter.Deserialize(memStream);
MemoryStream.Write 後,Position 會移至資料流末尾。Deserialize 從目前 Position 開始讀取,導致讀取到 0 位元組,拋出 SerializationException。
// ✅ 修正:反序列化前將 Position 歸零
memStream.Position = 0;
var formatter = new BinaryFormatter();
var diagrams = (List<DiagramInfo>)formatter.Deserialize(memStream);
或使用 memStream.Seek(0, SeekOrigin.Begin)。
MemoryStream、NetworkStream 正確釋放。BinaryFormatter 已標記過時,建議改用 System.Text.Json、protobuf-net、MessagePack 等高效能、跨平台格式。using (var client = tcpListener.AcceptTcpClient())
using (var netStream = client.GetStream())
using (var memStream = new MemoryStream())
{
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = netStream.Read(buffer, 0, buffer.Length)) > 0)
memStream.Write(buffer, 0, bytesRead);
memStream.Position = 0; // 關鍵!
var formatter = new BinaryFormatter();
var diagrams = (List<DiagramInfo>)formatter.Deserialize(memStream);
// 處理 diagrams 寫入資料庫...
}