Вверх ↑
Этот топик читают: Гость
Разработчик
Ответов: 4698
Рейтинг: 426
#1: 2015-01-31 00:15:26 ЛС | профиль | цитата
Два компонента для чтения/записи структур в потоках (stream).

Способности:
Работает с данными из потока в виде структуры, которая задается в специальном легком формате (ниже).

Как задать структуру?

  Очень просто: структура задается в виде списка точек, однако после имени точки следует имя типа этого поля. Например:
fisrtname=string
lastname=string
age=byte

Поддерживаются следующие типы:

  • Real (вещественное число)
  • Integer
  • Word
  • Byte
  • Char
  • String (первые 4 байта - размер строки, далее сама строка)
  • ZString (строка, заканчивающаяся символом с кодом 0 ('\0'))
Кроме того, после имени типа в квадратных скобках можно указать количество полей этого типа (т.е. задать массив). Из потока данных они будут считаны в виде MT-потока (и то же будет ожидаться при записи).
(!) Особенность: массив из char будет считан как обычная строка (фиксированной длины) и при записи тоже будет ожидаться строка (если она будет длиннее - все остальное не запишется).
Пример:
firstname=char[10]
lastname=char[10]
age=byte
mobilephone=byte[11]

Формат записи типа обновлен:
point_name=typename[_[s|u][le|be]][:length][[arr_length]]
s/u - знаковое ([s]igned) или беззнаковое ([u]nsigned)
le/be - little endian или big endian
:length - длина аргумента (префикса строки, длины целочисленного или вещественного числа. В байтах).
arr_length - длина массива элементов этого типа

Например:
a = integer_u:6 //целое, беззнаковое 6 байтовое
b = string:4[2] //массив из 2 строк с префиксом в 4 байта
c = word_be //слово с порядком байт Big Endian
d = integer_ule:5[2] //массив из 2 целых беззнаковых чисел с порядком байт Little Endian и длиной в 5 байт каждый

Скачать последнюю версию - filestructrw12.rar

P.S.: тестовая схема-пример прилагается.

