Многострочные и юникодные данные в INI-файлах
Многострочные и юникодные данные в INI-файлах
При всех неоспоримых плюсах ini-файлов у них есть ряд недостатков, которые так любят приводить в пример их противники. Например, ini-файлы не поддерживают значения ключей в юникоде, а также не позволяют сохранять многострочные текстовые данные. Основные функции и способы работы с ini-файлами мы уже разобрали, осталось устранить выявленные недостатки и на этом можно будет закрыть тему.
Вкратце, оба указанных недостатка можно обойти, если рассматривать юникодные или многострочные тексты не как строки, а как набор двоичных данных. Для их чтения и записи есть, соответственно, функции GetPrivateProfileStruct и WritePrivateProfileStruct, о которых я упоминал в предыдущей статье. Но, как говорится, есть нюанс.
Поскольку обе эти функции работают со структурами, размер передаваемых данных у них должен быть строго фиксированный, так как контрольные значения размеров записываются в значение ключа. Начнем с записи строк. При записи данных функцией WritePrivateProfileStruct надо указывать точный размер записываемой структуры, в то время, как функции WritePrivateProfileString достаточно только указателя на строку. В приведенных ниже примерах я буду считать, что текст в юникоде и, возможно, многострочный.
Code (Assembler) : Убрать нумерацию
- ; Получить юникодный текст из поля ввода
- invoke GetDlgItemText,[hwnddlg],ID_TEXT,buff,max_buff_len
- ; Длина "структуры" в байтах
- inc eax
- shl eax,1
- ; Сохранить юникодную строку в ini-файл
- invoke WritePrivateProfileStruct,szSection,szKey,\
- buff,eax,ini_file
С чтением немного сложнее. При попытке запросить данные "с запасом", как это делается функцией GetPrivateProfileString, выполнение GetPrivateProfileStruct завершится с ошибкой. Ей также надо указывать точный размер читаемой структуры. Получить этот размер можно несколькими способами. Первый - завести дополнительный ключ с числовым значением длины и обновлять его при записи. Этот способ имеет право на существование, но очень не хочется таскать в ini-файле избыточные данные. Второй способ - сначала получать сохраненные данные как строку, подсчитывать ее длину, а затем повторно загружать как структуру. Так и сделаем.
Code (Assembler) : Убрать нумерацию
- ; Очистить буфер для данных
- invoke RtlZeroMemory,buff,buff_len
- ; Выделить память в куче
- invoke GetProcessHeap
- invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,0xFFFF
- mov ebx,eax
- ; Прочитать значение ключа как строку
- invoke GetPrivateProfileString,szSection,szKey,\
- NULL,ebx,0xFFFF,ini_file
- or eax,eax
- jz @f
- ; Длина "структуры" в байтах
- shr eax,1
- dec eax
- ; Прочитать двоичные данные
- invoke GetPrivateProfileStruct,szSection,szKey,\
- buff,eax,ini_file
- @@:
- ; Прибраться за собой
- invoke GetProcessHeap
- invoke HeapFree,eax,NULL,ebx
В приложении пример программы с исходным текстом, которая хранит многострочные юникодные текстовые данные в ini-файле и работает с ними.
Просмотров: 844 | Комментариев: 2
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(23.07.2023 в 23:35):
Павел, так в этом и весь смысл. Хранить можно что угодно и где угодно, а вот пользоваться в удобном виде - нет. Никто ж не запрещает какими-то кастомными средствами записать юникод в чистом виде в ini-файл, но только читать его придется такими же кастомными решениями, без использования WinAPI.
Павел
(23.07.2023 в 23:30):
На самом деле аргументы противников ini-файлов, в том числе и самой MS относятся в своём большинстве к функциям WinApi. Сами же ini-файлы всех этих глупых ограничений, типа юникода, не имеют. Но противники об этом старательно умалчивают. ))
Добавить комментарий
Заполните форму для добавления комментария