基本问题是:将数据从一组分层对象写入文件的最佳方法是什么?最高阶父母有1000个孩子都有孩子(DOM风格)。尝试遍历树并创建一个大字符串然后写入文件会在创建字符串时抛出内存异常。
的详情 的
我创建了一组构成 HTML 文档的类
我需要预先打包的HtmlElement
和HtmlDocument
没有给出控制权。始终维护文档对象模型,具有一些类似的方法和属性等
我正在使用自定义类来创建一个非常大的 HTML 文档。当我说大的时候,我的意思是超过2000个打印页面。令人怀疑的是,它们都将被打印,但有些会被打印出来。
我的基础HTMLElement
对象(从中派生所有其他对象)包含OuterHTML
属性,正如预期的那样,它获取调用对象的完整 HTML 和所有子元素的 HTML
生成报告的代码运行后,我的 HTMLDocument 对象包含需要写入文件的整个报告。这是我一直遇到问题的地方。
如果我在OuterHTML
对象上调用HTMLDocument
,则会出现内存不足异常。
其他报告保存得很好,但这是迄今为止我在HTMLElement
对象上发布的最大报告。我的假设是属性调用产生了太多文本。
我基本上只是创建一个新的 .HTML 文件,打开它进行阅读,并写入所有文本。像:
File.WriteAllText(FileName, HtmlDoc.OuterHTML)
所以问题是:有什么更好的方法呢?
答案 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
循环。