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

Как правильно открыть TXT файл для чтения, например чтобы запихнуть в TextBox или просто загрузить в массив строк

17.09.2023, 18:23. Показов 3363. Ответов 82
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Я ещё раньше не занимался этим вопросом с помощью API-функций, так как всегда работал с помощью стандартных методов VB6. А теперь, поняв фундаментальный недостаток VB6-метода (отсутствие поддержки юникода в именах файлов), я хочу научиться открывать/загружать стандартный текстовый файл с помощью API.

Итак, за это отвечает у нас функция ReadFile, но уважаемый The Trick, я посмотрел, загружает файлы каким-то странным, другим способом, через функции CreateFileMapping и MapViewOfFile, я если честно в этом ничего не понимаю. Смотрел описание этих функций так толком и не понял зачем их использовать вместо стандартного ReadFile.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.09.2023, 18:23
Ответы с готовыми решениями:

GDI+ как освободить файл или открыть только для чтения
Добрый день! Занимаюсь написанием своего графического редактора на ассемблере. Последняя версия http://esm.ho.ua/Automat.html Нужна...

Как открыть доступ для чтения файла 'output.txt'?
Пример: program Project2; {$APPTYPE CONSOLE} uses SysUtils; var f1,f2:Text;

Как поток чтения (или записи) запихнуть в класс?
Здравствуйте!!! Ребят, подскажите пожалуйста, собственно, как запихнуть в класс поток ifstream? Че-то я озадачен оказался *-) Без...

82
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
21.09.2023, 21:13
Лучший ответ Сообщение было отмечено HackerVlad как решение

Решение

Студворк — интернет-сервис помощи студентам
Цитата Сообщение от HackerVlad Посмотреть сообщение
The trick, ну вот я тебе и доказал, что ты был неправ, что массив быстрее будет
Массив будет быстрее, просто в таких условиях это не заметно. Чтобы увидеть разницу нужно делать множество итераций на мелких данных + нужно массивы мапить на память также как ты делаешь через SysAllocStringByteLen.

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
Public Function ReadFileUTF8_2(ByVal FileName As String) As String
    Dim hFile   As OLE_HANDLE
    Dim tSADesc As SAFEARRAY
    Dim bData() As Byte
    Dim lRead   As Long
    Dim lSize   As Long
    Dim pStr    As Long
    Dim pRet    As Long
    Dim lStrLen As Long
 
    hFile = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0)
    
    If hFile = INVALID_HANDLE_VALUE Then
        Exit Function
    End If
 
    lSize = GetFileSize(hFile, ByVal 0&) ' Этот метод только до 2Гб
    
    If lSize <= 0 Then
        GoTo CleanUp
    End If
 
    With tSADesc
    
        .cDims = 1
        .cbElements = 1
        .fFeatures = FADF_AUTO
        .pvData = CoTaskMemAlloc(lSize)
        .Bounds.cElements = lSize
        
        If .pvData = 0 Then
            Debug.Print "no mem"
            GoTo CleanUp
        End If
        
    End With
    
    PutMem4 ArrPtr(bData), VarPtr(tSADesc)
 
    If ReadFile(hFile, tSADesc.pvData, lSize, lRead, ByVal 0&) = 0 Then
        Debug.Print "ReadFile failed"
        GoTo CleanUp
    End If
    
    If lRead >= 3 Then
        If bData(0) = &HEF And bData(1) = &HBB And bData(2) = &HBF Then ' Если есть запись BOM
            pStr = tSADesc.pvData + 3
            lRead = lRead - 3
        Else
            pStr = tSADesc.pvData
        End If
    Else
        pStr = tSADesc.pvData
    End If
        
    lStrLen = MultiByteToWideChar(CP_UTF8, 0&, pStr, lRead, 0&, 0&)
    
    If lStrLen > 0 Then
        
        pRet = SysAllocStringLen(0&, lStrLen)
        
        If pRet = 0 Then
            Debug.Print "no mem"
            GoTo CleanUp
        End If
        
        PutMem4 VarPtr(ReadFileUTF8_2), pRet
        
        If pStr Then
             If MultiByteToWideChar(CP_UTF8, 0&, pStr, lRead, pRet, lStrLen) = 0 Then
                ReadFileUTF8_2 = vbNullString
             End If
        End If
        
    End If
    
