Нужно посчитать md5 для файлов больше 1 гб. На данный момент всё проиходит через буфер, а это: создать буфер ~ 1 минута, скопировать в буфер 1 минута, посчитать ~40 секунд(это для 1 гб). В итоге видим, что в 3-ри раза больше времени уходит на подготовку файла. Я бы и дальше думал что так и надо, но меня удивляет скорость загрузки HEX редакторов, этот же 1 гб, грузиться мгновенно. Выслушаю все советы, ниже куски моих баго-версий(VS C++, сам алгоритм md5 не вылаживаю, он слишком большой, и его скорость меня устраивает.): Code (Text): int main(int argc, _TCHAR* argv[]) { struct stat st; char* pchGRF; unsigned char md5[0x020]; char* buffer[0x100]; FILE* file; CFile file2; CFileException FileException; //Проверим наличие параметров if(argc<2){ printf("Error! Use: <Path to GRF>\n"); exit(0); } //Сначала подготовим буфер. if(!stat((const char*)argv[1],&st)){ //Если удалось прочитать файл if(pchGRFList=(char*)malloc(st.st_size)) //Создаём буфер для данных printf("Debug: Buffer created. Size: %d Byte.\n",st.st_size); else printf("Error! Buffer not created!\n"); } else printf("Error! Could not find file: '%s'\n",(char*)argv[1]); //v.1 //Теперь грузим. fopen_s(&file, (const char*)argv[2], "wb"); fgets(pchGRFList,st.st_size,file); MD5(pchGRFList,st.st_size,md5); //v.2 //wcListPath = new wchar_t[0x80]; //MultiByteToWideChar(CP_ACP, 0, argv[1], strlen(argv[1])+1, wcListPath, strlen(argv[1])+1); //file2.open(wcListPath,CFile::modeRead,FileException); //file.read(pchGRFList,st.st_size); //MD5(pchGRFList,st.st_size,md5); return 0; }
Грузится только часть, не целиком. Вы создаёте буфер размером более гигабайта? Зачем? Создавайте и читайте к примеру по мегабайту.
Не знаю как перестроить md5 алгоритм под работу с кусками... Возможно ли работать напрямую с файлом, без записи в буфер?
devillsd А чего там переделывать-то? Он же по определению потоковый. Могу показать свой велосипед на C++. Как вы себе это представляете? mmap тоже не лучшее решение в данном случае.
Пока месть, наткнулся на mmap, почему нелогично использовать в моём случае?? На "Велосипед" посмотрю с удовольствием. qwentet@gmail.com / 471-010-9 девять 0.
Чёт не нашел опции - редактировать. Я так понимаю, этот класс работает так, начинаем с какого то буфера, а потом с каждым новым куском дынных производим операцию Update? Потом End, ну и получаем hash... Я всё правильно понял? И ещё , что за компилятор вы используете?
mmap здесь тупо ничего не даст. Ни удобства(из-за интерпретации как памяти), ни скорости(так как скорее всего файл не будет до этого промаплен). Оно может дать только тормоза, из-за большого расхода памяти и свопа. Так что не нужно.
Да, примерно так. Code (Text): MD5 hash; hash.Begin(); hash.Update(...); hash.Update(...); .... hash.End(); hash.GetHash(...); Компилятор gcc, но должно работать на любом.
А ещё добавлю=) Так как имеем потоковый md5, то прекрасно справимся с подзагрузкой в буфер... Спасибо за код, щяз буду тестить. Всё же, какой компилятор используете?
Если Вы ещё здесь, то очень кстати! Теперь имею, очень большую скорость считывания MD5, НОО!! С файлами более 1 GB ( может и на меньших размерах, на файлах около 70 mb всё ОК) трабл, просчитывает неверный Hash. С чем это может быть связано? Code (Text): CFile pFile; CFileException pFileException; //struct stat st; //wchar_t wcFilePath[0x080]; unsigned char* chFileBuff; int cDataSize; MD5 md5calc; char md5[0x010]; unsigned long RoundDataSize=ROUND_DATA_SIZE; //int CurCarret; if(argc<2){ printf("Error! Use: <Path to GRF List> <Path to GRF DB>\n"); exit(0); } //MultiByteToWideChar(CP_ACP, 0, argv[1], strlen(argv[1])+1, wcFilePath, strlen(argv[1])+1); if(!pFile.Open((char*)argv[1], CFile::modeRead, &pFileException)){ switch(pFileException.m_cause){ case 2: printf("Error: File not found!"); break; case 3: printf("Error: Bad path!"); break; default: printf("Error: ?"); break; } exit(0); } //инициализируем алгоритм MD5 md5calc.Begin(); //Создадим буфер if(pFile.GetLength()<ROUND_DATA_SIZE) RoundDataSize = pFile.GetLength(); chFileBuff = (unsigned char*)malloc(RoundDataSize); while(cDataSize=pFile.Read(chFileBuff, RoundDataSize)){ if(cDataSize!=ROUND_DATA_SIZE) printf("Near the end"); md5calc.Update((char*)chFileBuff, cDataSize); } md5calc.End(); md5calc.GetHash(md5); free(chFileBuff); pFile.Close();
У меня всё корректно, тестирую 4Гб файлы. Как проверяете корректность? Бинарный режим открытия файла не забыли? Тестовый код. Code (Text): #include "Md5.hpp" #include <fstream> #include <iostream> char* itoa(int value, char* result, int base); int main (int argc, char* argv[]) { if (argc<2) return 1; char buf[0xffff]; std::ifstream ifs(argv[1], std::ios::binary); if (!ifs.is_open()) return 1; MD5 hash; hash.Begin(); std::streamsize size = 1; while(size) { size = ifs.readsome(buf, sizeof(buf)); hash.Update(buf, size); } hash.End(); char szStr[33]; szStr[32] = 0; for (int i=0; i<16; i++) { szStr[i*2]='0'; szStr[i*2+1]='0'; itoa(hash.GetHash()[i],&szStr[i*2], 16); } std::cout<<szStr<<std::endl; } /** * C++ version 0.4 char* style "itoa": * Written by Lukás Chmela * Released under GPLv3. */ char* itoa(int value, char* result, int base) { // check that the base if valid if (base < 2 || base > 36) { *result = '\0'; return result; } char* ptr = result, *ptr1 = result, tmp_char; int tmp_value; do { tmp_value = value; value /= base; *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; } while ( value ); // Apply negative sign if (tmp_value < 0) *ptr++ = '-'; //*ptr-- = '\0'; --ptr; while(ptr1 < ptr) { tmp_char = *ptr; *ptr--= *ptr1; *ptr1++ = tmp_char; } return result; } В качестве аргумента передаёте имя файла, оно считает и показывает хеш. Для проверки можно использовать md5sum, которая есть и для никсов и для винды.
Там есть ошибка, цикл нужен такой. Code (Text): for (int i=0; i<16; i++) { szStr[i*2]=0; szStr[i*2+1]=0; itoa(hash.GetHash()[i],&szStr[i*2], 16); if (szStr[i*2+1]==0) { szStr[i*2+1] = szStr[i*2]; szStr[i*2] = '0'; } }
Корректность проверяю посредством TotalCommander, в нём есть функция подсчёта md5, действительно не учёл typeBinary, но после исправления ошибки баг не пропал... Попробую применить Ваш код, но бесит, в чём же проблема моего кода?
.redsome отказывается считывать данные из файла! Пытался даже скопировать Ваш не внося изменений, в итоге readsome возвращаёт - 0!