Редактировалось 14 раз(а), последний 2016-09-16 15:40:18
карма: 10
6
файлы: 1filestructrw.rar [6.9KB] [400]
Голосовали:LainX, Леонид, halt, ser_davkin, miver, Konst
Ответов: 9906
Рейтинг: 351
#2: 2015-01-31 10:33:07 ЛС | профиль | цитата
Assasin писал(а):

  • String (первые 4 байта - размер строки, далее сама строка)
  • PString (строка, заканчивающаяся символом с кодом 0 ())

  • Вообще-то, в DataToFile - наоборот.
    PString - префиксная строка (хоть префикс и двухбайтный)

    Спрашивается: зачем людей путать
    карма: 9

    0
    Разработчик
    Ответов: 4698
    Рейтинг: 426
    #3: 2015-01-31 14:31:34 ЛС | профиль | цитата
    Galkov писал(а):
    Вообще-то, в DataToFile - наоборот.
    PString - префиксная строка (хоть префикс и двухбайтный)

    Хм, действительно. Вот только правильно ли это?
    карма: 10
    0
    Ответов: 964
    Рейтинг: 12
    #4: 2015-02-01 01:20:42 ЛС | профиль | цитата
    Брр.. Разве PString это не УКАЗАТЕЛЬ на обычный String ?
    Насколько я помню со времен BP есть спец команды NewStr(S:String ) : PString; и DisposeStr(PS : PString) (или их аналоги )
    Недавно юзал в Лазарусе ...
    А PChar действительно строка, заканчивающаяся символом с кодом 0 () ASCIZ

    http://www.programmersclub.ru/typepchar/

    карма: 0

    0
    Ответов: 2059
    Рейтинг: 132
    #5: 2015-02-01 01:42:00 ЛС | профиль | цитата
    Тип PString - указатель на String значение. А String сам является указателем.
    PString = ^String;
    Массив символов String тоже заканчивающаяся символом с кодом 0 для быстрой конвертации.
    Иногда путают понятия String и СТРОКА.
    Вся путаница из за того что String и СТРОКА являются своего рода омографами.
    String - это указатель на массив символов (после префикса), а СТРОКА - это префикс(длинна массива) и идущий за ним массив символов оканчивающийся 0.
    Тип PChar - указатель на значение символа.
    Он может также использоваться для указания на символы в пределах строки.
    Если PChar указывает на первый символ строки, то его можно ассоциировать с ASCIZ строкой.
    Иногда пишут такое:

    PChar - нультерминальная строка

    - pstr: PChar; - это нультерминальная строка (zero-terminated). Так называется, потому что представляет собой указатель на цепочку символов, заканчивающуюся терминальным нулем #0. Ее еще называют сишной строкой (из языка С, там она определяется как char*).
    - type PChar = ^Char;
    - Используется для вызова ANSI-версий API-функций (типа CreateFileA). VCL использует только ANSI-версии API-функций для совместимости со всеми версиями Windows, поэтому вызов CreateFile идентичен CreateFileA. В модуле SysUtils сделаны функции-оболочки для многих API-функций, в которые надо передавать String вместо PChar (все-таки PChar не родной паскалевкий тип).
    Но это не корректно, потому что полуправда.
    Пытаются выдать частный случай за формулировку понятия.
    Это всё равно, что все прямоугольники назвать квадратами, а вот обратное можно.

    Строк с двухбайтовым префиксом в природе нет.
    Есть паскалевская стока она-же ShortString без терминального 0.
    Но она имеет префикс в один байт (255 символов).
    карма: 6

    0
    Ответов: 9906
    Рейтинг: 351
    #6: 2015-02-01 09:57:16 ЛС | профиль | цитата
    flint2 писал(а):
    Строк с двухбайтовым префиксом в природе нет.

    В природе есть ВСЕ. И одно-байтные префиксы, и двух, и трех... Не говоря уже о четырех.
    И real в природе не всегда 8-байтный... И формат чисел не всегда бывает интеловский (Litle Endian).

    Если под "природой" понимать содержимое файлов сторонних производителей.
    А не собственные фантазии. Или фантазии производителей скриптовых языков.

    Вообще-то, для того, чтобы можно было прочитать "ВСЕ", я и делал DataToFileEx.
    Коллеге Assasin, можно было бы и ознакомиться с его набором свойств
    карма: 9

    0
    Ответов: 2059
    Рейтинг: 132
    #7: 2015-02-01 14:25:00 ЛС | профиль | цитата
    Galkov
    Если под "природой" понимать содержимое файлов сторонних производителей.

    Подобный ответ был ожидаем.
    Но я намеренно не привёл примеры "не правильных" строк, потому что это от лукавого.
    Что касается DataToFileEx - абсолютная истина.
    карма: 6

    0
    Разработчик
    Ответов: 4698
    Рейтинг: 426
    #8: 2015-02-01 21:40:13 ЛС | профиль | цитата
    Galkov писал(а):
    Вообще-то, для того, чтобы можно было прочитать "ВСЕ", я и делал DataToFileEx.
    Коллеге Assasin, можно было бы и ознакомиться с его набором свойств

    А можно ссылочку? Вменяемой темы поиск не выдал что-то. Боюсь промахнуться с версией. Различных типов данных наделать-то - не проблема.
    карма: 10
    0
    Ответов: 9906
    Рейтинг: 351
    #9: 2015-02-01 22:33:53 ЛС | профиль | цитата
    Скажем - здесь

    Редактировалось 1 раз(а), последний 2017-08-21 20:04:02
    карма: 9

    1
    Голосовали:Assasin
    Разработчик
    Ответов: 4698
    Рейтинг: 426
    #10: 2015-02-08 03:02:14 ЛС | профиль | цитата
    Версия 1.1:

    • Оптимизирован расход памяти
    • Запись корректного байта в типе данных char.
    • При типе char[]: исправлена запись строки, длина которой меньше, чем указанный размер массива чаров.
    • Добавлено чтение целочисленных знаковых/беззнаковых и вещественных чисел разной длины (по компоненту Galkov-а)
    • Добавлена возможность указать порядок байт (big/little endian) (по компоненту Galkov-а)
    • Добавлена возможность указать длину префикса строки для типа данных string. (по компоненту Galkov-а)
    • Тип pstring переименован в zstring для исключения путаницы.

    Формат записи типа обновлен:
    point_name=typename[_[s|u][le|be]][:length][[arr_length]]
    s/u - знаковое ([s]igned) или беззнаковое ([u]nsigned)
    le/be - little endian или big endian
    :length - длина аргумента (префикса строки, длины целочисленного или вещественного числа. В байтах).
    arr_length - длина массива элементов этого типа

    Например:
    a = integer_u:6 //целое, беззнаковое 6 байтовое
    b = string:4[2] //массив из 2 строк с префиксом в 4 байта
    c = word_be //слово с порядком байт Big Endian
    d = integer_ule:5[2] //массив из 2 целых беззнаковых чисел с порядком байт Little Endian и длиной в 5 байт каждый

    Скачать - filestructrw11.rar

    Редактировалось 2 раз(а), последний 2016-09-16 15:17:38
    карма: 10
    4
    файлы: 1filestructrw11.rar [7.6KB] [418]
    Голосовали:ser_davkin, flint2, Konst, MasterXP
    Ответов: 758
    Рейтинг: 112
    #11: 2016-09-12 16:43:18 ЛС | профиль | цитата
    Assasin, Хочу прочитать структуру из файла
    Текстовая строка 19 байт и целое число 4 байта

    Add(MainForm,2953706,77,112)
    {
    Position=1
    }
    Add(FileStructReader,2819639,315,112)
    {
    Structure=#13:name=char[19]|10:tt=integer|
    link(onRead,16763951:doMessage,[])
    }
    Add(StyleXP,13914717,77,70)
    {
    }
    Add(Button,3303658,147,112)
    {
    Left=10
    Top=10
    link(onClick,8838475:doOpen,[])
    }
    Add(FileStream,8838475,203,112)
    {
    FileName="p.dat"
    link(onLoad,1842876:doEvent1,[])
    }
    Add(Message,16763951,371,112)
    {
    link(Message,2819639:name,[(377,103)(363,103)(363,159)(321,159)])
    link(Caption,2819639:tt,[(384,96)(356,96)(356,152)(328,152)])
    }
    Add(Hub,1842876,252,112)
    {
    OutCount=3
    link(onEvent1,2819639:doRead,[])
    link(onEvent2,11908774:doMessage,[(305,125)(305,209)])
    link(onEvent3,8838475:doClose,[(277,132)(277,153)(193,153)(193,125)])
    }
    Add(Message,11908774,322,203)
    {
    link(Message,8838475:Size,[(328,194)(216,194)])
    link(Caption,8838475:Position,[(335,187)(223,187)])
    }

    Но он выводит только 9 символов текста и непонятное число (перевел текстовые символы)
    Может где-то ошибка? Или я что-то не так делаю?

    Редактировалось 1 раз(а), последний 2016-09-12 16:47:10
    карма: 1

    1
    Голосовали:Assasin
    Разработчик
    Ответов: 4698
    Рейтинг: 426
    #12: 2016-09-16 14:39:42 ЛС | профиль | цитата
    miver писал(а):
    Но он выводит только 9 символов текста и непонятное число (перевел текстовые символы)

    Действительно. Небольшая бага была с регулярным выражением, которое используется внутри текста, в результате чего захватывалась только последняя цифра в [19] (т.е. 9). Исправил, компоненты в аттаче. Если не охота перекачивать, просто замени в файле hiFileStructReader.pas 88 строчку на:
    re.Expression := '^([\w\s]+)=\s*(\w+?)(_([su])?([lb]e)?)?\s*(:\s*(\d+)\s*)?(\[\s*(\d+)\s*\])?\s*$';

    --- Добавлено в 2016-09-16 14:43:34

    Офигеть, исправил ссылку в первом посте, и он вообще подчистую стерся после нажатия "сохранить"

    Редактировалось 3 раз(а), последний 2016-09-16 14:43:51
    карма: 10
    1
    файлы: 1filestructrw12.zip [8KB] [513]
    Голосовали:miver
    12
    Сообщение
    ...
    Прикрепленные файлы
    (файлы не залиты)