XML ファイルを生成する必要があり、できるだけ多くのデータをそれに貼り付ける必要がありますが、ファイルサイズの制限があります。そのため、何かがなくなるまでデータを挿入し続ける必要があります。ファイルに繰り返し書き込むことなく XML ファイルのサイズを把握するにはどうすればよいですか?
3 に答える
私はジョン・サンダースに同意します。基本的に彼が話していることを実行するコードを次に示しますが、FileStream 以外は XmlSerializer として実行し、MemoryStream を中間ストレージとして使用します。ただし、ストリームを拡張する方が効果的かもしれません。
public class PartitionedXmlSerializer<TObj>
{
private readonly int _fileSizeLimit;
public PartitionedXmlSerializer(int fileSizeLimit)
{
_fileSizeLimit = fileSizeLimit;
}
public void Serialize(string filenameBase, TObj obj)
{
using (var memoryStream = new MemoryStream())
{
// serialize the object in the memory stream
using (var xmlWriter = XmlWriter.Create(memoryStream))
new XmlSerializer(typeof(TObj))
.Serialize(xmlWriter, obj);
memoryStream.Seek(0, SeekOrigin.Begin);
var extensionFormat = GetExtensionFormat(memoryStream.Length);
var buffer = new char[_fileSizeLimit];
var i = 0;
// split the stream into files
using (var streamReader = new StreamReader(memoryStream))
{
int readLength;
while ((readLength = streamReader.Read(buffer, 0, _fileSizeLimit)) > 0)
{
var filename
= Path.ChangeExtension(filenameBase,
string.Format(extensionFormat, i++));
using (var fileStream = new StreamWriter(filename))
fileStream.Write(buffer, 0, readLength);
}
}
}
}
/// <summary>
/// Gets the a file extension formatter based on the
/// <param name="fileLength">length of the file</param>
/// and the max file length
/// </summary>
private string GetExtensionFormat(long fileLength)
{
var numFiles = fileLength / _fileSizeLimit;
var extensionLength = Math.Ceiling(Math.Log10(numFiles));
var zeros = string.Empty;
for (var j = 0; j < extensionLength; j++)
{
zeros += "0";
}
return string.Format("xml.part{{0:{0}}}", zeros);
}
}
これを使用するには、最大ファイル長で初期化してから、ベース ファイル パスを使用してシリアル化し、次にオブジェクトを使用します。
public class MyType
{
public int MyInt;
public string MyString;
}
public void Test()
{
var myObj = new MyType { MyInt = 42,
MyString = "hello there this is my string" };
new PartitionedXmlSerializer<MyType>(2)
.Serialize("myFilename", myObj);
}
この特定の例では、次のように分割された xml ファイルが生成されます。
myFilename.xml.part001
myFilename.xml.part002
myFilename.xml.part003
...
myFilename.xml.part110
一般に、開いているタグをすべて閉じたとしても、XML ドキュメントを任意の場所で分割することはできません。
ただし、XML ドキュメントを複数のファイルに分割し、それぞれが特定のサイズを超えないようにする必要がある場合は、Stream
クラスの独自のサブタイプを作成する必要があります。この " PartitionedFileStream
" クラスは、サイズ制限まで特定のファイルに書き込んでから、新しいファイルを作成し、そのファイルにサイズ制限まで書き込むことができます。
これにより、連結されたときに有効な XML ドキュメントを構成する複数のファイルが残ります。
通常、終了タグは機能しません。要素 A が 1 つと要素 B が 1 つ続く必要がある XML 形式を考えてみましょう。要素 A を記述した後でタグを閉じた場合、有効なドキュメントはありません。要素 B を記述する必要があります。
ただし、単純なサイト マップ ファイルの特定のケースでは、タグを閉じるだけでよい場合があります。
に を尋ねて、XmlTextWriter
であることBaseStream
を確認できますPosition
。他の人が指摘したように、Xml を適切に閉じるためにヘッドルームを確保する必要がある場合があります。