我的要求有点不同。我经常使用逗号分隔和制表符分隔的 ASCII 文件,其中单行是单条数据记录。而且它们真的很大,所以我需要将它们分成可管理的部分(同时保留标题行)。
所以,我恢复了我的经典 VBScript 方法,并拼凑了一个可以在任何 Windows 计算机上运行的小型 .vbs 脚本(它由 Window 上的 WScript.exe 脚本主机引擎自动执行)。
这种方法的好处是它使用文本流,因此不会将底层数据加载到内存中(或者至少不是一次全部加载)。结果是它非常快,并且运行起来并不需要太多内存。我刚刚在 i7 上使用此脚本拆分的测试文件的文件大小约为 1 GB,有大约 1200 万行测试并制作了 25 个部分文件(每个文件大约有 500k 行)——处理大约需要 2 分钟,但它没有'在任何时候都不会超过 3 MB 内存。
这里需要注意的是,它依赖于具有“行”的文本文件(意味着每条记录用 CRLF 分隔),因为文本流对象使用“ReadLine”函数一次处理一行。但是,嘿,如果您使用的是 TSV 或 CSV 文件,那就完美了。
Option Explicit
Private Const INPUT_TEXT_FILE = "c:\bigtextfile.txt" 'The full path to the big file
Private Const REPEAT_HEADER_ROW = True 'Set to True to duplicate the header row in each part file
Private Const LINES_PER_PART = 500000 'The number of lines per part file
Dim oFileSystem, oInputFile, oOutputFile, iOutputFile, iLineCounter, sHeaderLine, sLine, sFileExt, sStart
sStart = Now()
sFileExt = Right(INPUT_TEXT_FILE,Len(INPUT_TEXT_FILE)-InstrRev(INPUT_TEXT_FILE,".")+1)
iLineCounter = 0
iOutputFile = 1
Set oFileSystem = CreateObject("Scripting.FileSystemObject")
Set oInputFile = oFileSystem.OpenTextFile(INPUT_TEXT_FILE, 1, False)
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
iLineCounter = 1
sHeaderLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sHeaderLine)
End If
Do While Not oInputFile.AtEndOfStream
sLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sLine)
iLineCounter = iLineCounter + 1
If iLineCounter Mod LINES_PER_PART = 0 Then
iOutputFile = iOutputFile + 1
Call oOutputFile.Close()
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
Call oOutputFile.WriteLine(sHeaderLine)
End If
End If
Loop
Call oInputFile.Close()
Call oOutputFile.Close()
Set oFileSystem = Nothing
Call MsgBox("Done" & vbCrLf & "Lines Processed:" & iLineCounter & vbCrLf & "Part Files: " & iOutputFile & vbCrLf & "Start Time: " & sStart & vbCrLf & "Finish Time: " & Now())