Skip to main content
 首页 » 编程设计

c#之附加到序列化集合

2024年01月25日24落叶

我有一个某种类型的序列化数组。 有没有办法将新对象附加到这个序列化数组(以序列化形式)而不需要将已经保存的集合读入内存?

例子:

我在 file.xml 中有一个包含 10^12 个元素的实体的 XML 序列化数组。我需要向序列化文件中添加另外 10^5 个元素,但我不想读取所有以前的元素,追加新元素并将新数组写入流,因为这会占用大量资源(尤其是内存) .

如果它需要二进制序列化程序,我对此没有问题。

请您参考如下方法:

通常解决方案是更改 XML 字节,这样您就不必像在反序列化中那样读取所有字节。

一般的步骤是:

  1. 列表项
  2. 打开文件流
  3. 存储数组的结束节点
  4. 序列化新项目
  5. 将序列化的字节写入流
  6. 写下结点

例如将整数添加到序列化数组的代码:

// Serialize array - in you case it the stream you read from file.xml 
var ints = new[] { 1, 2, 3 }; 
var arraySerializer = new XmlSerializer(typeof(int[])); 
var memoryStream = new MemoryStream(); // File.OpenWrite("file.xml") 
arraySerializer.Serialize(new StreamWriter(memoryStream), ints); 
 
// Save the closing node 
int sizeOfClosingNode = 13; // In this case: "</ArrayOfInt>".Length 
                            // Change the size to fit your array 
                            // e.g. ("</ArrayOfOtherType>".Length) 
 
// Set the location just before the closing tag 
memoryStream.Position = memoryStream.Length - sizeOfClosingNode; 
 
// Store the closing tag bytes 
var buffer = new byte[sizeOfClosingNode]; 
memoryStream.Read(buffer, 0, sizeOfClosingNode); 
 
// Set back to location just before the closing tag. 
// In this location the new item will be written. 
memoryStream.Position = memoryStream.Length - sizeOfClosingNode; 
 
// Add to serialized array an item 
var itemBuilder = new StringBuilder(); 
// Write the serialized item as string to itemBuilder 
new XmlSerializer(typeof(int)).Serialize(new StringWriter(itemBuilder), 4); 
// Get the serialized item XML element (strip the XML document declaration) 
XElement newXmlItem = XElement.Parse(itemBuilder.ToString()); 
// Convert the XML to bytes can be written to the file 
byte[] bytes = Encoding.Default.GetBytes(newXmlItem.ToString()); 
// Write new item to file. 
memoryStream.Write(bytes, 0, bytes.Length); 
// Write the closing tag. 
memoryStream.Write(buffer, 0, sizeOfClosingNode); 
 
// Example that it works 
memoryStream.Position = 0; 
var modifiedArray = (int[]) arraySerializer.Deserialize(memoryStream); 
CollectionAssert.AreEqual(new[] { 1, 2, 3, 4 }, modifiedArray);