Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > SetFilePointer


Автор: En_t_end 15.12.2005, 15:51
Как я понял, с помошью SetFilePointer можно устанавливать байтовое смещение от определенной точки.
То есть могу ли я делать так:
SetFilePointer(hFile, BytesRealReaded-BytesReaded+1, NULL, FILE_BEGIN);
где BytesRealReaded - есть некая локальная для функция DWORD переменная отвечающая за хранение общего кол-ва прочитанных байт, а BytesReaded - есть локальная для модуля этой функции переменная DWORD отвечающая за хранение байтов прочитанных в последний раз.
Почему-то она неправильно позиционирует указатель, просто дико перемещая его smile

Автор: _hunter 15.12.2005, 16:09
должно работать...
может у тебя BytesRealReaded-BytesReaded в отрицательные числа уходит?
что происходит если туда готовые числа подставлять?

Автор: En_t_end 15.12.2005, 16:12
_hunter
Вот смотри:
Код

BOOL SearchText(LPCTSTR lpszFileName,   LPCTSTR Text, 
                LPDWORD ByteBegConcMas, LPDWORD CountMas)
{
    HANDLE hFile = CreateFile(lpszFileName, GENERIC_READ, 
        FILE_SHARE_READ, NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        lstrcpy(LastErr, "Can't open file!");
        return FALSE;
    }
    DWORD FileSize = GetFileSize(hFile, NULL);
    char *buffer = new char[lstrlen(Text)+1];
    DWORD BytesReaded = 0;
    DWORD BytesRealReaded = 0;
    while(BytesRealReaded+lstrlen(Text) <= FileSize)
    {
        lstrcpy(buffer, "");
    ReadFile(hFile, buffer, 1, &BytesReaded, NULL);
    BytesRealReaded += BytesReaded;
    if(buffer[0] == Text[0])
    {
        lstrcpy(buffer, "");
        SetFilePointer(hFile, BytesRealReaded-BytesReaded, NULL, FILE_BEGIN);
        BytesReaded = 0;
        ReadFile(hFile, buffer, lstrlen(Text), &BytesReaded, NULL);
        buffer[BytesReaded] = '\0';
        if(CompareStr(buffer, Text))
        {
            ByteBegConcMas[(*CountMas)++] = BytesRealReaded;
            BytesRealReaded += BytesReaded;
        }
        else SetFilePointer(hFile, BytesRealReaded-BytesReaded+1, NULL, FILE_BEGIN);
        MessageBox(NULL, buffer, "ST.DLL:", 0);
    }
    }
//    char buf2[20];    
//    MessageBox(NULL, itoa(*CountMas, buf2, 10), "ST.DLL:", 0);
    CloseHandle(hFile);
    delete[] buffer;
    if(*CountMas == 0) return FALSE;
    return TRUE;
}

Автор: En_t_end 15.12.2005, 16:42
За тупость реализации просьба не пинать...

Автор: Aleksandor 15.12.2005, 16:42
А ReadFile сам "file pointer" переставляет smile Так что когда читаем с начала то нет смысла его переставлять.
SetFilePointer обычно нужен только если надо прочитать с конца файла
Код

SetFilePointer(hFile,dwFileLength-175,NULL,FILE_BEGIN);
ReadFile(hFile,ReadBuff+dwFileLength-175,175,&cb,NULL);
........
........
SetFilePointer(hFileOpen,0,NULL,FILE_BEGIN); // теперь в начало

Автор: _hunter 15.12.2005, 16:59
кстати да.
т.е. ( если я правильно понял алгоритм ) достаточно будет SetFilePointer(hFile, -BytesReaded, NULL, FILE_CURRENT); сделать

P.S.
сорри что долго -- отойти нужно было...

Автор: En_t_end 15.12.2005, 19:31
Цитата(_hunter @ 15.12.2005, 20:59)
т.е. ( если я правильно понял алгоритм )

Совершенно верно, первый вариант как раз таким был, но почему-то он не прошел стресс тест - вылетал екзешен.

Автор: _hunter 15.12.2005, 19:44
именно на этой строке летит?

Автор: En_t_end 16.12.2005, 15:07
_hunter
Не сразу, но летит именно на ней.
Методом научного тыка пришел к такому варианту:
Код

BOOL SearchText(LPCTSTR lpszFileName,   LPCTSTR Text, 
                LPDWORD ByteBegConcMas, LPDWORD CountMas)
{
    HANDLE hFile = CreateFile(lpszFileName, GENERIC_READ, 
        FILE_SHARE_READ, NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        lstrcpy(LastErr, "Can't open file!");
        return FALSE;
    }
    DWORD FileSize = GetFileSize(hFile, NULL);
    char first;
    char *buffer = new char[lstrlen(Text)+1];
    DWORD BytesRealReaded = 0;
    while(BytesRealReaded+lstrlen(Text) <= FileSize+1)
    {
            DWORD BytesReaded = 0;
    ReadFile(hFile, &first, 1, &BytesReaded, NULL);
    BytesRealReaded += BytesReaded;
    if(first == Text[0] || *CharLower(&first) == Text[0] || *CharUpper(&first) == Text[0])
    {
        lstrcpy(buffer, "");
        BytesReaded = 0;
        buffer[0] = first;
        ReadFile(hFile, buffer+1, lstrlen(Text), &BytesReaded, NULL);
        buffer[BytesReaded] = '\0';
        if(CompareStr(buffer, Text))
        {
            ByteBegConcMas[(*CountMas)++] = BytesRealReaded;
            BytesRealReaded += BytesReaded;
        }
        else SetFilePointer(hFile, -BytesReaded, NULL, FILE_BEGIN);
    }
    MessageBox(NULL, buffer, "ST.DLL:", 0);
    }
    char buf2[20];    
    MessageBox(NULL, itoa(*CountMas, buf2, 10), "ST.DLL:", 0);
    CloseHandle(hFile);
    delete[] buffer;
    if(*CountMas == 0) return FALSE;
    return TRUE;
}

