» Главная
eXcode.ru » Статьи » Ruby
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 18





Цигун в москве

Обзоры и анонсы спортивных мероприятий. Адреса клубов лиги.

doctor-gui.ru




Чтение/запись двоичных файлов на Ruby




Данная мини-статья родилась в связи с тем, что мне понадобилось читать/писать двоичный файл. Соглашусь, задача для Руби несколько нетипичная, но надо - значит надо.

В сети информации по данной теме практически нет. Что-то есть на google groups, но толкового описания я не нашёл. В результате, начал выдумывать сам.

Итак была задача научиться читать и писать двоичный файл, созданный с помощью MFC метода Serialize. В файле присутствуют CString, int, float, double, BOOL и COLORREF.

Приведу кусочек кода на C++:

// создание файла
... ::Serialize(CArchive& archive)
{
int A = 44;
COLORREF Color = RGB(255,10,128);
float F = 0.345678;
BOOL B = FALSE;
CString str = _T("This is a sample string.");
archive << A << Color << F << B << str;
}

Небольшое отступление про сериализацию в MFC:
данные в файле хранятся "как есть", за исключением CString. Сей объект хранится в паскалевской нотации вида <1 байт - длина строки><строка>. В случае строк длиннее 255 символов - в виде <0xFF><2 байта - длина строки><строка>. В случае нулевой строки - <0>.

Речь идёт про ANSI строки, как хранятся UNICODE строки я не выяснял, в мои задачи это не входило. Предлагаю вам самим исследовать этот вопрос и поделиться с народом :)

Далее я применил слегка "нечестный" метод - подсчитал сколько байт занимает тот или иной тип. "Нечестный" - потому что на разных платформах данные будут разными. Меня интересовал Windows XP и 32-х битный компилятор Visual Studio 7.1.

#include ...
void main(void)
{
printf("float:%d, double:%d, int:%d, COLORREF:%d, BOOL:%d\n",
sizeof(float), sizeof(double), sizeof(int), sizeof(COLORREF), sizeof(BOOL));
}

Получаем для Windows XP:

float:4, double:8, int:4, COLORREF:4, BOOL:4

Собственно и всё. Далее - дописываем нужные методы к классу "File":

class File
def read_float
f = read(4).unpack("f")
end

def read_int
f = read(4).unpack("i")
end

def read_cstring
f = read(1).unpack("c")
if (f == 0)
return ""
end
if (f[0] == -1)
f = read(2).unpack('s')
str = read(f[0])
return str
end
str = read(f[0].to_i)
end

def read_colorref
f = read(4).unpack("i")
end

def read_double
f = read(8).unpack("d")
end

def write_float(float_var)
write(float_var.pack("4f"))
end

def write_double(double_var)
write(double_var.pack("8d"))
end

def write_int(int_var)
write(int_var.pack("4i"))
end

def write_colorref(colorref_var)
write(colorref_var.pack("4i"))
end

# TODO Поддержать длинные строки
def write_cstring(str_var)
len = str_var.length
write([len].pack("1c"))
write(str_var) if len > 0
end
end

Читаем:

def ReadBinary
f = File.open ("our.binary.file", "rb")
@A = f.read_int
@Color = f.read_colorref
@F = f.read_float
@B = f.read_int
@str = f.read_cstring
f.close
end

Пишем:
def WriteBinary
f = File.open("our.binary.file", "wb")
f.write_int(@A)
f.write_colorref(@Color)
f.write_float(@F)
f.write_int (@B)
f.write_cstring(@str)
f.close
end

Разумеется, порядок чтения/записи должен соответствовать порядку в функции сериализации.

Источник: www.ruby.inuse.ru
К началу статьи





Добавил: MadvEXДата публикации: 2008-02-11 00:34:32

Рейтинг статьи:0.00 [Голосов 0]Кол-во просмотров: 2690
Оцените статью:

Комментарии читателей

Всего комментариев: 0
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Вы программируйте ради
денег
15% (31)
славы
4% (8)
удовольствия
33% (68)
знаний
20% (40)
просто так
5% (10)
все вместе
23% (46)

Проголосовало: 203
- Что для геймера Жизнь?
- Два компакта с "Half-life"!
Рейтинг: 0/10 (0)
Посмотреть все анекдоты

 
eXcode.ru » Статьи » Ruby