CleanUp:
    
    If tSADesc.pvData Then
        CoTaskMemFree ByVal tSADesc.pvData
    End If
    
    CloseHandle hFile
    
End Function
При 100000 итерациях уже заметна разница. Да и сам глянь вот ассемблерный листинг твоего кода:

, а вот через массивы:
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
21.09.2023, 23:11  [ТС]
The trick, спасибо большое за труды, но ты забыл скопировать декларации и например я даже не знаю как объявлять структуру SAFEARRAY, вообще никогда с этим не работал.

Добавлено через 2 минуты
В твоих других кодах я пока нашёл только структуру SafeArray1d просто SafeArray пока нигде не нашёл ещё

Добавлено через 3 минуты
Я смотрю много твоих других примеров и везде встречаю только SAFEARRAYBOUND и SAFEARRAY1D структуры. SAFEARRAY просто пока нигде не могу найти.

Добавлено через 2 минуты
Ну ты и задал мне задачку. Нигде не могу найти структуру SAFEARRAY просто. SAFEARRAY1D есть только у тебя. SAFEARRAY2D в апи вьювере.

Добавлено через 37 секунд
Может это одно и тоже?

Добавлено через 1 минуту
Предположу что это одно и тоже, спустя 10 минут безуспешных поисков...

Добавлено через 7 минут
Ну наконец-то я ели нарыл всё недостающее. В итоге я НЕ почувствовал разницы в скорости в сравнении с моим методом со строкой. Но теперь твой массив зато стал работать так же быстро как и в случае со строкой. Полный код:

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
Option Explicit
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal Ptr As Long, ByVal Value As Long)
Private Declare Function SysAllocStringByteLen Lib "oleaut32" (ByVal olestr As Long, ByVal BLen As Long) As Long
Private Declare Function SysAllocStringLen Lib "oleaut32" (ByVal olestr As Long, ByVal BLen As Long) As Long
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cbMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileW" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal pv As Long)
Private Declare Function CoTaskMemAlloc Lib "ole32" (ByVal cBytes As Long) As Long
Private Declare Function ArrPtr Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Var() As Any) As Long
 
Private Const OPEN_EXISTING As Long = 3
Private Const GENERIC_READ As Long = &H80000000
Private Const CP_UTF8 As Long = 65001
Private Const GENERIC_WRITE As Long = &H40000000
Private Const FILE_SHARE_READ = &H1
Private Const CREATE_ALWAYS = 2
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const FADF_AUTO As Long = 1
 
Private Type SAFEARRAYBOUND
    cElements                       As Long
    lLbound                         As Long
End Type
 
Private Type SAFEARRAY1D
    cDims                           As Integer
    fFeatures                       As Integer
    cbElements                      As Long
    cLocks                          As Long
    pvData                          As Long
    Bounds                          As SAFEARRAYBOUND
End Type
 
