Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
Вернулся
 Аватар для HackerVlad
1751 / 647 / 45
Регистрация: 10.09.2021
Сообщений: 2,800

Функция подсчёта количества строк в файле на VB6 (для всех кодировок файлов)

03.03.2023, 18:02. Показов 1876. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет! В моих проектах, мне иногда надо подсчитывать количество строк в файле. Я очень долго искал самый быстрый способ это сделать. Особенно когда файлы по 50-100 МБ и количество строк в этих файлах доходит до миллиона или даже больше... Усложняется ситуация тогда, когда файлы имеют разные кодировки. Сейчас я написал две функции для ANSI и UTF8 кодировки и для UTF16.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Option Explicit
Private Declare Function IsFileAPI Lib "shlwapi" Alias "PathFileExistsA" (ByVal pszPath As String) As Long
Private Declare Function StrStrA Lib "shlwapi" (ByVal pszFirst As Long, ByVal pszSrch As Long) As Long
Private Declare Function StrStrW Lib "shlwapi" (ByVal pszFirst As Long, ByVal pszSrch As Long) As Long
 
' Подсчитать количество строк в файле, в кодировке ANSI или UTF8
Public Function CountStrsFromFileA(FileName As String) As Long
    Dim FileNo As Integer
    Dim str() As Byte
    Dim fLen As Long
    Dim NewLine As Long
    Dim FirstSearch As Long
    Dim SearchFromTheSymbol As Long
    Dim cnt As Long
    
    If IsFileAPI(FileName) = 0 Then Exit Function ' Файл не существует, с вероятностью 99%
    fLen = FileLen(FileName)
    If fLen = 0 Then Exit Function
    
    ' Инициализировать счётчик
    FileNo = FreeFile
    
    ' Открыть файл
    Open FileName For Binary As FileNo
        ReDim str(fLen - 1)
        Get #FileNo, , str
    Close FileNo
    
    cnt = 1
    SearchFromTheSymbol = VarPtr(str(0))
    NewLine = StrPtr(vbNewLine)
    
    Do
        FirstSearch = StrStrA(SearchFromTheSymbol, NewLine) ' Искать нужную нам строку
        If FirstSearch > 0 Then
            cnt = cnt + 1
            SearchFromTheSymbol = FirstSearch + 2 ' + vbcrlf
        End If
    Loop While FirstSearch > 0 ' Выполнять цикл до тех пор, пока будет найдена искомая подстрока
    
    CountStrsFromFileA = cnt
End Function
 
' Подсчитать количество строк в файле, в кодировке UTF16LE или UTF16BE (работает даже без BOM)
Public Function CountStrsFromFileW(FileName As String) As Long
    Dim FileNo As Integer
    Dim str() As Byte
    Dim fLen As Long
    Dim NewLine As Long
    Dim FirstSearch As Long
    Dim SearchFromTheSymbol As Long
    Dim cnt As Long
    Dim i As Long
    
    If IsFileAPI(FileName) = 0 Then Exit Function ' Файл не существует, с вероятностью 99%
    fLen = FileLen(FileName)
    If fLen = 0 Then Exit Function ' Если в файле 0 байт значит в файле 0 строк
    
    ' Инициализировать счётчик
    FileNo = FreeFile
    
    ' Открыть файл
    Open FileName For Binary As FileNo
        ReDim str(fLen - 1)
        Get #FileNo, , str
    Close FileNo
    
    ' Если файл это файл размером один байт
    If UBound(str) < 1 Then
        If str(0) = 13 Then cnt = 2
        
        CountStrsFromFileW = cnt
        Exit Function
    End If
    
    If str(0) = 254 And str(1) = 255 Then ' UTF16BE
        SearchFromTheSymbol = VarPtr(str(1)) ' Изменим адресацию поиска +1 байт
        NewLine = StrPtr(Chr(13) & Chr(0) & Chr(10))
    Else ' UTF16LE обычное
        SearchFromTheSymbol = VarPtr(str(0))
        NewLine = StrPtr(vbNewLine)
    End If
    
    cnt = 1 ' Будем предполагать, что в файле всегда есть хотя бы одна строка, если в файле не 0 байт конечно...
    
    Do
        FirstSearch = StrStrW(SearchFromTheSymbol, NewLine) ' Искать нужную нам строку
        If FirstSearch > 0 Then
            cnt = cnt + 1
            SearchFromTheSymbol = FirstSearch + 4 ' + vbcrlf
        End If
    Loop While FirstSearch > 0 ' Выполнять цикл до тех пор, пока будет найдена искомая подстрока
    
    If cnt = 1 Then ' Если ничего не найдено, попытаться поискать снова (на случай если в файле UTF16BE была утрачена запись BOM)
        SearchFromTheSymbol = VarPtr(str(1)) ' Изменим адресацию поиска +1 байт
        NewLine = StrPtr(Chr(13) & Chr(0) & Chr(10))
    
        Do
            FirstSearch = StrStrW(SearchFromTheSymbol, NewLine) ' Искать нужную нам строку
            If FirstSearch > 0 Then
                cnt = cnt + 1
                SearchFromTheSymbol = FirstSearch + 4 ' + vbcrlf
            End If
        Loop While FirstSearch > 0 ' Выполнять цикл до тех пор, пока будет найдена искомая подстрока
    End If
    
    CountStrsFromFileW = cnt
