共用方式為


HOW TO:執行文字到 XML 的資料流轉換

處理文字檔的其中一個方法是撰寫擴充方法,該方法會使用 yield return 建構將文字檔一次串流一行。 然後您可以撰寫利用延後的方式處理文字檔的 LINQ 查詢。 如果您接著使用 XStreamingElement 串流輸出,您就可以使用最少量的記憶體建立文字檔到 XML 的轉換,而不必在乎來源文字檔的大小。

關於串流轉換有一些警告。 在您可以處理一次整個檔案的情況下,以及您可以用行出現在來源文件中的順序處理這些行時,最適合使用串流轉換。 如果您必須多次處理檔案,或者,如果您必須在處理檔案前排序行,您將會失去使用串流技術的好處。

範例

下列文字檔 People.txt 為這個範例的來源。

#This is a comment
1,Tai,Yee,Writer
2,Nikolay,Grachev,Programmer
3,David,Wright,Inventor

下列程式碼包含的擴充方法可以用延緩的方式,串流文字檔的行。

注意事項注意事項

下列範例使用 C# 的 yield return 建構函式。在 Visual Basic 中,對等程式碼是使用實作 IEnumerable(Of XElement) 介面的類別來提供。如需在 Visual Basic 中實作 IEnumerable(Of T) 的範例,請參閱逐步解說:在 Visual Basic 中實作 IEnumerable(Of T)

public static class StreamReaderSequence
{
    public static IEnumerable<string> Lines(this StreamReader source)
    {
        String line;

        if (source == null)
            throw new ArgumentNullException("source");
        while ((line = source.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        StreamReader sr = new StreamReader("People.txt");
        XStreamingElement xmlTree = new XStreamingElement("Root",
            from line in sr.Lines()
            let items = line.Split(',')
            where !line.StartsWith("#")
            select new XElement("Person",
                       new XAttribute("ID", items[0]),
                       new XElement("First", items[1]),
                       new XElement("Last", items[2]),
                       new XElement("Occupation", items[3])
                   )
        );
        Console.WriteLine(xmlTree);
        sr.Close();
    }
}
Module Module1
    Sub Main()
        Dim sr = New IO.StreamReader("..\..\People.txt")
        Dim xmlTree = New XStreamingElement("Root",
            From line In sr.Lines()
            Let items = Split(line, ",")
            Where Not line.StartsWith("#")
            Select <Person ID=<%= items(0) %>>
                       <First><%= items(1) %></First>
                       <Last><%= items(2) %></Last>
                       <Occupation><%= items(3) %></Occupation>
                   </Person>
                   )

        Console.WriteLine(xmlTree)
        sr.Close()
    End Sub
End Module

Module StreamReaderSequence
    <System.Runtime.CompilerServices.Extension()>
    Public Function Lines(ByRef source As IO.StreamReader) As IEnumerable(Of String)
        If source Is Nothing Then Throw New ArgumentNullException("source")
        Return New StreamReaderEnumerable(source)
    End Function
End Module


Public Class StreamReaderEnumerable
    Implements IEnumerable(Of String)

    Private _source As IO.StreamReader

    Public Sub New(ByVal source As IO.StreamReader)
        _source = source
    End Sub

    Public Function GetEnumerator() As Generic.IEnumerator(Of String) Implements IEnumerable(Of String).GetEnumerator
        Return New StreamReaderEnumerator(_source)
    End Function

    Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
        Return Me.GetEnumerator()
    End Function
End Class

Public Class StreamReaderEnumerator
    Implements IEnumerator(Of String)

    Private _current As String
    Private _source As IO.StreamReader

    Public Sub New(ByVal source As IO.StreamReader)
        _source = source
    End Sub


    Public ReadOnly Property Current As String Implements Generic.IEnumerator(Of String).Current
        Get
            Return _current
        End Get
    End Property

    Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
        Get
            Return Me.Current
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        _current = _source.ReadLine()
        Return If(_current IsNot Nothing, True, False)
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        _current = Nothing
        _source.DiscardBufferedData()
        _source.BaseStream.Seek(0, IO.SeekOrigin.Begin)
    End Sub


    Public Sub Dispose() Implements IDisposable.Dispose

    End Sub

End Class

這個範例會產生下列輸出:

<Root>
  <Person ID="1">
    <First>Tai</First>
    <Last>Yee</Last>
    <Occupation>Writer</Occupation>
  </Person>
  <Person ID="2">
    <First>Nikolay</First>
    <Last>Grachev</Last>
    <Occupation>Programmer</Occupation>
  </Person>
  <Person ID="3">
    <First>David</First>
    <Last>Wright</Last>
    <Occupation>Inventor</Occupation>
  </Person>
</Root>

請參閱

參考

XStreamingElement

概念

進階查詢技術 (LINQ to XML)