Public Function ReadFromTextFileUTF8(ByVal FileName As String) As String
    Dim hFile As Long
    Dim stringbuffer As String
    Dim numread As Long
    Dim FileSize As Long
    Dim nOutputCharLen As Long
    Dim lpMultiByteStr As Long
    
    hFile = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0)
    
    If hFile <> INVALID_HANDLE_VALUE Then
        FileSize = GetFileSize(hFile, ByVal 0&) ' Этот метод только до 2Гб
        
        If FileSize > 0 Then
            PutMem4 VarPtr(stringbuffer), SysAllocStringByteLen(0&, FileSize) ' Мгновенно выделить память для строки
            
            If ReadFile(hFile, StrPtr(stringbuffer), FileSize, numread, ByVal 0&) > 0 Then
                If MidB$(stringbuffer, 1, 3) = ChrW(&HBBEF) & ChrB(&HBF) Then ' Если есть запись BOM
                    lpMultiByteStr = StrPtr(stringbuffer) + 3
                Else
                    lpMultiByteStr = StrPtr(stringbuffer)
                End If
                
                nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, FileSize, 0&, 0&)
                If nOutputCharLen > 0 Then
                    PutMem4 VarPtr(ReadFromTextFileUTF8), SysAllocStringLen(0&, nOutputCharLen)
                    MultiByteToWideChar CP_UTF8, 0&, lpMultiByteStr, FileSize, StrPtr(ReadFromTextFileUTF8), nOutputCharLen ' Преобразовать кодировки
                End If
            End If
        End If
        
        CloseHandle hFile
    End If
End Function
 
Public Function ReadFileUTF(ByVal FileName As String) As String
    Dim hFile As Long
    Dim byte_array() As Byte
    Dim numread As Long
    Dim FileSize As Long
    Dim nOutputCharLen As Long
    Dim lpMultiByteStr As Long
    
    hFile = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0)
    
    If hFile <> INVALID_HANDLE_VALUE Then
        FileSize = GetFileSize(hFile, ByVal 0&) ' Этот метод только до 2Гб
        
        If FileSize > 0 Then
            ReDim Preserve byte_array(FileSize - 1)
            
            If ReadFile(hFile, VarPtr(byte_array(0)), FileSize, numread, ByVal 0&) > 0 Then
                If byte_array(0) = &HEF And byte_array(1) = &HBB And byte_array(2) = &HBF Then ' Если есть запись BOM
                    lpMultiByteStr = VarPtr(byte_array(3))
                Else
                    lpMultiByteStr = VarPtr(byte_array(0))
                End If
                
                nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, FileSize, 0&, 0&)
                If nOutputCharLen > 0 Then
                    PutMem4 VarPtr(ReadFileUTF), SysAllocStringLen(0&, nOutputCharLen)
                    
                    If Len(ReadFileUTF) = nOutputCharLen Then ' Если строка была успешно выделена (специально для The Trick) чтобы не придерался ко мне
                        MultiByteToWideChar CP_UTF8, 0&, lpMultiByteStr, FileSize, StrPtr(ReadFileUTF), nOutputCharLen ' Преобразовать кодировки
                    End If
                End If
            End If
        End If
        
        CloseHandle hFile
    End If
End Function
 
Public Function ReadFileUTF8_2(ByVal FileName As String) As String
    Dim hFile   As OLE_HANDLE
    Dim tSADesc As SAFEARRAY1D
    Dim bData() As Byte
    Dim lRead   As Long
    Dim lSize   As Long
    Dim pStr    As Long
    Dim pRet    As Long
    Dim lStrLen As Long
 
    hFile = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0)
    
    If hFile = INVALID_HANDLE_VALUE Then
        Exit Function
    End If
 
    lSize = GetFileSize(hFile, ByVal 0&) ' Этот метод только до 2Гб
    
    If lSize <= 0 Then
        GoTo CleanUp
    End If
 
    With tSADesc
    
        .cDims = 1
        .cbElements = 1
        .fFeatures = FADF_AUTO
        .pvData = CoTaskMemAlloc(lSize)
        .Bounds.cElements = lSize
        
        If .pvData = 0 Then
            Debug.Print "no mem"
            GoTo CleanUp
        End If
        
    End With
    
    PutMem4 ArrPtr(bData), VarPtr(tSADesc)
 
    If ReadFile(hFile, tSADesc.pvData, lSize, lRead, ByVal 0&) = 0 Then
        Debug.Print "ReadFile failed"
        GoTo CleanUp
    End If
    
    If lRead >= 3 Then
        If bData(0) = &HEF And bData(1) = &HBB And bData(2) = &HBF Then ' Если есть запись BOM
            pStr = tSADesc.pvData + 3
            lSize = lSize - 3
        Else
            pStr = tSADesc.pvData
        End If
    Else
        pStr = tSADesc.pvData
    End If
        
    lStrLen = MultiByteToWideChar(CP_UTF8, 0&, pStr, lRead, 0&, 0&)
    
    If lStrLen > 0 Then
        
        pRet = SysAllocStringLen(0&, lStrLen)
        
        If pRet = 0 Then
            Debug.Print "no mem"
            GoTo CleanUp
        End If
        
        PutMem4 VarPtr(ReadFileUTF8_2), pRet
        
        If pStr Then
             If MultiByteToWideChar(CP_UTF8, 0&, pStr, lRead, pRet, lStrLen) = 0 Then
                ReadFileUTF8_2 = vbNullString
             End If
        End If
        
    End If
    
CleanUp:
    
    If tSADesc.pvData Then
        CoTaskMemFree ByVal tSADesc.pvData
    End If
    
    CloseHandle hFile
    
End Function
 
' Тестируем загрузку файла размером 180 Мб
Private Sub Command1_Click()
    Dim tick As Long
    Dim str As String
    
    tick = GetTickCount
    
    str = ReadFromTextFileUTF8("C:\Test\Test.txt") ' 843 ml
    
    Me.Caption = GetTickCount - tick
    
    Text1.Text = Mid$(str, 1, 1000)
End Sub
 
Private Sub Command2_Click()
    Dim tick As Long
    Dim str As String
    
    tick = GetTickCount
    
    str = ReadFileUTF("C:\Test\Test.txt") ' 889 ml
    
    Me.Caption = GetTickCount - tick
    
    Text1.Text = Mid$(str, 1, 1000)
End Sub
 
Private Sub Command3_Click()
    Dim tick As Long
    Dim str As String
    
    tick = GetTickCount
    
    str = ReadFileUTF8_2("C:\Test\Test.txt") ' 843 ml
    
    Me.Caption = GetTickCount - tick
    
    Text1.Text = Mid$(str, 1, 1000)
End Sub
Добавлено через 1 минуту
The trick, в итоге: кода гораздо больше нужно писать, а разницы в скорости НЕТУ!!!
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
21.09.2023, 23:13
Я уже написал как увидеть разницу.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
21.09.2023, 23:45  [ТС]
Разозлившись, сейчас буду тестировать аж целых 500 Мб на загрузку, чтобы проверить а есть ли всё же хоть какая-то разница в скорости.

Добавлено через 1 минуту
На 500 Мб у меня не хватает памяти) Пхахаххаах, разбежался блин пхахахах

Добавлено через 2 минуты
The trick, кстати ты говорил мол я не делаю проверок на случай если памяти не хватит. Вот я решил загрузить 500 Мб, памяти не хватило и ничего не произошло. Краха программы не случилось. Просто вернуло пустую строку.

Добавлено через 1 минуту
Так что получается проверку делать не обязательно.

Добавлено через 5 минут
The trick, на 10-20 млск меньше времени твой способ, при максимальном 450 Мб файле что я только могу загрузить, на 500 у меня уже оперативки не хватает просто

Добавлено через 51 секунду
Цитата Сообщение от The trick Посмотреть сообщение
Я уже написал как увидеть разницу.
короче говоря разницы нету с моим изначальным способом со строкой

Добавлено через 2 минуты
Ну вот как бы ты не хаил мой способ со строкой, а он не медленнее чем твой. А ты пытался доказать что он медленнее.

