Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/19: Рейтинг темы: голосов - 19, средняя оценка - 4.68
7 / 7 / 0
Регистрация: 21.12.2016
Сообщений: 152

FindFirstFile не корректно определяет имена файлов с диакритическими знаками

18.04.2023, 21:49. Показов 4894. Ответов 88
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток.

Делаю програмку, необходимо получить содержимое папки (список папок и файлов) и после определить ФАЙЛ или ПАПКА и другие атрибуты. Как всегда делал раньше, через API "FindFirstFile", привык, удобно и есть заготовки кода. И вот, выясняется такая неприятная ситуация. На компьютере есть несколько видео файлов с испанскими названиями.
В них содержатся слова с Диакритическими знаками.

например: "Niño cristiano GANA! concurso secular YouTube.flv español.mp4"

Как выяснилось, "FindFirstFile" возвращая имя этого файла, возвращает его как:
"Nino cristiano GANA! concurso secular YouTube.flv espanol.mp4" - ну и в дальнейшем соответственно вся обработка рушится.

Вот код, давно когда-то нашёл на просторах интернета и всегда использовал:

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
    Dim bstFileName As String
    Dim lngFileCount As Long
    Dim lngAPIReturn As Long
    Dim bstPath As String
    Dim bstCinteria As String
    Dim abstFileNames() As String
    Dim lngHSearch As Long
    Dim udtWFD As WIN32_FIND_DATA
   
    bstCinteria = iCinteria
    bstPath = iPath
    
    lngHSearch = INVALID_HANDLE_VALUE
    lngHSearch = FindFirstFile(bstPath & iCinteria, udtWFD)
    lngFileCount = -1&
       
    If lngHSearch <> INVALID_HANDLE_VALUE Then
        Do
            bstFileName = Left(udtWFD.cFileName, VBA.InStr(1, udtWFD.cFileName, Chr(0)) - 1) ', vbNullString)
            Stop
            If (bstFileName <> ".") And (bstFileName <> "..") Then
                lngFileCount = lngFileCount + 1
                ReDim Preserve abstFileNames(0& To lngFileCount) As String
                abstFileNames(lngFileCount) = bstFileName
            End If
            lngAPIReturn = FindNextFile(lngHSearch, udtWFD)
        Loop Until lngAPIReturn = 0&
        FindClose lngHSearch
    End If
 
    oFileNames = abstFileNames
    oMaxIdx = lngFileCount

Облазил весь интернет, так и не понял, как можно исправить данную ситуацию.

Читал на каком-то зарубежном С++ форуме, что используют FindFirstFileW и WIN32_FIND_DATAW
Но как это оформить и поможет ли это в моём случае, до конца так и не понял. Даже не понял, как объявить правильно на vb6.

Если не затруднит, подскажите кто знает, решение. А лучше готовый кусок кода. Буду очень признателен.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.04.2023, 21:49
Ответы с готовыми решениями:

Обработка символов с диакритическими знаками
Привет. Dim macron As String = &quot;M̄acron&quot; MsgBox(macron) For n As Integer = 0 To macron.Length - 1 MsgBox(macron(n)) ...

Укоротить длинные имена до размера K символов, а те имена, которые короче K символов дополнить восклицательными знаками
Дан список из N имён. Необходимо укоротить длинные имена до размера K символов, а те имена, которые короче K символов дополнить...

Работа с файлами поиск файлов FindFirstFile,FindNextFile
Доброго времени суток, спустя долгое время, с измученным гуглом я нашел решение проблемы, но создалась еще одна проблема ...

88
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
23.04.2023, 17:15
Студворк — интернет-сервис помощи студентам
ANSI строки - это многобайтовые строки. Я уже сказал как нужно делать - последний параметр WideCharToMultibyte говорит если при трансляции из UNICODE в ANSI возникают проблемы с представлением символа в нужной кодировке. Один раз вызвали - проверили последний параметр. Китайские символы точно также могут быть в ANSI кодировке, просто кодируются они не 1 байтом, а несколькими. 1-байтовые кодировки - это ASCII (ну и другие типа КОИ-8).
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
23.04.2023, 18:41
Цитата Сообщение от The trick Посмотреть сообщение
ANSI строки - это многобайтовые строки
Я всегда думал, что это однобайтовые, если честно))) Может я путал ASCII с ANSI конечно...
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
23.04.2023, 18:48
Цитата Сообщение от HackerVlad Посмотреть сообщение
Я всегда думал, что это однобайтовые, если честно))) Может я путал ASCII с ANSI конечно...
Не задумывался почему функция называется WideCharToMultibyte, MultibyteToWideChar?
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
23.04.2023, 18:54
Ты меня ни разу не попровил когда мы работали с ANSI файлами с поиском например, ты ни разу не сказал, что это файл не ANSI а ASCII мало того ты сам называл это ANSI хотя по факту там ОДИН байт на один символ! Даже в том файле что я тебе присылал 40МБ большой помнишь

