Прочитать текстовый файл в кодировке UTF-8 BOM

Автор timal1234, 14 ноября 2025, 19:52

0 Пользователи и 1 гость просматривают эту тему.

timal1234

Всем привет!

Подскажите, как прочитать текстовый файл в кодировке UTF-8 BOM и записать его в массив.
в файле БОЛЕЕ 1 млн. строк!

Через
filenumber = Freefile
lineNumber = 1 '  с 1-ой строчки
Open file For Input As filenumber ' указывает, что мы используем это как вход для подпрограммы, а не то, что мы собираемся в неё что-то передавать
While not EOF(filenumber) ' пока не достигнут конец файла
Line Input #filenumber, iLine 'начинаем чтение файла  с 1-ой строчки и сохраняем текст строки в переменную iLine
If iLine <> "" then ' если не пустая строка в файле
Full_LOG(lineNumber - 1) =  iLine ' записываем в массив содержимое строки
lineNumber = lineNumber + 1 ' следующая линия
end if
wend
Close #filenumber
считывает быстро, но в ANSII.

Через
Dim Full_LOG(0 to 0)  As String ' массив текущего файла
Dim filePath
filePath = ConvertToUrl(file)

Dim oSFA As Object
oSFA = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")

IF NOT oSFA.exists(filePath) THEN
  MsgBox("!!!  НЕТ такого файла  !!!!  " + CHR(13) + "выход из макроса " , 0+0+48)
  Exit Sub
END IF

Dim oUcb, oInputStream, sInputLine$
oUcb = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
oInputStream = CreateUnoService("com.sun.star.io.TextInputStream")
oInputStream.setInputStream(oUcb.openFileRead(filePath))
oInputStream.setEncoding("UTF-8") 'UTF-8 format
lineNumber = 1
Do While Not oInputStream.isEOF()
Full_LOG(lineNumber - 1) =  oInputStream.readLine() ' записываем в массив  содержимое строки
ReDim Preserve Full_LOG(0 to lineNumber) As String
lineNumber = lineNumber + 1 ' следующая линия
Loop
oInputStream.closeInput()
не могу дождаться окончания (20 минут ждал и не дождался)

Что не так?
почему так долго длится чтение?
-----------
если не переопределять массив, а задать ему размер по количеству строк в файле Dim Full_LOG(0 to lineCount - 1)  As String, то ругается на Full_LOG(lineNumber - 1) =  oInputStream.readLine(), что индекс за перелами диапазона

bigor

Цитата: timal1234 от 14 ноября 2025, 19:52задать ему размер по количеству строк в файле
а как вы получаете lineCount ?
И для чего это все? если файл больше миллиона строк, то при одном символе в строке это минимум 2 Mb
Поддержать наш форум можно здесь

timal1234

Цитата: bigor от 14 ноября 2025, 23:25
Цитата: timal1234 от 14 ноября 2025, 19:52задать ему размер по количеству строк в файле
а как вы получаете lineCount ?
вот так:
'Get line count
lineCount = 0
filenumber = Freefile
Open file For Input As filenumber 'указывает , что мы используем это как вход для подпрограммы, а не то, что мы собираемся в неё что-то передавать

'Используйте EOF, чтобы избежать ошибок при попытке получить данные за концом файла.
'При использовании инструкции Input или Get для считывания из файла указатель позиции в файле продвигается на количество считанных байтов.
'Если конец файла достигнут, EOF возвращает значение "True" (-1).

While not EOF(filenumber) ' пока не достигнут конец файла
Line Input #filenumber, iLine 'cчитать текущую строку файла и сохранять в переменную ' iLine
If iLine <> "" then 'если не пустая строка в файле
lineCount = lineCount + 1 ' следующая строка (идём дальше вниз)
end if
wend
Close #filenumber

ЦитироватьИ для чего это все?
задача:
найти в лог-файле строки, удовлетворяющие условию и записать на лист (ну или в новый файл).
лог-файл содержит пути к файлам. и если считывать по первому способу, русские символы превращаются в крякозябры.
уже думаю, может проще макросом удалить из этого файла ненужные строки.

Цитироватьесли файл больше миллиона строк, то при одном символе в строке это минимум 2 Mb
вопрос не понял... да, файл большой - 200Мб

mikekaganski

#3
Цитата: timal1234 от 14 ноября 2025, 19:52почему так долго длится чтение?
А с чего Вы взяли, что это чтение?
Вы сами указали на переопределение массива. Правда, пришлось задавать дополнительные вопросы, где выяснилось, что Ваш метод подсчёта числа строк даст 0 для файла с одной пустой строкой и без перевода строки. Да и вообще любые пустые строки он будет игнорировать.

А главное: если результат нужен в другом файле или в документе, то зачем вообще промежуточный массив? Сразу туда и пишите.
С уважением,
Михаил Каганский

timal1234

Цитата: mikekaganski от 15 ноября 2025, 11:28А главное: если результат нужен в другом файле или в документе, то зачем вообще промежуточный массив? Сразу туда и пишите.
Получилось !
Спасибо огромное!

timal1234

получилось вот так:

Dim filePath
filePath = ConvertToUrl(file)

Dim x
x = 0

Dim OFFSET
OFFSET = 2

Dim oSFA As Object
oSFA = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")

IF NOT oSFA.exists(filePath) THEN
  MsgBox("!!!  НЕТ такого файла  !!!!  " + CHR(13) + "выход из макроса " , 0+0+48)
ThisComponent.Sheets.getByName("Инфицированные").getCellByPosition(1, 0).setString( "!!! ПРЕРВАНО !!!" )
  Exit Sub
END IF

Dim Curr_STR As String
Dim oUcb, oInputStream, sInputLine$
oUcb = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
oInputStream = CreateUnoService("com.sun.star.io.TextInputStream")
oInputStream.setInputStream(oUcb.openFileRead(filePath))
oInputStream.setEncoding("UTF-8") 'UTF-8 format
Do While Not oInputStream.isEOF()
Curr_STR =  oInputStream.readLine() ' записываем в переменную содержимое строки

IF InStr(Curr_STR, "Обучение") > 0 THEN
ThisComponent.Sheets.getByName("Результат").getCellByPosition(0, x+OFFSET).setString( Curr_STR )
x = x+ 1
END IF
Loop
oInputStream.closeInput()

bigor

Цитата: timal1234 от 15 ноября 2025, 10:29строки, удовлетворяющие условию
Почему же сразу при чтении строки не проверять ее на условие и записывать в массив только нужные. Вижу вы пошли по этому пути :)
Поддержать наш форум можно здесь

timal1234

Цитата: bigor от 15 ноября 2025, 12:34
Цитата: timal1234 от 15 ноября 2025, 10:29строки, удовлетворяющие условию
Почему же сразу при чтении строки не проверять ее на условие и записывать в массив только нужные. Вижу вы пошли по этому пути :)

просто у меня в заготовках были 2 варианта чтения файла...
первый как оказалось не работает с UTF-8.
второй (как он был изначально) не сработал вообще ....
я думал сначала надо файл загнать в массив, а потом что-то искать  ;D

ВСЕМ СПАСИБО !