End Function
Это самый быстрый способ подсчитать количество строк в файле, но самый быстрый лишь в среде выполнения IDE VB6 или в откомпилированном P-коде. В откомпилированном Native-коде со всеми галочками оптимизации конечно же будет работать быстрее (но только чуть-чуть быстрее) простой цикл перебора, но не в самом VB6!!!

В этой функции я сразу здесь ищу, символы перехода на новую строку, сразу в байтовом массиве. Без лишних присвоений и копирований в строку (так экономится и память и скорость). Думал также сделать, искать в байтовом массиве через встроенную функцию InStr но не получилось! Функция InStr не ищет в байтовом массиве, а ищет только в строке! Поэтому я хотел бы узнать, почему функция InStr не ищет в байтовом массиве? Если байтовый массив это массив содержимого файла.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.03.2023, 18:02
Ответы с готовыми решениями:

Написать программу подсчета количества строк в тексте в бинарном файле
Хочу чтобы считало мои текстовый документ, не могу, что не так? #include &lt;iostream&gt; #include &lt;ios&gt; #include &lt;fstream&gt; ...

Написать программу подсчета количества строк в файле (желательно, не используя буферы)
Добрый день. У меня такая проблема, нужно посчитать количество строк в файле, но без буферизации, так как файл может быть очень большим....

Функция замены всех отрицательных элементов массива нулями и подсчета количества замен
Объявить делегат. Реализовать функции ввода и вывода элементов одномерного массива. Создать экземпляры делегата, вызвать реализованные...

25
 Аватар для Mikle Quits
787 / 308 / 17
Регистрация: 21.01.2023
Сообщений: 530
04.03.2023, 12:06
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от HackerVlad Посмотреть сообщение
плюс минус эти доли секунды
Когда ты измеряешь малые доли секунды, это имеет значение.
0
Вернулся
 Аватар для HackerVlad
1751 / 647 / 45
Регистрация: 10.09.2021
Сообщений: 2,800
04.03.2023, 12:48  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
ошибку нашел, исправил. Спасибо за тест!
А новый код не выложил...
0
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
04.03.2023, 12:54
Цитата Сообщение от HackerVlad Посмотреть сообщение
А новый код не выложил...
Обновил же.
0
Вернулся
 Аватар для HackerVlad
1751 / 647 / 45
Регистрация: 10.09.2021
Сообщений: 2,800
04.03.2023, 14:30  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Обновил же.
Я не знал что так можно. Только модератор может? У меня даже ссылку не получалось поменять в сообщении.

Добавлено через 1 час 13 минут
Или вот самая простая функция с обычным циклом. Но она будет только в натив-коде более ни менее быстро работать.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
' Подсчитать количество строк в файле, в кодировке ANSI или UTF8
Public Function CountStrsFromFileSimple(FileName As String) As Long
    Dim FileNo As Integer
    Dim str() As Byte
    Dim fLen As Long
    Dim cnt As Long
    Dim i As Long
    
    If IsFileAPI(FileName) = 0 Then Exit Function ' Файл не существует, с вероятностью 99%
    fLen = FileLen(FileName)
    If fLen = 0 Then Exit Function
    
    ' Инициализировать счётчик
    FileNo = FreeFile
    
    ' Открыть файл
    Open FileName For Binary As FileNo
        ReDim str(fLen - 1)
        Get #FileNo, , str
    Close FileNo
    
    cnt = 1
    
    For i = 0 To UBound(str)
        If str(i) = 10 Then ' vbLf
            cnt = cnt + 1
        End If
    Next
    
    CountStrsFromFileSimple = cnt
End Function
Обычный поиск Chr(10). Но вопрос у меня в том почему в UTF16 на 3 Chr(10) больше находит? На три строки как бы больше чем надо.