Добавлено через 40 секунд
Поэтому я тебя не понимаю теперь уже вообще

Добавлено через 1 минуту
Цитата Сообщение от The trick Посмотреть сообщение
Не задумывался почему функция называется WideCharToMultibyte, MultibyteToWideChar?
Потому что они работают с преобразованием байтового массива, однако в байтовом массиве на один символ может быть как два так и один байт...
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
23.04.2023, 19:21
Цитата Сообщение от HackerVlad Посмотреть сообщение
Ты меня ни разу не попровил когда мы работали с ANSI файлами с поиском например, ты ни разу не сказал, что это файл не ANSI а ASCII мало того ты сам называл это ANSI хотя по факту там ОДИН байт на один символ! Даже в том файле что я тебе присылал 40МБ большой помнишь
Не нужно этого, я не раз тебе сказал что символ - это не байт. Почитай внимательно эту тему https://www.cyberforum.ru/post16797309.html, я там несколько раз сказал про это. И насчет кодировок говорил, и что код можно ускорить на определенных кодировках (однобайтовых). Ты вероятно не знаешь что такое многобайтовая кодировка.

Цитата Сообщение от HackerVlad Посмотреть сообщение
Потому что они работают с преобразованием байтового массива, однако в байтовом массиве на один символ может быть как два так и один байт...
Нет, потому что в Windows есть многобайтовые кодировки (ANSI) и Юникод (UTF-16).
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
23.04.2023, 19:30
Интересно, технически то все эти кодировки помещаются в одну и туже структуру и отличаются только кодами в символьном массиве?
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
23.04.2023, 19:37
Цитата Сообщение от testuser2 Посмотреть сообщение
Интересно, технически то все эти кодировки помещаются в одну и туже структуру и отличаются только кодами в символьном массиве?
Создайте Label на форме, задайте ему шрифт к примеру Arial Unicode MS. Введите какие-либо кириллические символы (это будут коды > 127) и меняйте кодировку в параметрах шрифта. https://www.cyberforum.ru/post5938617.html
0
7 / 7 / 0
Регистрация: 21.12.2016
Сообщений: 152
27.04.2023, 05:16  [ТС]
Доброго времени суток, ещё раз..

Вобщем как отловить это дело, я разобрался. Спасибо за советы!)

Теперь вот озадачился, как дать всем файлам не повторяющиеся имена.
Дело в том, что если я китайские иероглифы буду заменять просто на "_", то у меня все файлы будут получаться типа: "_____.png" - только с разным количеством символов. Повторы неизбежны. И вот я думаю, может сделать какой-то счётчик.

Типа 0000001 и в каждой новой папке его запускать с нуля, наверное так. Пишу вот сейчас и мысль пришла)) пошёл пробовать.
0
Модератор
10060 / 3905 / 885
Регистрация: 22.02.2013
Сообщений: 5,854
Записей в блоге: 79
27.04.2023, 06:59
https://learn.microsoft.com/en... pfilenamew
1
7 / 7 / 0
Регистрация: 21.12.2016
Сообщений: 152
27.04.2023, 09:14  [ТС]
The trick, Спасибо, это лучшее решение.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
27.04.2023, 12:07
Цитата Сообщение от The trick Посмотреть сообщение
https://learn.microsoft.com/en... pfilenamew
А зачем любая программа на VB6 создаёт tmp-файл и как от этого избавиться?
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
29.04.2023, 22:30
В программе Vector06C у The Trick, в классе CTextFile.cls, есть функция IsInputTextUnicode, которая обращается к API-функции IsTextUnicode из библиотеки advapi32.dll. Так вот эта функция должна бы определять есть ли в строке уникод, но по факту получается, что если строка содержит русские символы то функция считает, что это уникод. Только если все английские то считает что это не уникод...

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
Private Function IsInputTextUnicode( _
                 ByVal pData As Long, _
                 ByVal lSize As Long, _
                 ByRef bIsBigEndian As Boolean) As Boolean
    Dim lFlags  As Long
    
    lFlags = -1
    
    If IsTextUnicode(ByVal pData, lSize, lFlags) Then
        If lSize < 100 And lFlags = IS_TEXT_UNICODE_STATISTICS Then
            IsInputTextUnicode = False
        Else
        
            If lFlags = IS_TEXT_UNICODE_REVERSE_STATISTICS Then
                bIsBigEndian = True
            Else
                bIsBigEndian = False
            End If
            
            IsInputTextUnicode = True
            
        End If
    End If
    
End Function
Добавлено через 5 часов 25 минут
Цитата Сообщение от Dragokas Посмотреть сообщение
GetFileDate
Можно передавать либо путь к файлу (либо его хендл последним аргументом).
Если не интересует получение даты и времени файла именно по открытому дескриптору, а только по имени файла, то лучше всего подойдёт функция GetFileAttributesEx вместо связки громоздкого CreateFile и GetFileTime.

Вот нашёл у иностранцев код:
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
Option Explicit
Private Declare Function GetFileAttributesEx Lib "kernel32" Alias "GetFileAttributesExW" (ByVal lpFileName As Long, ByVal fInfoLevelId As Long, ByVal lpFileInformation As Long) As Long
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (ByVal lpFileTime As Long, ByVal lpLocalFileTime As Long) As Long
Private Declare Function FileTimeToSystemTime Lib "kernel32" (ByVal lpFileTime As Long, ByVal lpSystemTime As Long) As Long
 
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
 
Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
 
Private Type WIN32_FILE_ATTRIBUTE_DATA
dwFileAttributes As Long
FTCreationTime As FILETIME
FTLastAccessTime As FILETIME
FTLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
End Type
 
' (VB-Overwrite)
Public Function FileDateTime(ByVal PathName As String) As Date
Dim FAD As WIN32_FILE_ATTRIBUTE_DATA
If Left$(PathName, 2) = "\\" Then PathName = "UNC\" & Mid$(PathName, 3)
If GetFileAttributesEx(StrPtr("\\?\" & PathName), 0, VarPtr(FAD)) <> 0 Then
    Dim FT As FILETIME, ST As SYSTEMTIME
    FileTimeToLocalFileTime VarPtr(FAD.FTLastWriteTime), VarPtr(FT)
    FileTimeToSystemTime VarPtr(FT), VarPtr(ST)
    FileDateTime = DateSerial(ST.wYear, ST.wMonth, ST.wDay) + TimeSerial(ST.wHour, ST.wMinute, ST.wSecond)
Else
    Err.Raise Number:=53, Description:="File not found: '" & PathName & "'"
End If
End Function
Я проверил, функция работает просто отлично, но вариант Драгокаса тоже хороший. Просто использовать CreateFile слишком муторно. Да и в этом коде у иностранцев так же добавлено в функцию преобразование UNC путей, а у Драгокаса такого нету, у него только из фишек это Wow64FSRedirection.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
30.09.2023, 08:22
Цитата Сообщение от HackerVlad Посмотреть сообщение
' Список файлов или подкаталогов в каталоге с помощью API (с поддержкой уникода)
Немного оптимизировал твою функцию. Конечно еще для скорости не очень хорошо писать все в массив строк, да еще делать redim preserve в каждой итерации, а лучше лить все в один большой буфер. Ты сам вроде бы в другой теме двигался в эту сторону.
Кликните здесь для просмотра всего текста
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
Public Function ListFilesOrDirsAPI2(Directory As String, StrArray() As String, Optional ListFiles As Boolean) As Long
    Dim DirName As String
    Dim hSearch As Long
    Dim WFD As WIN32_FIND_DATA_UNICODE
    Dim Cont As Long
    Dim cnt As Long, c As Long
    Dim lpStr As Long
    
    If Right(Directory, 1) <> "\" Then Directory = Directory & "\"
    
    Cont = True
    hSearch = FindFirstFileW(StrPtr(Directory & "*"), WFD)
    
    If hSearch <> INVALID_HANDLE_VALUE Then
        lpStr = VarPtr(WFD.cFileName(0))  '= VarPtr(WFD.dwReserved1) + 4
        PutMem4 VarPtr(DirName), lpStr    'меняем указатель строки на WFD.cFileName(0)
        Do While Cont
'            If DirName <> "." And DirName <> ".." Then
            If c = 2& Then                 'пропускаем первые 2 итерации
                WFD.dwReserved1 = lstrlen(lpStr) * 2 'пишем длину строки в WFD.dwReserved1 (=StrPtr(DirName)-4)
                If ListFiles = False Then
                    If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) <> 0 Then ' Если это каталог
                        ReDim Preserve StrArray(cnt)
                        StrArray(cnt) = DirName
                        
                        cnt = cnt + 1
                    End If
                Else
                    If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = 0 Then ' Если это не каталог
                        ReDim Preserve StrArray(cnt)
                        StrArray(cnt) = DirName
                        
                        cnt = cnt + 1
                    End If
                End If
            Else: c = c + 1
            End If
            
            Cont = FindNextFileW(hSearch, WFD)
        Loop
        PutMem4 VarPtr(DirName), 0&
        Cont = FindClose(hSearch)
    End If
    
    If cnt > 0 Then ListFilesOrDirsAPI2 = cnt
End Function


Добавлено через 5 минут
Вместо lstrlen(lpStr) * 2 можно просто искать, нуль в wfd.cFileName(), но, скорее всего, lstrlen будет бытрее

Добавлено через 16 минут
В идеале я вижу, так, что нужно писать строки в один общий буфер (как в StringBuilder-е), периодически расширяя его большими порциями с помощью HeapReAlloc. Параллельно можно писать в строковый массив указатели с этого буфера, если нужен именно массив.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
30.09.2023, 08:48
testuser2, поковырялся в этой функции и хорошо, я рад, что тебе она понравилась, конечно же я не делал упор на оптимизацию скорости тут, что касательно массивов то для XP нужно выделять буфер скажем ну сразу на 1000 строк. Итак каждую 1000 строк например подкачивать, для семёрки это не критично, так как ReDim Preserve StrArray(cnt) каждую интерацию работает быстро в семёрке. Пропускать первые две интерации это ты конечно интересно придумал, но вдруг в первой и второй интерации не будут позиции "." и ".." с точки зрения производительности ты хоть одну миллисекунду выиграл вообще? Я считаю что If DirName <> "." And DirName <> ".." Then будет лучше.

Добавлено через 1 минуту
Цитата Сообщение от testuser2 Посмотреть сообщение
PutMem4 VarPtr(DirName), 0&
А и ещё меня эта строчка удивила, зачем?

Добавлено через 2 минуты
testuser2, например, в корне диска, первые две позиции могут быть уже другими, а не "." и ".."
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
30.09.2023, 08:54
Цитата Сообщение от HackerVlad Посмотреть сообщение
А и ещё меня эта строчка удивила, зачем?
Возврат указателя DirName$. Нужно обязательно возвращать указатели. У DirName он меняется перед циклом, поэтому в конце процедуры нужно обязательно вернуть старый указатель, точнее 0 (неинициализированая строка)
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
30.09.2023, 08:56
Кстати эта функция я знаю что она не совершенна, например она не позволяет добавлять файлы БЕЗ КАТАЛОГОВ а мне это недавно понадобилось и пришлось переписать функцию. Плюс со всеми вложенными подпапками. Плюс добавил рекурсию. Для бесконечного поиска папок и файлов ровно до тех пор пока они будут найдены.

Это мой новый шедевр гениальности моей (можешь посмотреть если интересно), тут ещё плюс даты и время файлов и их размер, недавно написал как раз новый модуль:

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
Option Explicit
'////////////////////////////////////////////////////////
'// Модуль поиска файлов на винчестере                 //
'// Copyright (c) 04.09.2021, 05.09.2023 by HackerVlad //
'// e-mail: vladislavpeshkov@ya.ru                     //
'// Версия 2.2                                         //
'////////////////////////////////////////////////////////
Private Declare Function FindFirstFileW Lib "kernel32" (ByVal lpFileName As Long, lpFindFileData As WIN32_FIND_DATA_UNICODE) As Long
Private Declare Function FindNextFileW Lib "kernel32" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA_UNICODE) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Private Declare Function SysAllocStringLen Lib "oleaut32" (ByVal olestr As Long, ByVal BLen As Long) As Long
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal ptr As Long, ByVal Value As Long)
Private Declare Function PathRemoveExtensionW Lib "shlwapi" (ByVal pszPath As Long) As Long
 
Private Const MAX_PATH = 260
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
 
Dim add_cnt As Long
Dim all_cnt As Long
Dim Masks() As String
 
Private Type WIN32_FIND_DATA_UNICODE
    dwFileAttributes As Long
    ftCreationTime As Currency
    ftLastAccessTime As Currency
    ftLastWriteTime As Currency
    nFileSizeHigh As Long
    nFileSizeLow As Long
    dwReserved0 As Long
    dwReserved1 As Long
    cFileName(MAX_PATH) As Integer
    cAlternate(14) As Integer
End Type
 
Public Type PathsFileName
    PathDirName As String
    PathFileOrDirName As String
    PathFileSize As Currency
    PathDateTime As Currency
End Type
 
' Вручную сравниваем маски типов файлов
Private Function IsStrMaskEquivalentFileName(ByVal MaskStr As String, ByVal FileName As String) As Boolean
    Dim lNullPos As Long
    Dim StrMask As String
    Dim PathFileName As String
    Dim SearchExtension As String
    
    StrMask = Trim$(MaskStr)
    
    If StrMask <> "*.*" And StrMask <> "*" Then
        If Mid$(StrMask, 1, 1) = "*" Then ' Любое имя файла
            If Mid$(StrMask, 2, 1) = "." Then
                SearchExtension = Mid$(StrMask, 3)
                
                If Right$(FileName, Len(SearchExtension)) = SearchExtension Then
                    IsStrMaskEquivalentFileName = True
                End If
            End If
        Else ' Конкретное имя файла
            If Right$(StrMask, 2) = ".*" Then ' Любое расширение
                ' Получить имя файла до точки
                PathRemoveExtensionW StrPtr(StrMask)
                lNullPos = InStr(1, StrMask, vbNullChar)
                If lNullPos Then StrMask = Left$(StrMask, lNullPos - 1)
                
                PathFileName = FileName
                PathRemoveExtensionW StrPtr(PathFileName)
                lNullPos = InStr(1, PathFileName, vbNullChar)
                If lNullPos Then PathFileName = Left$(PathFileName, lNullPos - 1)
                
                If StrMask = PathFileName Then
                    IsStrMaskEquivalentFileName = True
                End If
            Else ' Конкретное имя файла и конкретное расширение
                If StrMask = FileName Then
                    IsStrMaskEquivalentFileName = True
                End If
            End If
        End If
    Else
        IsStrMaskEquivalentFileName = True
    End If
End Function
 
' Поиск файлов на винчестере
Public Function FindFilesAPI(path As String, FilesArray() As PathsFileName, Optional MaskStr As String, Optional AddDateAndSizeFiles As Boolean = True, Optional IncludeDirectories As Boolean = True, Optional Interrupt As Boolean, Optional FileCount As Long, Optional DirCount As Long) As Currency
    Dim lpStr As Long
    Dim FileName As String
    Dim dirNames() As String
    Dim nDir As Long
    Dim i As Long
    Dim hSearch As Long
    Dim WFD As WIN32_FIND_DATA_UNICODE
    Dim Cont As Long
    Dim cntMask As Byte
    Dim AddFileOrDir As Boolean
    Dim FileSize As Currency
    
    If FileCount = 0 Then ' Первый раз
        add_cnt = 0
        all_cnt = 0
        Erase Masks
    End If
    
    If Right(path, 1) <> "\" Then path = path & "\"
    nDir = 0
    ReDim dirNames(nDir)
    Cont = True
    hSearch = FindFirstFileW(StrPtr(path & "*"), WFD)
    
    If hSearch <> INVALID_HANDLE_VALUE Then
        Do While Cont
            lpStr = VarPtr(WFD.dwReserved1) + 4
            PutMem4 VarPtr(FileName), SysAllocStringLen(0, lstrlen(lpStr)) ' Мгновенно выделить память для строки
            lstrcpy StrPtr(FileName), lpStr ' Копирование строк
            
            all_cnt = all_cnt + 1
            If Right$(Trim$(Str$(all_cnt)), 3) = "000" Then ' Каждая тысяча строк
                If Interrupt = True Then
                    DoEvents ' Прерывание
                End If
            End If
            
            If FileName <> "." And FileName <> ".." Then
                AddFileOrDir = False
                FileSize = 0
                
                If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) <> 0 Then ' Если это каталог
                    dirNames(nDir) = FileName
                    DirCount = DirCount + 1
                    nDir = nDir + 1
                    ReDim Preserve dirNames(nDir)
                    
                    If IncludeDirectories = True Then
                        AddFileOrDir = True
                    End If
                Else ' Если это файл
                    If Len(MaskStr) > 0 Then
                        If InStr(1, MaskStr, ";") > 0 Then ' Маска содержит несколько типов файлов
                            If FileCount = 0 Then ' Первый раз
                                Masks = Split(MaskStr, ";") ' Расщепить строку на массив только один раз
                            End If
                            
                            For cntMask = 0 To UBound(Masks)
                                If IsStrMaskEquivalentFileName(Masks(cntMask), FileName) = True Then
                                    AddFileOrDir = True
                                End If
                            Next
                        Else
                            AddFileOrDir = IsStrMaskEquivalentFileName(MaskStr, FileName)
                        End If
                    Else
                        AddFileOrDir = True
                    End If
                    
                    If AddFileOrDir = True Then
                        Long2Size WFD.nFileSizeLow, WFD.nFileSizeHigh, FileSize ' Вычислить размер файла, с поддержкой файлов > 2 Гб
                        
                        FindFilesAPI = FindFilesAPI + FileSize
                        FileCount = FileCount + 1
                    End If
                End If
                
                ' Добавление строки
                If AddFileOrDir = True Then
                    ReDim Preserve FilesArray(add_cnt)
                    FilesArray(add_cnt).PathDirName = path
                    FilesArray(add_cnt).PathFileOrDirName = FileName
                    
                    If AddDateAndSizeFiles = True Then
                        FilesArray(add_cnt).PathFileSize = FileSize
                        FilesArray(add_cnt).PathDateTime = WFD.ftLastWriteTime
                    End If
                    
                    add_cnt = add_cnt + 1
                End If
            End If
            
            Cont = FindNextFileW(hSearch, WFD)
        Loop
        
        Cont = FindClose(hSearch)
    End If
    
    If nDir > 0 Then
        For i = 0 To nDir - 1
            FindFilesAPI = FindFilesAPI + FindFilesAPI(path & dirNames(i) & "\", FilesArray, MaskStr, AddDateAndSizeFiles, IncludeDirectories, Interrupt, FileCount, DirCount)
        Next i
    End If
End Function
 
Private Sub Long2Size(ByVal LongLow As Long, ByVal LongHigh As Long, ByRef FileSize As Currency)
    '&HFFFFFFFF unsigned = 4294967295
    Dim Cutoff As Currency
    Cutoff = 2147483647
    Cutoff = Cutoff + 2147483647
    Cutoff = Cutoff + 1 ' now we hold the value of 4294967295 and not -1
    FileSize = Cutoff * LongHigh
    If LongLow < 0 Then
        FileSize = FileSize + (Cutoff + (LongLow + 1))
    Else
        FileSize = FileSize + LongLow
    End If
End Sub
1
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
30.09.2023, 08:56
Если быть точнее нужно не возвращать указатели, а убирать лишние ссылки на один и тот же участок памяти. Здесь обсуждалось.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
30.09.2023, 09:13
Цитата Сообщение от testuser2 Посмотреть сообщение
Если быть точнее нужно не возвращать указатели, а убирать лишние ссылки на один и тот же участок памяти.
Да мне если честно всё равно как-то на это, у меня итак всё нормально работает. Когда функция завершается VB сам очищает всё лишнее из памяти, все переменные.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,671
Записей в блоге: 2
30.09.2023, 10:05
Цитата Сообщение от HackerVlad Посмотреть сообщение
у меня итак всё нормально работает
Может быть в vb это менее критично, но Трик, во втором примере возвращает указатели в структуре массивов.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
30.09.2023, 10:12
testuser2, ты с этими указателями не мудри
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.09.2023, 10:12

Создать файл, содержащий имена всех файлов системы, созданных в текущем месяце, имена пользователей, их создавших
Через командную строку необходимо: Создать файл, содержащий имена всех файлов системы, созданных в текущем месяце, имена пользователей,...

Функция поиска файлов, и вывод списка найденных (использую FindFirstFile, FindNextFile)
Друзья, возникла следующая сложность, написал функцию для поиска файлов(.txt) в текущей директории, название файлов нейзвестно, поэтому, с...

GetPixel не корректно определяет цвет
Добрый день! У меня стоит цель определять RGB пикселя в указанной курсором позиции в открытых изображениях. void...

OnEnterCollision не определяет имена и теги
Доброго времени суток, у меня возникла необходимость проверять на столкновения двух объектов, так вот я нашел функцию...

Переименование PDF-файлов в имена, берущиеся из содержимого этих файлов
Всем доброго времени суток!:) Подскажите, пожалуйста, как переименовать файл с расширением pdf, взяв сам текст для наименования файла из...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата) Этот документ предназначен для того, чтобы новый чат Claude мог продолжить работу без необходимости заново разбираться в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru