Файл - чтение по строкам

Тема в разделе "WASM.BEGINNERS", создана пользователем Qasm, 9 янв 2008.

  1. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Вопрос легкий, на 5 минут, но я новичок. Как читать файл, чтоб по строкам было, как readln например? Заранее благодарен
     
  2. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Если речь идет про С, то ф-ии gets/fgets должны помочь. Если про ассемблер, то можно вызвать эти же ф-ии, либо написать их самому.

    В общем, телепатируйте язык, ОС.

    P.S. Чую, тема для студенческого раздела.
     
  3. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    На ассемблере мучаюсь, не додумаюсь. lodsw тут не нужен случаем? чтоб сравнивать с 0D0Ah?
     
  4. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Можно с lodsw и проверить ax на значение. Можно с помощью 'scasw', поместив перед этим в значение в ax.
     
  5. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Еще не помешает учесть, что в *nix другой формат текстовых файлов.
     
  6. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Не получается. Приведите пример использования, пожалуйста..
     
  7. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Вот, пытаюсь хотя бы первую строку получить.

    Код (Text):
    1.     invoke      lstrlen,pMapFile
    2.     mov     ecx,eax
    3.    
    4.     cld
    5.     mov     eax,0D0Ah
    6.     lea     edi,pMapFile
    7.     repne       scasw
    8.     jnz     k20
    9.     mov     eax,edi
    10.  
    11.     invoke      lstrcpyn,addr szBuffer512_2,pMapFile,eax
    12.     invoke      MessageBox,hwnd_dlg_Main,addr szBuffer512_2,0,0
    13. k20:
    Вроде все так же, как и у Абеля:
    Код (Text):
    1.                STRLEN    EQU  15             ;Длина поля STRING
    2.                STRING    DB   'The time&is now'
    3.                          ...
    4.                          CLD
    5.                          MOV  AL,'&'         ;Искомый символ
    6.                          MOV  CX,STRLEN      ;Длина поля STRING
    7.                          LEA  DI,STRING      ;Адрес поля STRING
    8.                          REPNE SCASB         ;Сканировать
    9.                          JNZ  K20            ;Символ найден?
    10.                          DEC  DI             ;Да - уменьшить адрес
    11.                          MOV  BYTE PTR[DI],20H  ;Подставить пробел
    12.                K20:      RET
    Запускаю, открываю файл, выполняется тот самый код и судя по тому, что никакого сообщения нет, выходит на k20
     
  8. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    ошибка. последний параметр - длина строки, а не указатель на конец строки
     
  9. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Аа.. понятно. Исправил. Но в этом месте
    Код (Text):
    1.     repne       scasw
    2.     jnz         k20
    он почему то вылетает на k20. Правильно ли то, что до этого?
     
  10. Vov4ick

    Vov4ick Владимир

    Публикаций:
    0
    Регистрация:
    8 окт 2006
    Сообщения:
    581
    Адрес:
    МО
    Сишник читает из файла побайтово, сваливая таким образом всю буферизацию на ОС. Советую поступить также, т.к. скорость не нужна, но получится проще.
     
  11. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Vov4ick
    А как это на ассемблере?
     
  12. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    отредактировано...

    <ответ постом ниже>
     
  13. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Это неверно. ReadFile/WriteFile всегда переходят в режим ядра, так что вызывать их для побайтного чтения в случае хоть сколько-нибудь значительного файла приведёт к очень значительным издержкам. В msvcrt есть буферизация, и размер буфера по умолчанию там 0x200 байт.
    Qasm
    Во-первых, если ax=0D0A, то в байтовом представлении байты идут в порядке 0A 0D. Во-вторых, repne scasw ищет ax в массиве слов. Строка - это не массив слов, а массив байт. Если, к примеру, строка состоит из одного символа 41 ('A'), после которого следует перевод строки (в стиле DOS/Win, 0D 0A), то repne scasw проверит позицию 0, потом позицию 2, потом позицию 4, но не промежуточные позиции, так что не найдёт ничего.
     
  14. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    diamond
    У меня с этим всегда проблемы были
    Ну да, я об этом догадывался

    Magnum
    Огромное спасибо! Пара вопросов об этом коде:
    1) там случайно вместо mov ecx, [BufSize] не должен стоять mov ecx, [BlockSize]? Просто я не уверен
    2) BlockSize:lol: WORD <- что сюда надо передавать? Я со строковыми операторами в ассемблере не знаком, поэтому такие немного странные вопросы
    3) XP вылетает с ошибкой ("Не отправлять отчет"), там точно должен стоять ret 12? Я его поменял на просто ret и больше ошибок с XP не было. Но он уже неправильно определял строку. Вот как я вызывал:

    Код (Text):
    1.     invoke      CreateFileMapping,hFile,NULL,PAGE_READONLY,0,0,NULL
    2.     mov     hMapFile,eax
    3.     invoke      MapViewOfFile,hMapFile,FILE_MAP_READ,0,0,0
    4.     mov     pMapFile,eax
    5.  
    6.     invoke      lstrlen,pMapFile
    7.     mov     BufSize,eax
    8.    
    9.     invoke      ReadStr,pMapFile,addr szBuffer512_2,1 ; последний параметр наугад
    10.     invoke      MessageBox,hwnd_dlg_Main,addr szBuffer512_2,0,0
     
  15. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Тот код я за 2 минуты накатал...
    Вот рабочий вариант.

    На входе:
    pSrc - начало входного буфера
    EndFile - конец входного буффера (в твоем случае pMapFile + FileSize. FileSize можно получить, воспользовавшись функцией GetFileSize)
    pDest - выходной буффер

    Код (Text):
    1. ReadStr proc pSrc:DWORD,  EndFile:DWORD,  pDest:DWORD
    2.     pushad
    3.     mov esi,  [pSrc]
    4.     mov edi,  [pDest]
    5.     mov ebx, [EndFile]
    6.  
    7. read_str:
    8.         cmp esi, ebx
    9.         jz end_read
    10.     movsb
    11.     cmp word ptr [esi-1], 0A0Dh
    12.     jnz read_str
    13.  
    14. end_read:
    15.      movsb
    16.      mov dword ptr [esp+28], esi
    17.      mov dword ptr [esp+20], edi
    18.      popad
    19.      ret
    20. ReadStr endp
    на выходе:
    еах - указатель на начало новой строки в файле
    edx - указатель на конец текущей строки в выходном буффере


    вызывать так:
    Код (Text):
    1. mov ecx, pMapFile
    2. add ecx, FileSize  
    3. invoke  ReadStr, pMapFile, ecx, pOutBuffer  ;считываем первую строку
    4. invoke  ReadStr, eax, ecx, edx              ;считываем вторую строку
    5. invoke  ReadStr, eax, ecx, edx              ;считываем n-ую строку
     
  16. nobodyzzz

    nobodyzzz New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2005
    Сообщения:
    475
    Код (Text):
    1. invoke lstrlen,pMapFile
    2. mov BufSize,eax
    сие есть не верно, ибо маппинг не есть zero-terminated строка =))
     
  17. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    Magnum
    Все заработало, проверял. Огромное спасибо! +1
     
  18. Qasm

    Qasm New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2008
    Сообщения:
    14
    nobodyzzz
    Ну да, чет не подумавши написал