Добавлено через 17 минут
То есть у меня возникает вопрос, а может ли быть в тексте файла Chr(10) не относящийся к переходу на следующею строку?
0
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
04.03.2023, 14:54
Цитата Сообщение от HackerVlad Посмотреть сообщение
То есть у меня возникает вопрос, а может ли быть в тексте файла Chr(10) не относящийся к переходу на следующею строку?
В UTF16 два байта на элемент, нужно тестировать 2 байта.
0
Вернулся
 Аватар для HackerVlad
1751 / 647 / 45
Регистрация: 10.09.2021
Сообщений: 2,800
04.03.2023, 15:47  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
нужно тестировать 2 байта
Да, ты прав, я уже придумал код даже простой.

Итак если переход на новую строку в ANSI файлах это 0D 0A. Будем искать именно 0D 0A для начала.
Потом если переход на новую строку в файлах UTF16 LE это 0D 00 0A 00,
а в файлах UTF16 BE это 00 0D 00 0A то мы видим что во всех вариантах UTF16 переход на новую строку включает в себя три символа 0D 00 0A это верняк, будет определять как в UTF16 LE так и в UTF16 BE. Поэтому я написал такую функцию:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
' Подсчитать количество строк в файле во всех кодировках
Public Function CountStrsFromFileUniversal(FileName As String) As Long
    Dim FileNo As Integer
    Dim str() As Byte
    Dim fLen As Long
    Dim cnt As Long
    Dim i As Long
    
    If IsFileAPI(FileName) = 0 Then Exit Function ' Файл не существует, с вероятностью 99%
    fLen = FileLen(FileName)
    If fLen = 0 Then Exit Function
    
    ' Инициализировать счётчик
    FileNo = FreeFile
    
    ' Открыть файл
    Open FileName For Binary As FileNo
        ReDim str(fLen - 1)
        Get #FileNo, , str
    Close FileNo
    
    cnt = 1
    
    For i = 0 To UBound(str)
        If str(i) = 10 Then ' vbLf
            If i <> 0 Then
                If str(i - 1) = 13 Then ' Если предыдущий символ это vbCr
                    cnt = cnt + 1
                End If
                If str(i - 1) = 0 Then ' Если предыдущий символ это ноль
                    If i > 1 Then
                        If str(i - 2) = 13 Then ' Если два символа назад это vbCr
                            cnt = cnt + 1
                        End If
                    End If
                End If
            End If
        End If
    Next
    
    CountStrsFromFileUniversal = cnt
End Function
Точно определяет во всех кодировках. Тестировал в ANSI, UTF8, UTF16 LE и UTF16 BE.

Добавлено через 39 минут
Единственный минус этой функции CountStrsFromFileUniversal получается что если в файлах будет один байт 0A или 0D для перехода на новую строку, то функция не будет работать получается так как она ищет именно vbCrLf то есть 0D 0A. Но зато во всех кодировках видит. А если искать только 0A то в UTF16 кодировках уже может немного неправильно определять, но не во всех файлах тоже... А моя эта функция во всех файлах определяет верно где переход строки это именно 0D 0A.

Добавлено через 7 минут
Может тогда нужно для ANSI и UTF8 искать просто 0A а для UTF16 искать просто 00 0A?
Но для ANSI тогда можно искать так же и просто 0D тоже. Вдруг у кого будет такой символ перехода просто 0D.

Скорее всего для ANSI лучше всего искать просто 0A или 0D а для UTF16 просто 00 0A или просто 0D 00. Скорее всего так лучше всего будет.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.03.2023, 15:47

Написать программу для подсчета количества слов в файле
Помогите решить задачу на с++. Создать текстовый файл, состоящий из одной строки и содержит слова, разделенные символом пропуска, знаки...

Создать приложение для подсчета количества пробел в текстовом файле
Использовать оператор цикла while.

Программа для подсчета количества строк в тексте
Нужно написать программу, для подсчета количества строк в текстовом файле, и каждые 5 строк она должна делать абзац. Помогите пожалуйста,...

Функция для подсчета суммы и количества элементов больше K
Добрый вечер! Есть задачка одна - звучит так: С помощью генератора случайных чисел сформировать квадратную матрицу вещественных чисел...

Рекурсивная функция для подсчета количества в структуре TreeView
Здравствуйте. Прошу помочь разобраться и написать рекурсивную функцию для подсчета количества человек в отделе, описанной в структуре...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Новые блоги и статьи
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат» Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru