Мапинг или Не Мапинг, как распарсить файл

Тема в разделе "WASM.BEGINNERS", создана пользователем [ixTor], 13 янв 2017.

  1. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    Имеется задача, считывать с файла по одной строке, в некотором государстве посоветовали делать мапинг но я в этом не шарю, кто то может привести пример такого кодеса? Сам ненашел...но нужно обязательно делать это на WinAPI, парсить строку на переходы строк (\r и \n) нехочется но возможно можно както это сделать с мапингом?
     
  2. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    нашел вот такой кодес но он читает посимвольно, а мне нужно всю строку и так одну за другой
    Код (C++):
    1.  
    2. #include <Windows.h>
    3. int main()
    4. {
    5.   HANDLE hFile = CreateFile("test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
    6.   int sizeChars = GetFileSize(hFile, NULL);
    7.   HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    8.   char* lpText = (char*) MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    9.   char* lpCurrent = lpText;
    10.   while(lpCurrent - lpText < sizeChars )
    11.   {
    12.   char* lpLineStart = lpCurrent;
    13.   while (lpCurrent - lpText < sizeChars && *lpCurrent != 0xD) // первое условие увы, необходимо , так как в конце последней строки может не быть CR
    14.        {
    15.          MessageBox(0,lpCurrent, lpCurrent, MB_OK);
    16.         lpCurrent++;
    17.        }
    18.    
    19.   // lpLineStart - начало, (lpCurrent -1) - конец
    20.   // отладочная печать
    21.   //for(char* p = lpLineStart; p < lpCurrent; p++)
    22.   //  putchar(*p);
    23.   //putchar('\n');
    24.   //// конец отладочной печати
    25.   lpCurrent += 2;
    26.   }
    27.   UnmapViewOfFile(lpText);
    28.   CloseHandle(hFileMapping);
    29.   CloseHandle(hFile);
    30.   return 0;
    31. }
    32.  
     
  3. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    помогите плз правильно оформить вот этот кодес из цикла
    Код (C++):
    1.  
    2.       char *test1 = new char[24];
    3.   for(char* p = lpLineStart; p < lpCurrent; p++, test1++)
    4.        { *test1 = *p;}
    5.        MessageBox(0,test1, test1, MB_OK);
    6.   lpCurrent += 2;
    7.  
    надо чтоб каждую строчку вывело месаджбоксом отдельно по очереди
     
  4. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    все разобрался вот кодес патча =))))
    Код (C++):
    1.  
    2.   char* p = lpLineStart;
    3.   for(; p < lpCurrent; p++)
    4.          putchar(*p);
    5.   MessageBox(0,p, p, MB_OK);
    6.   putchar('\n');
    7.  
    вот толкьо чую что гдето там остался (\r).
    что если снести его в 13ой строке добавив *lpCurrent-1 != \r

    PS мои опасения были напрасны , все срезается в цикле
    тему можно закрыть
     
    Последнее редактирование: 13 янв 2017
  5. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    [ixTor]

    Слишком много скрипта. В смысле что текст большой а смысла в нём нет. Проекция файла в память это фундаментальный механизм ос. Тут часто видны примеры, где на каждой итерации в цикле выполняется обращение к файлу. Так делать нельзя, это нубство ибо не профайл. Файл отображается на память и после работы с памятью сохраняется.
     
  6. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    почему не делается, а как делать? я лично к этому кодесу еще кучу всего должен прикрутить, ибо пишу бруНтенг, предлогаешь юзаеть фраемворки?

    по мойму норм, спроецировали в память и с памятью работаем=\
     
  7. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Да, правильно. Только там нужно учитывать что текст может быть без LF или CR, т.е. тестить второй символ за искомым, если там противоположный, его тоже пропускать, конечную строку либо копировать в буфер либо (используя PAGE_WRITECOPY доступ писать \0 прямо в память проекции), если хочешь выводить стандартными WinAPI функциями строку.
    Предложу еще способ это заюзать стандартный FSO и юзать метод ReadLine объекта TextStream.
     
  8. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Код (C++):
    1. #include <atlbase.h>
    2.  
    3. #undef GetFreeSpace
    4.  
    5. #import <scrrun.dll>
    6.  
    7. using namespace Scripting;
    8.  
    9. void startup() {
    10.  
    11.     {
    12.         CComPtr<IFileSystem> pfs;
    13.         CComPtr<ITextStream> pstm;
    14.         _bstr_t bstrLine;
    15.  
    16.         CoInitialize(NULL);
    17.  
    18.         HRESULT hr = pfs.CoCreateInstance(OLESTR("Scripting.FileSystemObject"));
    19.  
    20.         if (SUCCEEDED(hr))
    21.             pstm = pfs->OpenTextFile(bstr_t(L"C:\\Temp\\test.txt"), IOMode::ForReading,
    22.                                     (VARIANT_BOOL) false, TristateUseDefault);
    23.             if (pstm)
    24.                 while (SUCCEEDED(hr = pstm->raw_ReadLine(bstrLine.GetAddress())))
    25.                     MessageBox(NULL, bstrLine.GetBSTR(), NULL, NULL);
    26.    
    27.     }
    28.  
    29.     CoUninitialize();
    30.  
    31.     return;
    32.  
    33. };
     
  9. _edge

    _edge Well-Known Member

    Публикаций:
    1
    Регистрация:
    29 окт 2004
    Сообщения:
    631
    Адрес:
    Russia
    Простите, чем автора топика не устраивают gets() из обычной Си-шки? Оно же все равно всю низкоуровневую подноготную реализует лучше, чем руками изображать-изобретать, разве нет? Разумеется при условнии что файл честно текстовый.
     
  10. comrade

    comrade Константин Ёпрст

    Публикаций:
    0
    Регистрация:
    16 сен 2002
    Сообщения:
    232
    Адрес:
    Russian Federation
    На сколько большой файл? Что потом делается с данными - они читаются, редактируются? Ограничена ли память?

    Много лет назад я писал парсер очень большого текст файла (десятки-сотни тысяч линий), для случайного чтения. Алгоритм был такой: сделать первый пасс по файлу (либо через MMF или просто банальный fread/ReadFile), и записать оффсеты всех линий в массив. Само содержимое линий в память сразу не вчитывалось. Потом, при нужде, линии считывалась используя уже ранее понятные оффсеты. (Длина данной линии это просто разница между следующим и текущим оффсетом).

    Кодом могу поделиться, но он далеко (на старом компе в кладовке - доставать и грузить надо). На FASM'е - но алгоритм я уже описал.
     
    rococo795 нравится это.
  11. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    ребята , решил перенести проект в юникодную версию и столкнулся с траблами, сразу говорю проект написан в Embarcader C++ Berlin и учел то что в настройках проекта надо сделать юникод, вот исходник
    Код (C++):
    1.  
    2. struct FileMapping {
    3.    HANDLE hFile;
    4.    HANDLE hMapping;
    5.    size_t fsize;
    6.    wchar_t* dataPtr;
    7. };
    8. void __fastcall TForm1::Button1Click(TObject *Sender)
    9. {
    10.    HANDLE hHeap = HeapCreate(0,300,0);
    11.  
    12.    HANDLE hFile = CreateFile(L"E:\\strings.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
    13.  
    14.    int sizeChars = GetFileSize(hFile, NULL);
    15.    SECURITY_ATTRIBUTES secAttr;
    16.    secAttr.lpSecurityDescriptor = NULL;
    17.    secAttr.bInheritHandle = FALSE;
    18.    HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);//nullptr
    19.    wchar_t* lpText = NULL;
    20.    lpText = (wchar_t*) MapViewOfFile(hFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, sizeChars);
    21.    BOOL loginOk = NULL;
    22.    if(hHeap!=0 && lpText!=0)
    23.    {
    24.      wchar_t * lpString = NULL;
    25.      lpString=(wchar_t*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,150);
    26.      FileMapping* mapping = (FileMapping*)malloc(sizeof(FileMapping));
    27.      mapping->hFile = hFile;
    28.      mapping->hMapping = hFileMapping;
    29.      mapping->dataPtr = lpText;
    30.      mapping->fsize = (size_t)sizeChars;
    31.      for( ; mapping->dataPtr-2 != NULL ; mapping->dataPtr = mapping->dataPtr+wcslen(lpString)+4)
    32.      {
    33.          lpString = wcstok(mapping->dataPtr,L"\u000D\u000A");
    34.          if(lpString==NULL)break;
    35.          MessgeBox(0, lpString, L"Alert", MB_OK);
    36.      }
    37.      mapping->dataPtr=lpText;
    38.      HeapFree(hHeap, 0, lpString);
    39.      UnmapViewOfFile(mapping->dataPtr);
    40.      CloseHandle(mapping->hMapping);
    41.      CloseHandle(mapping->hFile);
    42.      free(mapping);
    43.    }
    44.    HANDLE hToken = NULL;
    45. }
    46.  
    дело в том что он не ловит строки, пробовал дебагать но не фига не понял в листинге ольки и закрыл с перепуганным лицом...

    собственно выводит одно сообщение хотя в текстовом файле 3 строки, сообщение которое он выводит отображается иероглифами китайскими наверное...где-то я напортачил, помогите пожалуйста. Сразу оговорюсь что файл сохранен в кодировке юникод без БОМ
    вывод в блоке Edit = 瑓楲ㅮ匊牴ਲ呓卲牴ਲ਼ или MessageBox одинаково иероглифы
     
    Последнее редактирование: 28 янв 2017
  12. [ixTor]

    [ixTor] Member

    Публикаций:
    0
    Регистрация:
    5 янв 2017
    Сообщения:
    53
    я таки своего добился выводит нормально но каждый раз перекодировать файл в Notepad++ в кодировку UCS-2 Little Endian както геморойно