1

XML ファイルを生成する必要があり、できるだけ多くのデータをそれに貼り付ける必要がありますが、ファイルサイズの制限があります。そのため、何かがなくなるまでデータを挿入し続ける必要があります。ファイルに繰り返し書き込むことなく XML ファイルのサイズを把握するにはどうすればよいですか?

4

3 に答える 3

2

私はジョン・サンダースに同意します。基本的に彼が話していることを実行するコードを次に示しますが、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
于 2010-02-21T23:26:59.810 に答える
1

一般に、開いているタグをすべて閉じたとしても、XML ドキュメントを任意の場所で分割することはできません。

ただし、XML ドキュメントを複数のファイルに分割し、それぞれが特定のサイズを超えないようにする必要がある場合は、Streamクラスの独自のサブタイプを作成する必要があります。この " PartitionedFileStream" クラスは、サイズ制限まで特定のファイルに書き込んでから、新しいファイルを作成し、そのファイルにサイズ制限まで書き込むことができます。

これにより、連結されたときに有効な XML ドキュメントを構成する複数のファイルが残ります。


通常、終了タグは機能しません。要素 A が 1 つと要素 B が 1 つ続く必要がある XML 形式を考えてみましょう。要素 A を記述した後でタグを閉じた場合、有効なドキュメントはありません。要素 B を記述する必要があります。

ただし、単純なサイト マップ ファイルの特定のケースでは、タグを閉じるだけでよい場合があります。

于 2010-02-21T22:39:25.447 に答える
0

に を尋ねて、XmlTextWriterであることBaseStreamを確認できますPosition。他の人が指摘したように、Xml を適切に閉じるためにヘッドルームを確保する必要がある場合があります。

于 2010-02-21T22:34:29.047 に答える