Форум программистов, компьютерный форум, киберфорум
bedvit
Войти
Регистрация
Восстановить пароль
Рейтинг: 3.40. Голосов: 5.

Быстрая реализация поиска строк в csv/txt(ANSI) файлах (WinAPI + С++)

Запись от bedvit размещена 06.06.2020 в 23:22
Обновил(-а) bedvit 22.09.2020 в 12:14 (v1.0.2.7)

Реализация для XLL как функция Excel. В планах, реализация в СОМ. Реализовано.
Часть библиотеки BedvitXLL
Особенности реализации:
1.WinAPI: CreateFile + ReadFile
2.Асинхронность в чтения с диска и выполнения рабочего кода.
3.Возможность отключения системного кеширования.
4.Посему чтение блоками, кратно степени двойки - по 16 Мб.(16777216 байт), в большинстве hdd - такого размера свой кеш.
5.Посему адрес принимающего буфера и рабочего выровнен по размеру сектора/страницы - 4096 байт
6.Возможность вывода всех найденных строк или первой найденной (поиск с начала файла)
7.Строка выводится вся, в т.ч. с разделителями.
8.Кодировка csv/txt - ANSI
9.Размер искомой строки и подстроки поиска не может быть больше буфера (16 Мб).
10.Файл может быть любого размера.
11.Поддерживается Стандарт RFC 4180

Функции:
1.GetRowsCountCSVansi(Файл(строка), ОтключениеКешированияФайла(0/1)) - возвращает кол-во строк в файле (учитываются пустые строки, расчет происходит по количеству разделителей строк)
2.GetRowCSVansi(Файл(строка), ПодстрокаДляПоиска(индекс), ОтключениеКешированияФайла(0/1)) - возвращает найденную строку по индексу
3.FindRowsInCSVansi(Файл(строка), ПодстрокаДляПоиска(строка), ВывестиВсеСтроки(0/1), ОтключениеКешированияФайла(0/1)) - возвращает найденную строку/строки по искомой подстроке

Код:
Кликните здесь для просмотра всего текста
C++
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
extern "C" __declspec(dllexport) LPXLOPER12  WINAPI FindRowsInCSVansi(wchar_t *  file, char* findStr, bool multiLine, int fileFlagNoBuffering)
{
    LPXLOPER12 OperOut = TempErr12(xlerrValue);
       
    const DWORD  nNumberOfBytesToRead = 16777216;//67108864;//33554432; //16777216;//8388608;//читаем в буфер байты
    size_t findStrLen = strlen(findStr);
    if (findStrLen >= nNumberOfBytesToRead) { return OperOut; };
 
    // создаем события с автоматическим сбросом
    HANDLE hEndRead = CreateEvent(NULL, FALSE, FALSE, NULL);// дескриптор события
    if (hEndRead == NULL){  return OperOut; }
 
    // открываем файл для чтения
    HANDLE hFile = CreateFile(  // дескриптор файла
        file,   // имя файла
        GENERIC_READ,          // чтение из файла
        FILE_SHARE_READ,       // совместный доступ к файлу
        NULL,                  // защиты нет
        OPEN_EXISTING,         // открываем существующий файл
        FILE_FLAG_OVERLAPPED | (fileFlagNoBuffering != 0 ? FILE_FLAG_NO_BUFFERING : FILE_FLAG_RANDOM_ACCESS),// асинхронный ввод//отключаем системный буфер
        NULL                   // шаблона нет
    );
    // проверяем на успешное открытие
    if (hFile == INVALID_HANDLE_VALUE)
    {
        CloseHandle(hEndRead);
        return OperOut;
    }
 
    char* notAlignBuf = new char[nNumberOfBytesToRead * 2 + 4096 + 1]; //буфер
    char* buf = notAlignBuf + nNumberOfBytesToRead;; //буфер
    if (size_t(buf) % 4096) { buf += 4096 - (size_t(buf) % 4096); }//адрес принимающего буфера тоже должен быть выровнен по размеру сектора/страницы 
 
    char* notAlignBufWork = new char[nNumberOfBytesToRead * 2 + 4096 + 1]; //буфер Рабочий
    char* bufWork = notAlignBufWork + nNumberOfBytesToRead; //буфер
    if (size_t(bufWork) % 4096) { bufWork += 4096 - (size_t(bufWork) % 4096); }//адрес рабочего буфера тоже выровнял по размеру сектора/страницы  
 
    buf[nNumberOfBytesToRead] = '\0';//добавим нуль-терминатор
    bufWork[0] = '\0';//добавим нуль-терминатор
    bufWork[nNumberOfBytesToRead] = '\0';//добавим нуль-терминатор
 
    DWORD dwBytesReadWork = 0;
    DWORD findStatus = 0; //статус поиска
    bool errHandleEOF = false; //метка конца файла
    char* find;// указатель для поиска
    char* strStart;
    char* strEnd;
    char* bufWorkNew = bufWork;//буфер с учетом полной строки
    size_t strStartLen = 0;
    size_t strCount = 1; //счетчик строк
    std::string strOut; //итоговая строка
 
    _ULARGE_INTEGER ui; //Представляет 64-разрядное целое число без знака обединяя два 32-х разрядных
    ui.QuadPart = 0;
 
    OVERLAPPED  ovl;   // структура управления асинхронным доступом к файлу// инициализируем структуру OVERLAPPED
    ovl.Offset = 0;         // младшая часть смещения равна 0
    ovl.OffsetHigh = 0;      // старшая часть смещения равна 0
    ovl.hEvent = hEndRead;   // событие для оповещения завершения чтения
 
    // читаем данные из файла
    for (;;)
    {
        DWORD  dwBytesRead;
        DWORD  dwError;
        find = buf; //буфер
        // читаем одну запись
        if (!ReadFile(
            hFile,           // дескриптор файла
            buf,             // адрес буфера, куда читаем данные
            nNumberOfBytesToRead,// количество читаемых байтов
            &dwBytesRead,    // количество прочитанных байтов
            &ovl             // чтение асинхронное
        ))
        {
            switch (dwError = GetLastError())// решаем что делать с кодом ошибки
            {
                //эти ошибки смотрм после завершения асинхронной операции чтения, для возможности обработать рабочий буфер
            case ERROR_IO_PENDING: { break; }        // асинхронный ввод-вывод все еще происходит // сделаем кое-что пока он идет 
            case ERROR_HANDLE_EOF: { errHandleEOF = true;   break; } // мы достигли конца файла читалкой ReadFile
            default: {goto return1; }// другие ошибки
            }
        }
 
        //работаем асинхронно, выполняем код, пока ждем чтение с диска//
        bufWork[dwBytesReadWork] = '\0';//добавим нуль-терминатор
    goNextFind:
        if (findStatus == 0)//goFind
        {
            find = strstr(bufWorkNew, findStr);
            if (find != NULL) //если нужная подстрока найдена
            {
                for (strStart = find; strStart >= bufWorkNew; strStart--)
                {
                    if (*strStart == '\n') { break; } //если нашли начало строки
                }
                strStart++; //не учитываем '\n'
 
                strEnd = strchr(find, '\n'); //ищем конец строки
                if (strEnd != NULL) //если нашли конец строки
                {
                    strOut = strOut + std::string(strStart, strEnd - strStart + 1);
                    if (!multiLine)
                    {
                        goto return0;
                    }
                    else//поиск в следующей строке начинаем с конца предыдущей
                    {
                        bufWorkNew = strEnd++;
                        findStatus = 0;
                        goto goNextFind;
                    }
                }
                else//если конец строки в следующем буфере или конец файла
                {
                    strOut = strOut + std::string(strStart);
                    findStatus = 1;
                }
            } //если нужная подстрока найдена
        }
        else if (findStatus == 1)//goBuf
        {
            strEnd = strchr(bufWork, '\n');
            if (strEnd != NULL) //если нашли конец строки
            {
                strOut = strOut + std::string(bufWork, strEnd - bufWork + 1);
                findStatus = 0;
                if (!multiLine)
                {
                    goto return0;
                }
                else//поиск в следующей строке начинаем с конца предыдущей
                {
                    bufWorkNew = strEnd++;
                    findStatus = 0;
                    goto goNextFind;
                }
            }
            else//если конец строки в следующем буфере или конец файла
            {
                strOut = strOut + std::string(bufWork);
            }
        }
 
        //блок дозагрузки рабочего буфера межбуферной строкой
        char* bufWorkEnd = bufWork + dwBytesReadWork; //конец буфера
        for (strStart = bufWorkEnd; strStart >= bufWork; strStart--) { if (*strStart == '\n') { break; } } //если нашли начало строки
        if (strStart < bufWork && ui.QuadPart >= nNumberOfBytesToRead) { goto return1; }; //если строка больше буфера (не найден разделитель), кроме первого буфера
        strStartLen = (bufWorkEnd - ++strStart); //размер буфера, который добавляем к рабочему
        //пишем начало строки в новый буфер
        bufWorkNew = buf - strStartLen;//bufWorkNew = bufWork - strStartLen;
        memcpy(bufWorkNew, strStart, strStartLen);
        //
 
        if (errHandleEOF) { goto return0; }
        //работаем асинхронно, выполняем код, пока ждем чтение с диска//
 
        // ждем, пока завершится асинхронная операция чтения
        WaitForSingleObject(hEndRead, INFINITE);
 
        // проверим результат работы асинхронного чтения // если возникла проблема ... 
        if (!GetOverlappedResult(hFile, &ovl, &dwBytesRead, FALSE))
        {
            switch (dwError = GetLastError())// решаем что делать с кодом ошибки
            {
            case ERROR_HANDLE_EOF: { goto return0; break; }//если конец файла. но мы должны вернутся найти начало строки.
            // мы достигли конца файла в ходе асинхронной операции
            default: {goto return1; }// другие ошибки
            }// конец процедуры switch (dwError = GetLastError())
        }
 
        //меняем буфер
        char* bufTmp = bufWork;
        bufWork = buf;
        buf = bufTmp;
        //
 
        // увеличиваем смещение в файле
        dwBytesReadWork = dwBytesRead;//кол-во считанных байт
        ui.QuadPart += nNumberOfBytesToRead; //добавляем смещение к указателю на файл
        ovl.Offset = ui.LowPart;// вносим смещение в младшее слово
        ovl.OffsetHigh = ui.HighPart;// вносим смещение в старшеее слово
    }
 
return0:
    // закрываем дескрипторы, освобождаем память
    CloseHandle(hFile);
    CloseHandle(hEndRead);
    delete[] notAlignBuf;
    delete[] notAlignBufWork;
 
    OperOut->xltype = xltypeStr | xlbitDLLFree;
    if (strOut.length() > 32767)
    {
        OperOut->val.str = new XCHAR[24 + 2]; //+1 под размер + 1 под нуль-терминатор
        wcscpy(OperOut->val.str + 1, L"Overflow. Max char 32767\0");
        OperOut->val.str[0] = 24;
    }
    else
    {
        OperOut->val.str = new XCHAR[strOut.length() + 2]; //+1 под размер + 1 под нуль-терминатор
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strOut.c_str(), -1, OperOut->val.str + 1, strOut.length() + 1);
        OperOut->val.str[0] = strOut.length();
    }
    return OperOut;
 
return1:
    CloseHandle(hFile);
    CloseHandle(hEndRead);
    delete[] notAlignBuf;
    delete[] notAlignBufWork;
    return OperOut;
}

Наблюдения:
1.Если рабочий файл не влезает в системный кеш, отключение кеширования положительно влияет на тайминг, если влезает кеширование серьезно ускоряет процесс (т.е. кеширование не отключаем на малых, отключаем на больших файлах).
2.При документированной скорости чтения SSD - 450 Мб/с, 10 ГБ читается за 22,2 сек, что близко к скорости поиска (25,45 сек. с отключенным кешированием - 40 млн.строк, ищем последнюю).

Запуск из VBA
Visual Basic
1
2
3
Sub Test()
[a2] = Application.Run("FindRowsInCSVansi", "C:\CSV_10_GB.csv", "40000000", 1, 0) 'file 10Gb
End Sub

UPD 03/07/2020 v1.0.2.7
Реализация в СОМ:

[id(10), helpstring("Get Rows Count in CSV-file encoded ANSI")] HRESULT GetRowsCountCSVansi([in] BSTR FileIn, [in, defaultvalue(0)] LONG FileFlagNoBuffering, [out, retval] LONG* RowsCountOut);

[id(11), helpstring("Get Row by index in CSV-file encoded ANSI")] HRESULT GetRowCSVansi([in] BSTR FileIn, [in] LONG IndexString, [in, defaultvalue(0)] LONG FileFlagNoBuffering, [out, retval] BSTR* StringOut);

[id(12), helpstring("Find Rows/String by substring in CSV-file encoded ANSI")] HRESULT FindRowsInCSVansi([in] BSTR FileIn, [in] BSTR FindString, [in, defaultvalue(0)] LONG MultiLine, [in, defaultvalue(0)] LONG FileFlagNoBuffering, [out, retval] BSTR* StringOut);


Запуск из VBA
Visual Basic
1
2
3
Sub Test()
[a2] = CreateObject("BedvitCOM.VBA").FindRowsInCSVansi("C:\CSV_1_GB.csv", "4000000", 0, 0) 'file 1Gb
End Sub
Последние версии библиотек.
Миниатюры
Нажмите на изображение для увеличения
Название: FindRowsInCSVansi.PNG
Просмотров: 683
Размер:	24.2 Кб
ID:	6293  
Размещено в Без категории
Показов 6292 Комментарии 37
Всего комментариев 37
Комментарии
  1. Старый комментарий
    Аватар для Avazart
    Это не С++ это Си ...
    Ну или отличный пример С++гавнокода.
    (простыни, goto, магические числа).

    Попробуйте переписать код с использованием std::unique_ptr<> для хендлов, возможно получиться лучше.
    Запись от Avazart размещена 07.06.2020 в 00:08 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 11:28
  2. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    Это не С++ это Си ...
    Ну или отличный пример С++гавнокода.
    Да, в основном это Си, здесь мне так и посоветовали. У вас другая точка зрения, обоснуйте. Можете привести свой пример, который будет эффективнее.
    Запись от bedvit размещена 07.06.2020 в 12:58 bedvit вне форума
  3. Старый комментарий
    Аватар для Avazart
    Цитата:
    Да, в основном это Си,
    В основном это гавнокод.

    1. Не важно Си или С++ - функция неоправданно объемная как в длину так и в ширину т.е. простыня. Так пишут студенты не научившиеся разбивать код на -функции и модули (в С, а в С++ еще и классы)

    2. В коде есть магические числа, что такое в коде 4096 ? Почему не 666 ?
    Почему некоторые переменные названы капсом? Капс - для макросов.

    3. В С++ есть классы и исключения (и есть break и continue) что позволяет писать лаконичнее и избегать goto

    4. И я же посоветовал. Вы про идиому RAII слышали? Ну и где оно?
    Запись от Avazart размещена 07.06.2020 в 14:01 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 14:11
  4. Старый комментарий
    Аватар для Avazart
    Что мешало вместо
    C++
    1
    
    char* notAlignBuf = new char[nNumberOfBytesToRead + 4096]; //буфер
    Использовать std::string или std::vector<char> ?

    Цитата:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    
     // проверяем на успешное открытие
       if (hFile == INVALID_HANDLE_VALUE)
        {
            CloseHandle(hEndRead);
            delete[] notAlignBuf;
            delete[] notAlignBufBufWork;
            return OperOut;
        }
    А ошибку вывести пользователю? Причину пользователь должен как то узнать почему файл не открыт.
    Запись от Avazart размещена 07.06.2020 в 14:15 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 14:18
  5. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    В основном это гавнокод.
    Спасибо за вашу оценку, благодаря вам мы становимся лучше.

    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    1. Не важно Си или С++ - функция неоправданно объемная как в длину так и в ширину т.е. простыня. Так пишут студенты не научившиеся разбивать код на -функции и модули (в С, а в С++ еще и классы)
    не вижу целесообразности что-то выделять в класс.

    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    2. В коде есть магические числа, что такое в коде 4096 ? Почему не 666 ?
    Почему некоторые переменные названы капсом? Капс - для макросов.
    Если бы вы прочитали инфо, по ссылке мной ранее высланной, у вас бы не было этого вопроса. Эти магические числа хочет CreateFile+FILE_FLAG_NO_BUFFERING, вопрос не ко мне. Капсом - это тоже не ко мне, а к microsoft. У меня нет таких переменных.

    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    3. В С++ есть классы и исключения (и есть break и continue) что позволяет писать лаконичнее и избегать goto
    Если вы думаете, что я не знал про это, увы знаю. У меня так получилось лаконичнее, есть предложения - вносите, пример перед перед вами в теме.

    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    4. И я же посоветовал. Вы про идиому RAII слышали? Ну и где оно?
    Мне нужно была простая и быстрая реализация. Не вижу зачем здесь идиома RAII и умные указатели.
    Запись от bedvit размещена 07.06.2020 в 15:40 bedvit вне форума
  6. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    Что мешало вместо
    C++
    1
    
    char* notAlignBuf = new char[nNumberOfBytesToRead + 4096]; //буфер
    Использовать std::string или std::vector<char> ?
    Опять же, если вы посмотрите тему по ссылке выше - там будет реализация на std::string - это медленно.

    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    А ошибку вывести пользователю? Причину пользователь должен как то узнать почему файл не открыт.
    Верно, поэтому там ошибка и выводится.
    строка кода 3-5:
    C++
    1
    2
    3
    
    LPXLOPER12 OperOut = new XLOPER12;
        OperOut->xltype = xltypeErr;
        OperOut->val.err = xlerrValue;
    Запись от bedvit размещена 07.06.2020 в 15:45 bedvit вне форума
  7. Старый комментарий
    Аватар для Avazart
    Цитата:
    не вижу целесообразности что-то выделять в класс.
    В этом и проблема.
    Цитата:
    Если бы вы прочитали инфо, по ссылке мной ранее высланной, у вас бы не было этого вопроса. Эти магические числа хочет CreateFile+FILE_FLAG_NO_BUFFER ING, вопрос не ко мне. Капсом - это тоже не ко мне, а к microsoft. У меня нет таких переменных.
    Никто не хочет магические числа, они может и таинственные, но не сексуальные.
    Я шучу по тому что это явный зашквар и я не понимаю как реагировать если человек не понимает что магические числа это плохо.

    Строка #23
    C++
    1
    
    bool ERR_HANDLE_EOF = false; //метка конца файла
    А это что? Пришел Майкрософт и нагадил Вам в код? Носом его носом ... кто это сделал ? Фу...


    Цитата:
    Опять же, если вы посмотрите тему по ссылке выше - там будет реализация на std::string - это медленно.
    Глупости.
    Цитата:
    Вы не любите кошек? Вы просто не умеете их готовить.
    Запись от Avazart размещена 07.06.2020 в 15:52 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 16:30
  8. Старый комментарий
    Аватар для bedvit
    Так покажите, как надо.
    Запись от bedvit размещена 07.06.2020 в 16:00 bedvit вне форума
  9. Старый комментарий
    Аватар для Алексей1153
    bedvit, а для чего тут асинхронное чтение? Вроде нет другого потока, нет петли обработки сообщений. Функция линейная
    Или я что-то не увидел?

    std::string, std::ifstream - портянка сократится в несколько раз

    Цитата:
    std::string - это медленно
    std::string - практически ничем не отличается от динамического массива char. Скорость работы будет такая же
    Запись от Алексей1153 размещена 07.06.2020 в 16:04 Алексей1153 вне форума
  10. Старый комментарий
    Аватар для Алексей1153
    а если уж WinAPI, то проще создать проекцию файла CreateFileMapping/MapViewOfFile и найти строку std::search
    Запись от Алексей1153 размещена 07.06.2020 в 16:11 Алексей1153 вне форума
    Обновил(-а) Алексей1153 07.06.2020 в 16:14
  11. Старый комментарий
    Аватар для Avazart
    Цитата:
    Так покажите, как надо
    Что показать? Как на гуглить перечисленное по пунктам? Или как скачать книгу по STL ?

    Цитата:
    Мне нужно была простая и быстрая реализация. Не вижу зачем здесь идиома RAII и умные указатели.
    Нужно была простая а получили трешовую.
    Был бы "RAII и умные указатели" код был бы проще. А так получили теш из goto и копипасты.

    Цитата:
    Верно, поэтому там ошибка и выводится.
    А вот и нет вернитесь и увидите что там не вызывается GetLastError() соответственно возвращается непонятно что, но только не ошибка. Сложность кода спагетти в том что тяжело найти такую логическую ошибку.

    Цитата:
    а если уж WinAPI, то проще создать проекцию файла CreateFileMapping/OpenFileMapping и найти строку std::search
    Mapping File мне тоже пришли в голову при чтении его темы, но тут не все так просто стоит почитать Рихтера.
    Да и просто std::search не подходит нужно на его основе чет построить что бы "детектить" частичное совпадение и докачивать след. кусок файла.

    Цитата:
    bedvit, а для чего тут асинхронное чтение? Вроде нет другого потока, нет петли обработки сообщений.
    Там перекрываемые (overlapped) операции для них не нужна обработка сообщение. Т.е. ф-ции просто не блокирующие.
    Запись от Avazart размещена 07.06.2020 в 16:14 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 16:33
  12. Старый комментарий
    Аватар для Avazart
    ...
    Запись от Avazart размещена 07.06.2020 в 16:18 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 16:33
  13. Старый комментарий
    Аватар для bedvit
    Коллеги, прошу прочитать тему, https://www.cyberforum.ru/blog... g6617.html
    тогда и вопросы можно обсудить. Сейчас как-то в молоко, извините.
    Алексей1153, асинхронность есть, смотрите внимательнее. Про MMF, вот цитата из той же темы, и мне она представляется верной.
    Цитата:
    Сообщение от VTsaregorodtsev Посмотреть сообщение
    Ибо при MMF сразу всего гигового файла - будет page fault на каждой новой 4кб-странице памяти. Т.к. замапленная память выделяется сначала виртуально - и лишь при состоявшемся обращении она будет сопоставляться со страницей реальной физической памяти и в неё будет грузиться содержимое куска файла. Т.е. MMF здесь к чтению данных добавляет кучу сработок процессорного/системного обработчика исключений.
    А если мапить кусками - к чтению данных (невидимому нам при MMF) добавляются регулярные вызовы MapViewOfFile/UnmapViewOfFile на каждом таком куске. Т.е. затраты на передачу аргументов, на вызовы функций, затем на проверку аргументов в них, на выполнение нужной логики. Ну и нафиг оно - всё это лишнее, когда можно обойтись просто одним вызовом обычной читалки ReadFile()?
    Если не согласны, можем сравнить скорости. С вас MMF-реализация.
    Запись от bedvit размещена 07.06.2020 в 16:29 bedvit вне форума
  14. Старый комментарий
    Аватар для XLAT
    Цитата:
    Опять же, если вы посмотрите тему по ссылке выше - там будет реализация на std::string - это медленно.
    так как я в прошлом тоже ассемблердрочер, то вопрос эффективности у меня не на последнем месте,
    то решил проверить ваше утверждение на вашем же тесте:
    https://www.cyberforum.ru/cpp-... st14628185
    Запись от XLAT размещена 07.06.2020 в 17:10 XLAT вне форума
  15. Старый комментарий
    Аватар для Avazart
    Цитата:
    Сообщение от bedvit Просмотреть комментарий
    Так покажите, как надо.
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    #include <memory>
    #include <Windows.h>
     
    int main()
    { 
      std::unique_ptr<void, decltype(&CloseHandle)>
         event(CreateEvent(NULL, FALSE, FALSE, NULL),&CloseHandle);
     
      return 0;
    }

    https://ru. stackoverflow.com/questions/423359/Как-использовать-unique-ptr-для-хендлов

    Вместо Си-строк - контейнеры и код вида:

    C++
    1
    2
    3
    4
    5
    6
    7
    
    if (hFile == INVALID_HANDLE_VALUE)
        {
            CloseHandle(hEndRead);
            delete[] notAlignBuf;
            delete[] notAlignBufBufWork;
            return OperOut;
        }
    не нужно копипастить при каждой обработке ошибок и goto не нужен.

    Кстати
    C++
    1
    
    LPXLOPER12 OperOut = new XLOPER12;
    Не удаляется создавая утечку?
    Запись от Avazart размещена 07.06.2020 в 18:04 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 18:46
  16. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    Кстати
    C++
    1
    
    LPXLOPER12 OperOut = new XLOPER12;
    Не удаляется создавая утечку?
    нет, строка 214
    C
    1
    
    OperOut->xltype = xltypeStr | xlbitDLLFree;
    все зачистит.
    Запись от bedvit размещена 07.06.2020 в 19:36 bedvit вне форума
  17. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от XLAT Просмотреть комментарий
    так как я в прошлом тоже ассемблердрочер, то вопрос эффективности у меня не на последнем месте,
    то решил проверить ваше утверждение на вашем же тесте:
    https://www.cyberforum.ru/cpp-... st14628185
    fgets() - тоже медленно, я вам ответил.
    Запись от bedvit размещена 07.06.2020 в 19:38 bedvit вне форума
  18. Старый комментарий
    Аватар для bedvit
    XLAT, моя реализация быстрее вашей на std::string - в 8 раз. В теме тест.
    Запись от bedvit размещена 07.06.2020 в 19:58 bedvit вне форума
  19. Старый комментарий
    Аватар для Avazart
    Цитата:
    Сообщение от bedvit Просмотреть комментарий
    нет, строка 214
    C
    1
    
    OperOut->xltype = xltypeStr | xlbitDLLFree;
    все зачистит.
    Так есть куча случаев где это строчка не выполняется.
    Например если прыжок по return1: или еще раньше файл не открылся.
    Или я ошибаюсь?
    Запись от Avazart размещена 07.06.2020 в 20:26 Avazart вне форума
    Обновил(-а) Avazart 07.06.2020 в 20:27
  20. Старый комментарий
    Аватар для bedvit
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    Или я ошибаюсь?
    Замечание дельное.
    4я строка кода
    C++
    1
    
    OperOut->xltype = xltypeErr;
    превращается в
    C++
    1
    
    OperOut->xltype = xltypeErr | xlbitDLLFree;
    std::unique_ptr штука удобная, но goto все равно нужен, т.к. разный возвращаемый результат.
    Запись от bedvit размещена 07.06.2020 в 23:25 bedvit вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru