четверг, 19 ноября 2009 г.

Файл "своего" типа

Если вашей программе требуется сохранять в файлах какие-то специфические данные, то наверняка встанет вопрос о формате файла. Например, если сохраняются картинка, текст и звук в одном файле. Можно, конечно, воспользоваться компонентом Zipper, который упакует всё в zip-архив, однако "свой" формат - это более профессионально и универсально.

Поскольку мы говорим о сохранении в файле картинок и других нетекстовых данных, то ясно, что использовать придётся файловый поток и работать с байтами файла. А потому прочтите статью о бинарных файлах и работе с файловым потоком, если вы ещё этого не сделали.

Прежде всего, необходимо решить, как будет устроен ваш формат. Ведь файл – это просто набор байт, и если программа не будет знать, откуда какие данные читать, то ничего извлечь не сможет, ведь любой байт может принадлежать к любым данным.

Для демонстрации создадим формат, который будет содержать в себе картинку, комментарий к ней и звук. И пусть первыми будут байты картинки, следующими – байты комментария, а затем – байты звука. Картинку и звук будем брать с диска, комментарий – писать сами.

Но если мы байты из файла картинки, комментарий и байты из файла звука добавим друг за другом, то потом не сможем определить, где кончаются одни данные (например, картинка) и начинают другие (комментарий). А потому перед байтами каждых данных нужно записывать их размер (т.е. количество байт этих данных). Размер – это число, поэтому можно использовать значения байт (ведь это тоже числа). Но один байт может иметь максимальное значение 255, и это мало. Оптимально – 4 байта, это более 4 миллиардов значений. И максимальное количество байт, которое можно обозначить 4-мя байтами – 4 Гб.



В этой схеме загрузка картинка вам уже известна. А вот загрузка звука идёт не для проигрывания, а для получения байт из файла звука. Как вы видите, после открытия идёт его закрытие, но событие onLoad компонента FileStream передаёт файловый поток компоненту MemoryStream, который предназначен для запоминания файлового потока. Мы делаем так, чтобы не прекращать доступ к файлу других программ, пока работает эта.



Поначалу может показаться, что схема сложная, но начинаем, как обычно, с первых событий и идём по линиям связи…
При сохранении файла сначала в диалоговом окне запрашивается имя для сохранения. Введите любое. Расширение также не имеет значения. Оно передаётся в потоке через разветвитель на метод doOpen. А FileStream имеет Mode=Write, то есть файл открывается для записи. А если файла нет – он создаётся. Так что после этой операции файл создан и открыт для записи.

Второе событие разветвителя записывает строку в файл. Обратите внимание: параметр Type=dtAnsiString, то есть записывается строка, а потому никакие байты передавать не надо: компонент сам всё преобразует. Размер мы также не указываем, потому что к этой строке в конец добавляется байт с номером 0, по которому программа и найдёт конец строки.
Следующее событие разветвителя задействует компонент BitmapStream. Этот компонент из bmp-картинки получает набор байт и наоборот. Мы здесь даже DtatToFile не используем, потому что считывать будем картинку этим же компонентом, и он сам определит её размер (соответственно, число байт, которое он сам запишет в файл, и нам размер записывать не надо).
А вот подобного компонента для звука нет, поэтому приходится из MemoryStream получать сначала размер данных, который записывать как число Integer. А затем записываем в файл сами данные, причём делаем это через точку doCopyFromStream,. Этот метод записывает в файл сразу файловый поток целиком, а не отдельные байты, что нам и нужно.

Осталось лишь реализовать чтение такого файла.



Разберёмся с ней. Когда в диалоге вы выберете свой файл и откроете его, FileStream откроется его в режиме чтения. Затем будет прочитана строка типа AnsiString и передана в поле ввода.
Потом будет из потока загружена картинка (помните, что указатель уже сдвинут к байту после строки, а это как раз картинка).
Со звуком немного сложнее. Сначала считывается, конечно, размер (указатель уже у этих байт). После этого вступает в действие компонент StreamCopy. Он копируется часть файлового потока, а именно: в новый MomoryStream копируется с текущей позиции столько байт, сколько показал нам DataToFile. Затем используется TempFileStream, потому что из памяти пока в HiAsm файл проиграть нельзя. TempFileStream создаёт временный файл (его имя и местоположение автоматически определяются системой, и вам не нужно об этом заботиться, ведь такой файл после закрытия программы исчезнет), а данные в него записывает те, что скопировали ранее. Ну и затем PlaySound проигрывает звук.

Вот и всё. Это основы создания файлов «своего» типа. С их помощью вы сможете создавать «свои» файлы для разных ситуаций. А в следующей статье я расскажу про сжатие информации.




Когда потребуется перевезти грузы, обращайтесь в компанию "Трансмиссия". Она осуществляет грузоперевозки по России и имеет широкий выбор транспорта, который в целости и сохранности доставит ваш груз.

Еслиу вас есть бизнес, но вы не хотите создавать для него бухгалтерский штат, то лучший выход - получить бухгалтерские услуги от компании "Оптима". Произведёт бухучёт, налоговую отчётность и многое другое.

Собрались закреплять изделия - используйте дюбель-гвоздь Wkret-Met, быстрый монтаж. Гвоздь вбивается, а шуруп потом выкручивается.

3 комментария:

  1. Этот комментарий был удален автором.

    ОтветитьУдалить
  2. Автор перезалей видео файл не качает или скинь на мыло komlvl@bk.ru зарание благодарен

    ОтветитьУдалить
  3. Этот комментарий был удален автором.

    ОтветитьУдалить