Мое требование было немного по-другому. Я часто работаю с файлами с разделителями-запятыми и с разделителями табуляции ASCII, где одна строка является одной записью данных. И они действительно большие, поэтому мне нужно разбить их на управляемые части (при сохранении строки заголовка).
Итак, я вернулся к своему классическому методу VBScript и собрал небольшой скрипт .vbs, который можно запустить на любом компьютере под управлением Windows (он автоматически запускается движком хоста сценария WScript.exe в окне).
Преимущество этого метода состоит в том, что он использует текстовые потоки, поэтому базовые данные не загружаются в память (или, по крайней мере, не все одновременно). В результате это происходит исключительно быстро, и на самом деле не нужно много памяти для запуска.Тестовый файл, который я только что разделил, используя этот скрипт на моем i7, составлял около 1 ГБ в размере файла, имел около 12 миллионов строк текста и был разделен на 25 файлов частей (каждая из которых имела около 500 тыс. Строк каждая) - обработка заняла около 2 минут и он не переходил на 3 МБ памяти, используемой в любой момент.
Предостережение здесь заключается в том, что он опирается на текстовый файл, имеющий «линии» (что означает, что каждая запись разделена CRLF), поскольку объект Text Stream использует функцию «ReadLine» для обработки одной строки за раз. Но, если вы работаете с TSV или CSV-файлами, это прекрасно.
Option Explicit
Private Const INPUT_TEXT_FILE = "c:\bigtextfile.txt"
Private Const REPEAT_HEADER_ROW = True
Private Const LINES_PER_PART = 500000
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())
Это именно то, что я искал, и спасибо за подтверждение моей догадки, что получение контента не очень велико с большими файлами. –
Полезный совет: вы можете выразить числа вроде этого ... $ upperBound = 5MB – Lee
Для тех, кто слишком ленив, чтобы прочитать следующий ответ, вы можете установить объект $ reader через $ reader = new-object System.IO.StreamReader ($ inputFile) – lmsurprenant