В VBA: открывайте, читайте, заменяйте символы и закрывайте текстовый файл максимально быстро

У меня есть большой текстовый файл (около 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. Это была опечатка, когда я копировал код. Извините за путаницу!

Создайте инструмент на .NET VB.

rotabor 26.08.2024 11:11

Ваш код ничего не делает. Он считывает файл построчно в sTemp, затем игнорирует его и использует sText, который пуст. Непонятно, почему вам нужно сначала построить всю строку, поскольку вы можете выполнять замену построчно. Что правильно сделать с файлом размером 1,7 ГБ, потому что после того, как вы прочитаете его таким образом, это будет строка размером 3,4 ГБ, за исключением того, что вы не можете иметь строку такого размера.

GSerg 26.08.2024 11:30

Вам следует избегать использования replace по одному символу несколько раз. Те будут выделять снова и снова. Рассмотрите возможность использования промежуточного и небольшого буфера и очищайте его при обнаружении непредвиденного символа.

user-id-14900042 26.08.2024 11:50

Программа UNIX sed отлично подходит для подобных задач (также можно использовать команду cut, если она предназначена только для удаления символов). Если вы работаете на компьютере с Windows, вы можете рассмотреть возможность установки Cygwin для этого.

Dominique 26.08.2024 11:52

Какую ошибку вызывают фрагменты кода, извлекающие содержимое файла сразу? Вы пробуете это в Windows? Все это, кроме опечатки (strTemp вместо sText)...

FaneDuru 26.08.2024 12:24

Извиняюсь - допустил опечатку. Оба должны быть sText.

Jennifer Brady 27.08.2024 00:00
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
6
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
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 26.08.2024 13:36

@GSerg Я обновил свой ответ, чтобы обработать файл дважды, удвоив размер буфера на втором проходе. Текстовый файл размером 189 МБ он обработал примерно за 11 секунд, что кажется разумным. Что вы думаете?

TinMan 26.08.2024 15:28

Думаю, это перебор :) И переобрабатывать односимвольные замены вроде бы не требуется, они гарантированно заменяются при первом проходе. Если не известно, что файл представляет собой одну огромную строку, вероятно, проще выполнить линейный ввод, как это делает OP. Только не объединяя все это.

GSerg 26.08.2024 16:24

@GSerg Причина, по которой я хотел использовать RegEx, заключается в том, что я знаю, что замена большого текста выполняется намного быстрее. При этом я не смог прочитать 189 ГБ, используя буферный подход. Я обновил чтение кода построчно. еще раз спасибо

TinMan 26.08.2024 17:15

Спасибо @TinMan — это работает очень хорошо. Очень ценю.

Jennifer Brady 27.08.2024 00:19

Другие вопросы по теме

Похожие вопросы