Добавлено через 9 минут
Цитата Сообщение от The trick Посмотреть сообщение
При 100000 итерациях уже заметна разница.
Аааа вот где разница? Как буд-то я по 100 тысяч раз буду файл загружать. Один раз загрузил и хватит. Ну хорошо твой способ чуть-чуть быстрее, даже для одного раза на 10 млск быстрее. Но смысл... Я не знаю, кода писать гораздо больше надо...

Добавлено через 6 минут
The trick, так что ты меня извини пожалуйста, ноя не вижу смысла переходить на твою технологию, я нормально написал функцию изначально загружая в строку. по крайне мере кода писать нужно гораздо меньше. скорость одинаковая.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
22.09.2023, 11:49
Интересно, почему именно байтовый массив, а не ,допустим integer? Меньше переменных, меньше сущностей в памяти типа.. Хотя, я так понимаю, байтовый это классика.
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
22.09.2023, 12:44
Цитата Сообщение от HackerVlad Посмотреть сообщение
Я не знаю, кода писать гораздо больше надо...
Да не пиши, что ты от меня хочешь? Тебе объяснил что этот код быстрее чем со строками - даже асм листинг кинул. Не веришь/лень писать несколько строчек - твое дело. В конечном итоге код работает тысячи раз, когда программист пишет его всего один раз. Лучше потратить чуть больше времени и написать больше кода, что в итоге выльется в более оптимальный и меньший по размеру код, но ты можешь делать так как захочешь.

Цитата Сообщение от testuser2 Посмотреть сообщение
Интересно, почему именно байтовый массив, а не ,допустим integer? Меньше переменных, меньше сущностей в памяти типа.. Хотя, я так понимаю, байтовый это классика.
Можно любой массив, просто файл может быть и 3 байта и 1 и где Integer просто не поместится.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
22.09.2023, 17:24  [ТС]
testuser2, с UTF-8 форматом Integer не проканает, только с UTF16

Добавлено через 42 секунды
testuser2, там просто на один сивол может быть то один байт, то два байта фиг поймешь

Добавлено через 1 минуту
The Trick меня короче не убедил, весь день переписывал свои коды, смотрел скорости - всё зря, мой код со стркоами вполне оптимален

Добавлено через 11 минут
Как буд-то я файл по 100 тысяч раз загружаю, можно подумать

Добавлено через 8 секунд
Провёл очень много тестов

Добавлено через 10 секунд
The Trick не убедил ни скольео
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
23.09.2023, 15:16  [ТС]
Тем ни менее, хоть я и не очень согласен с The Trick, но тем ни менее моя тема называется как правильно открыть TXT файл. Поэтому я помечу ответ The Trick как решение, потому что у него чуть более правильный вариант, чем у меня, и на 10 млск быстрее. На этом тему мы закончили, я думаю.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
23.09.2023, 17:26
В любом случае это быстрые методы. Кстати, сейчас проверил, буфер строки можно расширять с помощью HeapRealloc, так же как и массив. Только после этого надо менять заголовочный указатель у строки на новый.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 19:53  [ТС]
Придётся вернуться к этой теме снова, так как я обнаружил ошибку в своей функции ReadFromTextFileUTF8. Если в загружаемом файле есть запись BOM то функция загружала на 3 байта больше чем нужно. Эту ошибку я исправил:

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
Public Function ReadFromTextFileUTF8(ByVal FileName As String) As String
    Dim hFile As Long
    Dim stringbuffer As String
    Dim numread As Long
    Dim FileSize As Long
    Dim nOutputCharLen As Long
    Dim lpMultiByteStr As Long
    Dim IsBOM As Boolean
    
    hFile = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0)
    
    If hFile <> INVALID_HANDLE_VALUE Then
        FileSize = GetFileSize(hFile, ByVal 0&) ' Этот метод только до 2Гб
        
        If FileSize > 0 Then
            PutMem4 VarPtr(stringbuffer), SysAllocStringByteLen(0&, FileSize) ' Мгновенно выделить память для строки
            
            If ReadFile(hFile, StrPtr(stringbuffer), FileSize, numread, ByVal 0&) > 0 Then
                If MidB$(stringbuffer, 1, 3) = ChrW(&HBBEF) & ChrB(&HBF) Then ' Если есть запись BOM
                    lpMultiByteStr = StrPtr(stringbuffer) + 3
                    IsBOM = True
                Else
                    lpMultiByteStr = StrPtr(stringbuffer)
                End If
                
                nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, FileSize, 0&, 0&)
                If nOutputCharLen > 0 Then
                    PutMem4 VarPtr(ReadFromTextFileUTF8), SysAllocStringLen(0&, nOutputCharLen - IIf(IsBOM, 3, 0))
                    MultiByteToWideChar CP_UTF8, 0&, lpMultiByteStr, FileSize, StrPtr(ReadFromTextFileUTF8), nOutputCharLen ' Преобразовать кодировки
                End If
            End If
        End If
        
        CloseHandle hFile
    End If
End Function
Теперь функция окончательно вполне оптимальная. Её тоже можно было бы в лучшие ответы пометить как решение кстати.
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.09.2023, 21:35
Цитата Сообщение от HackerVlad Посмотреть сообщение
nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, FileSize, 0&, 0&)
А это что? Какой FileSize?
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 21:39  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
А это что? Какой FileSize?
Ошибку ещё одну нашёл? А что там надо? nOutputCharLen что ли?

Добавлено через 1 минуту
Да вроде FileSize надо. Что не так?

Добавлено через 47 секунд
Заранее я ведь не знаю будущий размер буфера, поэтому я тебя не понимаю.
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.09.2023, 21:42
Цитата Сообщение от HackerVlad Посмотреть сообщение
Да вроде FileSize надо. Что не так?
Ну во-первых, ReadFile возвращает число фактических прочитанных байт в numread.
Во-вторых, когда ты делаешь lpMultiByteStr = StrPtr(stringbuffer) + 3 то размер у тебя соответственно уменьшается.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 21:52  [ТС]
The trick, то есть надо написать либо FileSize -3 либо numread или numread -3?

Добавлено через 1 минуту
может numread просто? без -3
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.09.2023, 21:52
Цитата Сообщение от HackerVlad Посмотреть сообщение
numread -3
Нужно корректировать размер если у тебя BOM.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 21:55  [ТС]
numread просто надо, без -3
с -3 уже не работает код падает

Добавлено через 28 секунд
Для узнавания буфера (первый вызов функции):

Visual Basic
1
nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, numread, 0&, 0&) ' Получить размер буфера в символах
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.09.2023, 21:55
Смотри как у меня сделано.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 21:57  [ТС]
Поменял FileSize на numread

Добавлено через 2 минуты
Правильно ли я тебя понимаю что ты предлагаешь мне в SysAllocStringLen не отризать 3 символа, как я это сделал, а отрезать в другом месте
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
24.09.2023, 21:59
HackerVlad, вот ты узнал размер файла, к примеру 30 байт. Ок. Смотришь первый BOM (если файл больше или равен 3 байтам). Если BOM присутствует то ты пропускаешь его при конверсии в UTF-16, правильно? Правильно. Ты так и делаешь, но передаешь что в функцию MultiByteToWideChar те же 30 байт. Вопрос - что получит функция если у тебя буфер в 30 байт, ты пропускаешь первые 3 и просишь ее конвертировать 30 (!) байт? Правильно - чтение за пределом буфера и неверный результат преобразования.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
24.09.2023, 22:00  [ТС]
Проверяй мои исправления:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
' Прочитать файл, ровно столько байтов, сколько нужно
            If ReadFile(hFile, StrPtr(stringbuffer), FileSize, numread, ByVal 0&) > 0 Then
                If MidB$(stringbuffer, 1, 3) = ChrW(&HBBEF) & ChrB(&HBF) Then ' Если есть запись BOM
                    lpMultiByteStr = StrPtr(stringbuffer) + 3
                    IsBOM = True
                Else
                    lpMultiByteStr = StrPtr(stringbuffer)
                End If
                
                nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, numread - IIf(IsBOM, 3, 0), 0&, 0&) ' Получить размер буфера в символах
                If nOutputCharLen > 0 Then
                    PutMem4 VarPtr(stringbuffer2), SysAllocStringLen(0&, nOutputCharLen)
                    
                    ' Преобразовать кодировки
                    If MultiByteToWideChar(CP_UTF8, 0&, lpMultiByteStr, numread - IIf(IsBOM, 3, 0), StrPtr(stringbuffer2), nOutputCharLen) > 0 Then
                        QuickSplit2 stringbuffer2, DataList, vbNewLine ' Быстро преобразовать строку в массив
                        SuccessfullyLoaded = True
                    End If
                End If
            End If
