Зачем нужен Open Statement, когда есть FSO? Думаю, как многие из вас… — Дневник VBAшника — TG.ME

Зачем нужен Open Statement, когда есть FSO?

Думаю, как многие из вас, я мало задумывался над тем каким способом читать текстовые файлы. FileSystemObject (FSO) — удобно, просто, работает.

И вот наступил момент, когда любопытство взяло верх: решил проверить на практике, насколько велика разница.


🖥 Тест: три способа чтения, один большой файл

Для теста я взял обычный текстовый файл объемом около 200 Мб (для наглядности) и выбрал три разных подхода для чтения данных:
▶️FSO — привычный способ через OpenTextFile().ReadAll()
▶️Open For Input — построчное чтение
▶️Open For Binary Access Read — побайтовое чтение всего файла за раз

Результаты оказались весьма показательными (скрин ниже).
Binary Access просто разорвал конкурентов на больших объемах.
Там, где FSO и Input начинают тупить, Binary метод справляется моментально.

ℹ️ Сразу оговорюсь:
на маленьких файлах разница практически незаметна, но когда дело доходит до больших объемов, Binary Access просто творит чудеса!
👏



🧑‍💻 Код для теста

Можно потестить у себя.
Просто вставьте код ниже в любой модуль, сохраните файл в удобном месте, разместите рядом текстовый файл test.txt для теста или укажите свое имя в константе FILE_PATH.
'@Folder("VBAProject")
Option Explicit

Const FILE_PATH As String = "test.txt"

Public Sub Run()
Const LINE_SEP As String = "------------"

FileSystem.ChDir ThisWorkbook.Path

FSORead
Debug.Print LINE_SEP
RegularRead
Debug.Print LINE_SEP
BinaryRead
Debug.Print LINE_SEP
End Sub

Public Sub RegularRead()
Dim t As Single
t = DateTime.Timer

Dim n As Integer
n = FileSystem.FreeFile()

Dim Buffer() As String
ReDim Buffer(255)

Dim i As Long
Open FILE_PATH For Input As #n
While Not FileSystem.EOF(n)
If i > UBound(Buffer) Then
ReDim Preserve Buffer(Conversion.CLng(UBound(Buffer) * 1.5))
End If
Line Input #n, Buffer(i)
i = i + 1
Wend
Close #n

ReDim Preserve Buffer(i - 1)

Dim Data As String
Data = Strings.Join(Buffer, vbNewLine)

Debug.Print "RegularRead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "RegularRead:", "Data len: "; Strings.Len(Data)
End Sub

Public Sub BinaryRead()
Dim t As Single
t = DateTime.Timer

Dim n As Integer
n = FileSystem.FreeFile()

Dim i As Long
Open FILE_PATH For Binary Access Read As #n
Dim Buffer() As Byte
ReDim Buffer(FileSystem.LOF(n) - 1)
Get #n, , Buffer
Close #n

Dim Data As String
Data = Strings.StrConv(Buffer, vbUnicode)

Debug.Print "BinaryRead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "BinaryRead:", "Data len: "; Strings.Len(Data)
End Sub

Public Sub FSORead()
Dim t As Single
t = DateTime.Timer

Dim FSO As FileSystemObject
Set FSO = New FileSystemObject

Dim Data As String
Data = FSO.OpenTextFile(FILE_PATH, ForReading).ReadAll()

Debug.Print "FSORead:", "Reading time: "; (DateTime.Timer - t) * 1000 & "ms"
Debug.Print "FSORead:", "Data len: "; Strings.Len(Data)
End Sub


Stay tuned
❤️

Дневник VBAшника
🔥9❤6👍2
March 31, 2025 794 15 6