Теперь вот думаю, почему в таком файле не может найти строку the
файл.txt:
the

Автор: _hunter 16.12.2005, 15:37
а почему ты при совпадении строк ( if(CompareStr(buffer, Text)) )
указатель назад смещаеш? по-идее наоборот нужно
+ SetFilePointer(hFile, -BytesReaded+1, NULL, FILE_BEGIN); по-идее смещать нужно ( а то на то же место вернемся )

Автор: En_t_end 16.12.2005, 15:45
_hunter

Цитата(En_t_end @ 16.12.2005, 19:07)
else SetFilePointer(hFile, -BytesReaded, NULL, FILE_BEGIN);

Там else стоит smile
Моя логика такова: Если нашли подходящую строку, то нафига нам смещать назад указатель ? нам уже пофигу , мы знаем, что позади точно нет неучтенной строки нашего типа(ибо размер мы знаем, он константый, по крайней мере локально)
А если же строка оказалась галиматьей, то надо сместиться назад от прочтенной строки, оказвшись тем самым на месте BytesRealReaded = BytesRealReaded-BytesReaded+1.

Автор: JoyEx 16.12.2005, 16:21
En_t_end
ReadFile/WriteFile изменяют файловый указатель и поэтому лучше перед их вызовом позиционировать его с помощью SetFilePointer.

Чтобы не вылетать на
Код

ByteBegConcMas[(*CountMas)++]

надо передавать в ф-цию размер массива и проверять прежде, чем туда что-то писАть. Зачем читать из файла по 1 байту? Так долго, лучше сразу читать не менее lstrlen(Text) байт и потом не забывать делать Си строку ( + 0 ).

Автор: _hunter 16.12.2005, 16:21
так при равенстве строк CompareStr ноль отдаст и соответственно произойдет переход на else SetFilePointer(hFile, -BytesReaded, NULL, FILE_BEGIN)...
+ ты ситуацию с -1 не учитываеш...

Автор: En_t_end 16.12.2005, 17:28
JoyEx
Цитата(JoyEx @ 16.12.2005, 20:21)
надо передавать в ф-цию размер массива и проверять прежде, чем туда что-то писАть.

Дело не в этом, это я учел. Я же показываю лишь тестовую версию, в ней меня не интересует выход за границы, ибо массив передаваемый в моем случае в тестовом коде имеет размер не ниже предполагаемому кол-ву совпадений в файле( я его сам создаю). Я же ведь только тестирую... Естественно я ни в коем случае не возражаю против проверки на выход за пределы выделенной памяти массива smile

Цитата(_hunter @ 16.12.2005, 20:21)
так при равенстве строк CompareStr ноль отдаст и соответственно произойдет переход на else SetFilePointer(hFile, -BytesReaded, NULL, FILE_BEGIN)...
+ ты ситуацию с -1 не учитываеш...

CompareStr - это моя функция smile
Нужна для экспериментов с lstrcmpi stricmp strcmp
Код

BOOL CompareStr(LPCTSTR Str1, LPCTSTR Str2)
{
    if(lstrcmp(Str1, Str2) == 0) return TRUE;
    return FALSE;
}

Сделанна именно так, чтобы не заморачиваться...
Цитата(JoyEx @ 16.12.2005, 20:21)
ReadFile/WriteFile изменяют файловый указатель и поэтому лучше перед их вызовом позиционировать его с помощью SetFilePointer.

Что я и делаю....
Добавлено @ 17:35
JoyEx
Цитата(JoyEx @ 16.12.2005, 20:21)
Так долго, лучше сразу читать не менее lstrlen(Text)

Было бы все так легко smile
файл.txt:
БлtheБtheБлаБлаthe

Таким образом в первый раз прочитается Блt, что не есть гуд smile

Автор: _hunter 16.12.2005, 17:36
Цитата(En_t_end @ 16.12.2005, 16:28)
CompareStr - это моя функция smile

ааа... ясно.
просто такая же функция в SysUtils есть. я и подумал что это она...

Автор: En_t_end 16.12.2005, 17:37
_hunter
Цитата(_hunter @ 16.12.2005, 21:36)
просто такая же функция в SysUtils есть. я и подумал что это она...

ЗЫ я борландом не пользуюсь smile
Добавлено @ 17:39
Эгхм... все таки вопрос остается открытым, почему и что я делаю не правильно, единственное на что я пока могу грешить, так это на SetFilePointer , поэтому и создал эту тему. Прошу откликнуться...

Автор: Fixin 16.12.2005, 20:17
Ошибка вышла.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)