Теперь правильно?

Добавлено через 1 минуту
Я работаю только с UTF8.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.09.2023, 22:00

Открыть файл и загрузить содержимое в TextBox
Доброго времени суток! Ребят помогите справиться с задачей есть код по открытие файла private void toolStripMenuItem2_Click(object...

Как расшифровать файл dat или просто открыть его и вывести на экран
Мне нужно открыть файл с расширением dat и вывести на экран Как это сделать, дайте пожалуйста примерный код

Открыть для записи текстовый файл data.txt и записать в него полученный массив, закрыть файл
Составить программу с подпрограммами для выполнения следующего алгоритма (предусмотреть процедуры записи и чтения информации из файла). ...

Как открыть файл для чтения?
некоторый дивайс пишет данные в текстовый файл , мне нужно не прерывая и не мешая дивайсу прочитать этот файл делаю так var ...

Файл: Как можно открыть файл txt и занести из него данные в массив?
как можно открыть файл txt и занести из него данные в массив, а после из этого массива вывести в выпадающий список значения? заранее...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата) Этот документ предназначен для того, чтобы новый чат Claude мог продолжить работу без необходимости заново разбираться в. . .
сукцессия 15 неявная схема
anaschu 29.06.2026
Алиса Калибровка параметров симбиотической модели: технический обзор Содержание: Введение Постановка проблемы Технические аспекты реализации Процесс внедрения изменений
сукцессия 14. Обновленная схема модели
anaschu 28.06.2026
ГЛОБАЛЬНАЯ ОПИСАТЕЛЬНАЯ СПЕЦИФИКАЦИЯ ЭКОСИСТЕМНОЙ МОДЕЛИ «SOIL CHEMISTRY & MYCORRHIZA 2. 0» https:/ / ibb. co/ NnkGpfMd Представленная интегрированная схема описывает непрерывную нелинейную. . .
сукцессия 13. Питон модель трехзонного мицелия, пока что в основном арбускулярного
anaschu 28.06.2026
## Разработка агентной модели микоризной сукцессии: от выявления артефактов к созданию комплексной системы ### Аннотация Представлено исследование по разработке агентной модели микоризной. . .
сукцессия 12. краткий список проверок модели перед запуском.
anaschu 27.06.2026
Скрытые отказы в моделях систем динамики (SD-models) экологических систем: два случая из практики Контекст Разбирался прототип модели систем динамики (SD-модели) микоризной сукцессии: пять. . .
Сукцессия 11. Проверка орудий перед войной: разработка через тестирование
anaschu 27.06.2026
Как не дать модели соврать самой себе: проверки для симуляции микоризной сукцессии Введение Когда вы строите математическую модель живой системы — грибов, растений, почвы — главная опасность. . .
10 сукцессия. Питон код войны грибов и растений
anaschu 27.06.2026
import numpy as np class PlantAgent: def __init__(self, name, strategy, initial_biomass): self. name = name self. strategy = strategy # "greedy" (широколиственные) или. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru