我在C#中有一个数据集,我可以使用dataset.WriteXml(filename);
进行序列化,但我希望该文件也包含其他数据(基本上是关于数据集的一些元数据)。
我可以在包含元数据的数据集中添加另一个表,但如果可能的话,我宁愿将它保持分开。
基本上我认为我想创建一个'文件组合'文件,看起来像这样:
size_of_file1
file1
size_of_file2
file2
... etc
然后,我想将文件加载到内存中,并将文件拆分为单独的流,以便我可以将数据集输入dataset.ReadXml(stream);
,将元数据输入其他内容。
听起来可能吗?谁能告诉我怎么做呢?
由于
添
PS。我希望生成的文件保持人类可读性。
答案 0 :(得分:1)
这是可能的。
您应该将其设为二进制(非人类可读)文件,并使用BinaryWriter
和BinaryReader
类来读取和写入长度。
您可以像这样读取文件:
using (FileStream combinedFile = File.Open(...))
using (var binReader = new BinaryReader(combinedFile)) {
while(!combinedFile.EOF) {
long segmentLength = binReader.ReadInt64();
var bytes = new byte[segmentLength];
long totalRead = 0;
while(bytesRead < segmentLength) {
int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead));
if (read == 0)
throw new InvalidDataException();
}
yield return new MemoryStream(bytes);
}
}
编辑要制作人类可读的文件,请将段长度写为固定长度的字符串(填充到一些合理的位数,例如16),可选地后跟换行符。最大段大小是字符串的长度。
您可以像这样读取文件:
const int LengthPadding = 16
using (FileStream combinedFile = File.Open(...))
using (var binReader = new BinaryReader(combinedFile)) {
while(!combinedFile.EOF) {
char[] segmentLengthChars = binReader.ReadChars(16);
long segmentLength = long.Parse(new string(segmentLengthChars));
binReader.ReadChars(2); //Skip the newline
var bytes = new byte[segmentLength];
long totalRead = 0;
while(bytesRead < segmentLength) {
int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead));
if (read == 0)
throw new InvalidDataException();
}
yield return new MemoryStream(bytes);
}
}
要编写段长度,请调用
binWriter.WriteChars(length.ToString().PadLeft(16, '0').ToCharArray());
binWriter.WriteChars(new char[] { '\r', '\n' });
您应该明确传递编码,CultureInfo.InvariantCulture
适用。
答案 1 :(得分:1)
您可以扩展DataSet对象,将元数据添加为属性并序列化...
答案 2 :(得分:1)
如果需要人类可读,请使用XML文件。将元数据存储在元素中,将数据集存储在另一个元素中。
答案 3 :(得分:1)
如果你想简单地将XML写出一个节点,就像这样:
DataSet ds;
// populate ds with some data
string serialized;
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
string metaData = "<MetaData version=\"1.0\" date=\"" + System.Xml.XmlConvert.ToString(DateTime.Now) + "\">" +
"<Detail>Some more details</Detail></MetaData>";
sw.Write(metaData);
ds.WriteXml(sw, System.Data.XmlWriteMode.WriteSchema);
sw.Close();
serialized = sw.ToString();
}
然后你可以把它读作像这样的XML文档片段中的一系列节点,利用数据集使用XMLReader的能力:
using (System.IO.StringReader sr = new System.IO.StringReader(serialized))
{
System.Xml.XmlReaderSettings xs = new System.Xml.XmlReaderSettings();
xs.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;
System.Xml.XmlReader xr = System.Xml.XmlTextReader.Create(sr, xs);
xr.Read();
string metaData = xr.ReadOuterXml();
Console.WriteLine(metaData);
ds = new System.Data.DataSet();
ds.ReadXml(xr);
ds.WriteXml(Console.Out);
}