У меня есть большой текстовый файл (около 1,7 ГБ). Я хочу открыть его, прочитать в строку, заменить различные символы, записать строку обратно в текстовый файл и закрыть его.
Кто-нибудь может подсказать, как это сделать быстрее?
Мой код работает, но довольно медленно:
Function RemoveCharactersFromText(sFile as string) as string
Dim sText as String
dim sLineContect as String
Dim iFileNum as Integer
Open sFile for Input as iFileNum
Do Until EOF(iFileNum)
Line Input #iFileNaum, sLineContent
sText = sText & sLineContent & vbCrLf
Loop
Close iFileNum
On Error Resume Next
sText = Replace(sText, ",", "")
sText = Replace(sText, "#", "")
sText = Replace(sText, "*", "")
sText = Replace(sText, "+", "")
sText = Replace(sText, " = ", "")
sText = Replace(sText, Chr(34), "")
sText = Replace(sText, "null", "")
On Error GoTo 0
iFileNum = FreeFile
Open sFile for Output as iFileNum
Print #iFileNum, sText
Close iFileNum
iFileNum = 0
Я попробовал записать весь текстовый файл в строку одним ударом:
Open sFile for Input as FreeFile
sText = Input(EOF(iFileNum), iFileNum)
Я также пробовал через FSO:
With CreateObject("Scripting.FileSystemObject")
sText = .OpenTextFile(sFile, 1).ReadAll
End With
И получите ошибки с обоими из них.
Есть идеи? Спасибо!
ОТРЕДАКТИРОВАНО: я изменил sTemp на sText. Это была опечатка, когда я копировал код. Извините за путаницу!
Ваш код ничего не делает. Он считывает файл построчно в sTemp
, затем игнорирует его и использует sText
, который пуст. Непонятно, почему вам нужно сначала построить всю строку, поскольку вы можете выполнять замену построчно. Что правильно сделать с файлом размером 1,7 ГБ, потому что после того, как вы прочитаете его таким образом, это будет строка размером 3,4 ГБ, за исключением того, что вы не можете иметь строку такого размера.
Вам следует избегать использования replace
по одному символу несколько раз. Те будут выделять снова и снова. Рассмотрите возможность использования промежуточного и небольшого буфера и очищайте его при обнаружении непредвиденного символа.
Программа UNIX sed
отлично подходит для подобных задач (также можно использовать команду cut
, если она предназначена только для удаления символов). Если вы работаете на компьютере с Windows, вы можете рассмотреть возможность установки Cygwin для этого.
Какую ошибку вызывают фрагменты кода, извлекающие содержимое файла сразу? Вы пробуете это в Windows? Все это, кроме опечатки (strTemp
вместо sText
)...
Извиняюсь - допустил опечатку. Оба должны быть sText.
My original post worked on 189MB but I could not read a 185 GB file using a buffer. This code processed the file in 121 seconds. Thanks GSerg.
Sub Test2()
Const SourceFilePath As String = "D:\Test.txt"
Const DestFilePath As String = "D:\Test_Output.txt"
Dim t As Double
t = Timer
' Process the file
RemoveTextInFileByReplace SourceFilePath, DestFilePath
' Replace the original file with the processed file
On Error Resume Next
Kill DestFilePath ' Delete the original source file
On Error GoTo 0
Debug.Print Timer - t
End Sub
Sub RemoveTextInFileByReplace(ByVal SourceFilePath As String, ByVal DestFilePath As String)
Dim SourceFile As Integer, DestFile As Integer
Dim FileLine As String
' Open the source file for reading
SourceFile = FreeFile
Open SourceFilePath For Input As #SourceFile
' Open the destination file for writing
DestFile = FreeFile
Open DestFilePath For Output As #DestFile
' Read the file line by line
Do While Not EOF(SourceFile)
Line Input #SourceFile, FileLine
FileLine = Replace(FileLine, ",", "")
FileLine = Replace(FileLine, "#", "")
FileLine = Replace(FileLine, "*", "")
FileLine = Replace(FileLine, "+", "")
FileLine = Replace(FileLine, " = ", "")
FileLine = Replace(FileLine, Chr(34), "")
FileLine = Replace(FileLine, "null", "")
Print #DestFile, FileLine ' Write the modified line to the destination file
Loop
' Close the files
Close #SourceFile
Close #DestFile
End Sub
"null"
может в конечном итоге занимать два буфера и не будет заменен. Воссоздание регулярного выражения для каждой строки также является сомнительным решением.
@GSerg Я обновил свой ответ, чтобы обработать файл дважды, удвоив размер буфера на втором проходе. Текстовый файл размером 189 МБ он обработал примерно за 11 секунд, что кажется разумным. Что вы думаете?
Думаю, это перебор :) И переобрабатывать односимвольные замены вроде бы не требуется, они гарантированно заменяются при первом проходе. Если не известно, что файл представляет собой одну огромную строку, вероятно, проще выполнить линейный ввод, как это делает OP. Только не объединяя все это.
@GSerg Причина, по которой я хотел использовать RegEx, заключается в том, что я знаю, что замена большого текста выполняется намного быстрее. При этом я не смог прочитать 189 ГБ, используя буферный подход. Я обновил чтение кода построчно. еще раз спасибо
Спасибо @TinMan — это работает очень хорошо. Очень ценю.
Создайте инструмент на .NET VB.