如何将自定义HTML文档写入文件

时间:2011-05-02 21:39:53

标签: vb.net file-io

基本问题是:将数据从一组分层对象写入文件的最佳方法是什么?最高阶父母有1000个孩子都有孩子(DOM风格)。尝试遍历树并创建一个大字符串然后写入文件会在创建字符串时抛出内存异常。

详情 的 我创建了一组构成 HTML 文档的类 我需要预先打包的HtmlElementHtmlDocument没有给出控制权。始终维护文档对象模型,具有一些类似的方法和属性等 我正在使用自定义类来创建一个非常大的 HTML 文档。当我说大的时候,我的意思是超过2000个打印页面。令人怀疑的是,它们都将被打印,但有些会被打印出来。

我的基础HTMLElement对象(从中派生所有其他对象)包含OuterHTML属性,正如预期的那样,它获取调用对象的完整 HTML 和所有子元素的 HTML 生成报告的代码运行后,我的 HTMLDocument 对象包含需要写入文件的整个报告。这是我一直遇到问题的地方。

如果我在OuterHTML对象上调用HTMLDocument,则会出现内存不足异常。 其他报告保存得很好,但这是迄今为止我在HTMLElement对象上发布的最大报告。我的假设是属性调用产生了太多文本。

我基本上只是创建一个新的 .HTML 文件,打开它进行阅读,并写入所有文本。像:

File.WriteAllText(FileName, HtmlDoc.OuterHTML)

所以问题是:有什么更好的方法呢?

1 个答案:

答案 0 :(得分:0)

我把这个问题留了几天,希望得到一些建议,但没有运气。因此,在花了那么多时间试图找到解决方案后,我终于提出了一个,我认为,相当不错。

在我的HTMLDocument.SaveDocument()例程中,我创建了一个FileStream和一个StreamWriter对象。由于文档是树结构,我创建了一个递归例程,它将StreamWriter和标记集合作为参数。

Public Sub SaveDocument(ByVal FileName As String, Optional ByVal IncludeLineBreaks As Boolean = False)
    If Len(FileName) > 0 Then
        'Save the document
        Dim fs As FileStream
        Dim s As StreamWriter
        Dim LineBreak As String = IIf(IncludeLineBreaks, vbCrLf, "").ToString()

        Try
            fs = New FileStream(FileName, FileMode.Create, FileAccess.Write)
            s = New StreamWriter(fs)
        Catch ex As Exception
            MsgBox("Cannot save the HTML document." & vbCrLf & "Error: " & ex.Message, MsgBoxStyle.OkOnly, "Save HTML Dcoument Error")
            Exit Sub
        End Try

        Try
            With s
                .BaseStream.Seek(0, SeekOrigin.End)

                'begin the html document
                .Write(Me.DocType.OuterHTML & LineBreak)
                .BaseStream.Seek(0, SeekOrigin.End)

                Me.RecursiveDocumentSave(s, Me, LineBreak)

                .Close()
            End With

        Catch ex As Exception
            MsgBox("Error saving the HTML document." & vbCrLf & "Error: " & ex.Message, MsgBoxStyle.OkOnly, "Save HTML Dcoument Error")
        End Try

        s = Nothing
        fs = Nothing
    End If
End Sub

Private Sub RecursiveDocumentSave(ByRef s As StreamWriter, ByRef tag As HTMLTag, ByVal LineBreak As String)
    s.Write(tag.OpenTagText & LineBreak)
    s.BaseStream.Seek(0, SeekOrigin.End)

    For Each t As HTMLTag In tag.Tags.Items
        If t.TagType = "TEXT" Then
            s.Write(t.Text & LineBreak)
            s.BaseStream.Seek(0, SeekOrigin.End)
        Else
            Me.RecursiveDocumentSave(s, t, LineBreak)
        End If
    Next

    s.Write(tag.CloseTagText & LineBreak)
    s.BaseStream.Seek(0, SeekOrigin.End)
End Sub

OpenTagText属性可以优雅地处理自我关闭的<br /><img />等标记。这些标签不会有子项,因此会跳过for循环。