【问题标题】:Opening, parsing, and saving a copy of a large txt or xml file (6gb)打开、解析和保存大型 txt 或 xml 文件 (6gb) 的副本
【发布时间】: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,即使它巧妙地转换文件,我仍然必须将其导出为文本文件。这不会造成与我现在的文件大小相同的问题吗?
  • 您可以将该文件拆分为更易于管理的较小文件,然后解析较小的文件以获取内容。

标签: xml vba parsing


【解决方案1】:

谢谢。我放弃了 VBA 路线。看起来它永远无法处理大文件。我选择了 DB 路线,并成功地将大型 XML 文件导入到单列单行表中,我已经能够在其中查询并生成更精简的平面 (TXT) 文件。我使用了在 URL here 找到的过程。

再次感谢, 安德鲁

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    相关资源
    最近更新 更多