Blog. Just Blog

Многострочные и юникодные данные в INI-файлах

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Многострочные и юникодные данные в INI-файлах
Многострочные и юникодные данные в INI-файлах

При всех неоспоримых плюсах ini-файлов у них есть ряд недостатков, которые так любят приводить в пример их противники. Например, ini-файлы не поддерживают значения ключей в юникоде, а также не позволяют сохранять многострочные текстовые данные. Основные функции и способы работы с ini-файлами мы уже разобрали, осталось устранить выявленные недостатки и на этом можно будет закрыть тему.

Вкратце, оба указанных недостатка можно обойти, если рассматривать юникодные или многострочные тексты не как строки, а как набор двоичных данных. Для их чтения и записи есть, соответственно, функции GetPrivateProfileStruct и WritePrivateProfileStruct, о которых я упоминал в предыдущей статье. Но, как говорится, есть нюанс.

Поскольку обе эти функции работают со структурами, размер передаваемых данных у них должен быть строго фиксированный, так как контрольные значения размеров записываются в значение ключа. Начнем с записи строк. При записи данных функцией WritePrivateProfileStruct надо указывать точный размер записываемой структуры, в то время, как функции WritePrivateProfileString достаточно только указателя на строку. В приведенных ниже примерах я буду считать, что текст в юникоде и, возможно, многострочный.
  1.         ; Получить юникодный текст из поля ввода
  2.         invoke  GetDlgItemText,[hwnddlg],ID_TEXT,buff,max_buff_len
  3.         ; Длина "структуры" в байтах
  4.         inc     eax
  5.         shl     eax,1
  6.         ; Сохранить юникодную строку в ini-файл
  7.         invoke  WritePrivateProfileStruct,szSection,szKey,\
  8.                 buff,eax,ini_file
GetDlgItemText возвращает длину текста в символах, к ней прибавляем длину нулевого символа и умножаем полученное значение на 2, так как строка в юникоде и для кодирования каждого символа нужно два байта. В итоге получаем размер "структуры", которую надо будет записать в ini-файл.

С чтением немного сложнее. При попытке запросить данные "с запасом", как это делается функцией GetPrivateProfileString, выполнение GetPrivateProfileStruct завершится с ошибкой. Ей также надо указывать точный размер читаемой структуры. Получить этот размер можно несколькими способами. Первый - завести дополнительный ключ с числовым значением длины и обновлять его при записи. Этот способ имеет право на существование, но очень не хочется таскать в ini-файле избыточные данные. Второй способ - сначала получать сохраненные данные как строку, подсчитывать ее длину, а затем повторно загружать как структуру. Так и сделаем.
  1.         ; Очистить буфер для данных
  2.         invoke  RtlZeroMemory,buff,buff_len
  3.         ; Выделить память в куче
  4.         invoke  GetProcessHeap
  5.         invoke  HeapAlloc,eax,HEAP_ZERO_MEMORY,0xFFFF
  6.         mov     ebx,eax
  7.         ; Прочитать значение ключа как строку
  8.         invoke  GetPrivateProfileString,szSection,szKey,\
  9.                 NULL,ebx,0xFFFF,ini_file
  10.         or      eax,eax
  11.         jz      @f
  12.         ; Длина "структуры" в байтах
  13.         shr     eax,1
  14.         dec     eax
  15.         ; Прочитать двоичные данные
  16.         invoke  GetPrivateProfileStruct,szSection,szKey,\
  17.                 buff,eax,ini_file
  18. @@:
  19.         ; Прибраться за собой
  20.         invoke  GetProcessHeap
  21.         invoke  HeapFree,eax,NULL,ebx
Тут я динамически беру память из кучи, но можно использовать заранее зарезервированный буфер, особенно в случае, если планируется активная работа с ini-файлом. Согласно документации, максимальный размер значения ключа не может превышать 65535 байт. При подсчете размера "структуры" от прочитанной строки отсекается контрольное значение.

В приложении пример программы с исходным текстом, которая хранит многострочные юникодные текстовые данные в ini-файле и работает с ними.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Unicode.Multiline.INI.Demo.zip (3,007 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 632 | Комментариев: 2

Комментарии

Отзывы посетителей сайта о статье
ManHunter (23.07.2023 в 23:35):
Павел, так в этом и весь смысл. Хранить можно что угодно и где угодно, а вот пользоваться в удобном виде - нет. Никто ж не запрещает какими-то кастомными средствами записать юникод в чистом виде в ini-файл, но только читать его придется такими же кастомными решениями, без использования WinAPI.
Павел (23.07.2023 в 23:30):
На самом деле аргументы противников ini-файлов, в том числе и самой MS относятся в своём большинстве к функциям WinApi. Сами же ini-файлы всех этих глупых ограничений, типа юникода, не имеют. Но противники об этом старательно умалчивают. ))

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.06 сек. / MySQL: 2 (0.0042 сек.) / Память: 4.5 Mb
Наверх