【发布时间】:2017-12-22 22:14:16
【问题描述】:
我正在尝试打开一个大 (6gb) txt/xlm 文件,对其进行解析,然后将解析后的信息保存到一个新的、更小的文件中。在最简单的情况下,我有一个类似于...的 xml 文件。
<cat>
<a1>a</a1>
<b1>b</b1>
</cat>
<cat>
<a1>x</a1>
<b1>y</b1>
<c1>z</c1>
</cat>
<cat>
<a1>aa</a1>
<b1/>
<c1>cc</c1>
</cat>
<cat>
<a1></a1>
<b1>GG</b1>
<c1>HH</c1>
</cat>
...我想将其解析为...
a | b |
x | y | z
aa | | cc
| GG | HH
我在解析方面做得很好(尽管稍后我可能会提出问题)。我的主要问题是处理 6gb 的大文件。
我可以打开、操作和保存最大约 30mb 的文件。在那之后,Excel死了。在 50mb 之后的某个地方,我开始收到代码错误,说“文件已经打开”。所以我的问题是,我该如何处理这个非常大的文件(6gb)?我知道 VBA 不是最好的方法,但我还没有找到可以加载文件的文本编辑器,而像 Access 这样的 MS 应用程序的大小约为 2gb。在 Excel 以外的应用程序中运行 VBA 会更好吗?在 .asp 页面上使用 FSO 会更好吗?我难住了。任何帮助将不胜感激。
提前谢谢你, 安德鲁
这是我一直在尝试的代码的简化版本:
Public Sub atest()
Dim filePath As String
Dim breakIdentity As String
Dim piece As String
Dim newFilePath As String
Dim strIn As String
Dim lineCtr As Long
filePath = Sheets("Parse").Range("A2").Value
newFilePath = Replace(filePath, ".txt", "-ReFormatted.txt")
Open filePath For Input As #1
Open newFilePath For Output As #2 'HERE IS WHERE I GET FILE ALREADY OPEN ERRORS ON LARGE FILES
Do While Not EOF(1)
Line Input #1, strIn
If Len(strIn) > 1 Then
lineCtr = lineCtr + 1
If InStr(strIn, breakIdentity) <> 0 And lineCtr > 1 Then
Print #2, strIn
Debug.Print strIn
End If
End If
Loop
Close #1
Close #2
MsgBox "Done"
End Sub
这是 txt/xml 的示例...
<?xml version="1.0" encoding="UTF-8"?>
<TagValidationList>
<TVLHeader>
<SubmissionType>STVL</SubmissionType>
<SubmissionDateTime>2017-10-02T01:03:15Z</SubmissionDateTime>
<SSIOPHubID>9002</SSIOPHubID>
<HomeAgencyID>9002</HomeAgencyID>
<BulkIndicator>B</BulkIndicator>
<BulkIdentifier>32</BulkIdentifier>
<RecordCount>15482798</RecordCount>
</TVLHeader>
<TVLDetail>
<TVLTagDetails>
<HomeAgencyID>0041</HomeAgencyID>
<TagAgencyID>1110</TagAgencyID>
<TagSerialNumber>01234567</TagSerialNumber>
<TagStatus>V</TagStatus>
<TagClass>2</TagClass>
<TVLPlateDetails>
<PlateCountry>US</PlateCountry>
<PlateState>TX</PlateState>
<PlateNumber>ABC123</PlateNumber>
<PlateEffectiveFrom>2010-09-09T15:57:05Z</PlateEffectiveFrom>
</TVLPlateDetails>
<TVLAccountDetails>
<AccountNumber>7654321</AccountNumber>
</TVLAccountDetails>
</TVLTagDetails>
<TVLTagDetails>
<HomeAgencyID>0041</HomeAgencyID>
<TagAgencyID>1110</TagAgencyID>
<TagSerialNumber>21234567</TagSerialNumber>
<TagStatus>V</TagStatus>
<TagType>S</TagType>
<TagClass>2</TagClass>
<TVLPlateDetails>
<PlateCountry>US</PlateCountry>
<PlateState>TX</PlateState>
<PlateNumber>BBC123</PlateNumber>
<PlateEffectiveFrom>2010-09-09T16:14:43Z</PlateEffectiveFrom>
</TVLPlateDetails>
<TVLAccountDetails>
<AccountNumber>6543210</AccountNumber>
</TVLAccountDetails>
</TVLTagDetails>
<TVLTagDetails>
<HomeAgencyID>0041</HomeAgencyID>
<TagAgencyID>1110</TagAgencyID>
<TagSerialNumber>31234567</TagSerialNumber>
<TagStatus>V</TagStatus>
<TagClass>2</TagClass>
<TVLPlateDetails>
<PlateCountry>US</PlateCountry>
<PlateState>TX</PlateState>
<PlateNumber>CBC123</PlateNumber>
<PlateEffectiveFrom>2010-09-09T15:58:15Z</PlateEffectiveFrom>
</TVLPlateDetails>
<TVLAccountDetails/>
</TVLTagDetails>
</TVLDetail>
</TagValidationList>
【问题讨论】:
-
如果它是一个有效的 xml 文件,您应该考虑使用适当的 xml 解析器(对于大文件,最好使用 SAX 解析器)。您还可以使用 XSLT 转换 xml 以生成所需的输出。
-
也许使用 SQL Server Express 是一种选择。请参阅:microsoft.com/en-ca/sql-server/sql-server-editions-express。您应该能够使用它导入整个数据集并更轻松地对其进行分析。
-
我不能保证 XML 的格式正确。我的伙伴尝试了几个解析器,他们声明文件格式不正确。我们不知道这是因为文件大小还是格式。我会检查他是否尝试过 SAX。 SAX 所需的编码超出了我的能力范围。我已经简要介绍了 XSLT。它会处理 6gb 的文件大小吗?
-
谢谢。我现在正在研究 SQL Server Express。关于 XSLT,即使它巧妙地转换文件,我仍然必须将其导出为文本文件。这不会造成与我现在的文件大小相同的问题吗?
-
您可以将该文件拆分为更易于管理的较小文件,然后解析较小的文件以获取内容。