Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Чтение бинарного файла


Автор: bawukr 15.6.2007, 21:29
Подскажите, как читать данные из бинароного файла.

Формат данных на Си выглядит так:

Код

struct Header
  {
   int               version;
   char              copyright[64];
   char              symbol[12];
   time_t            timesign;
   int               unused[13];
  };


Как мне прочитать char длиной [64] байта и  time_t ? Какая у time_t вообще длина (Подозреваю, что Long)?

Автор: Entry_N3 15.6.2007, 22:25
Это вопрос в разделе по Java?

Автор: bawukr 15.6.2007, 22:31
Да, т.к. такую структуру мне надо читать в JAVA

Автор: nornad 16.6.2007, 00:53
Цитата(bawukr @  16.6.2007,  00:29 Найти цитируемый пост)
Как мне прочитать char длиной [64] байта и  time_t ?

char[64] - легко, если тупо 64 раза прочитать char
time_t - если я правильно помню и ничего не путаю, то это long (в MSDN'е сказано, что это __int64 or long integer  smile )

Автор: LSD 16.6.2007, 09:23
Цитата(bawukr @  15.6.2007,  22:29 Найти цитируемый пост)
Как мне прочитать char длиной [64] байта и  time_t ? Какая у time_t вообще длина (Подозреваю, что Long)?

char - это что за тип данных (сколько байт занимает, какая кодировка, litle/big endian)?
Цитата(bawukr @  15.6.2007,  22:29 Найти цитируемый пост)
Какая у time_t вообще длина (Подозреваю, что Long)?

Тебе видней, что вообще за тип такой timesign. В Java время хранится в виде целого long (8 байт), а вот как оно хранится в C тебе видней.

Если ты четко объяснишь в каком формате хранятся данные (количество и порядок байт, формат и т.д.) то прочитать их не проблема.

Автор: nornad 16.6.2007, 14:00
Да, не подумал, что в жабе char - юникодовский. smile
Тут сишный char, а он один байт.

Про time_t я уже сказал. В данном случае это тоже восьмибатовый лонг.

Автор: bawukr 17.6.2007, 03:30
Вот насчет litle/big endian, я как то не подумал... сижу сейчас мучаюсь..

читайю файл так:

DataInputStream din = new DataInputStream(
             new FileInputStream(xfile));
      
int version = din.readInt();


Знаю что в самом начале файла сохранен тип Int со значением 400.
Но когда читаю выше указаным способом, получаю билеберду в виде -1878982656

Насколько я понял, друшлянул я как раз в litle/big endian

Подскажите, что надо сделать?

Автор: LSD 17.6.2007, 13:05
Цитата(bawukr @  17.6.2007,  04:30 Найти цитируемый пост)
Подскажите, что надо сделать?

Забить на DataInputStream и сделать чтение вручную:
Код
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if((ch1 | ch2 | ch3 | ch4) < 0)
  throw new EOFException();
int result =  ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));

Автор: bawukr 18.6.2007, 16:23
Последний раз помучаю Вас.  smile 

А как, тоже самое только для Double делать?

Автор: LSD 18.6.2007, 19:49
Цитата(bawukr @  18.6.2007,  17:23 Найти цитируемый пост)
А как, тоже самое только для Double делать?

Элементарно:
Код
long ch1 = in.read();
long ch2 = in.read();
long ch3 = in.read();
long ch4 = in.read();
long ch5 = in.read();
long ch6 = in.read();
long ch7 = in.read();
long ch8 = in.read();
if((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
  throw new EOFException();
long l = (ch8 << 56) + (ch7 << 48) + (ch6 << 40) + (ch5 << 32) + (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
double d = Double.longBitsToDouble(l);

или так:
Код
long ch1 = in.read();
long ch2 = in.read();
long ch3 = in.read();
long ch4 = in.read();
long ch5 = in.read();
long ch6 = in.read();
long ch7 = in.read();
long ch8 = in.read();
if((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
  throw new EOFException();
long l = (ch1 << 56) + (ch2 << 48) + (ch3 << 40) + (ch4 << 32) + (ch5 << 24) + (ch6 << 16) + (ch7 << 8) + (ch8 << 0);
double d = Double.longBitsToDouble(l);

смотря какой порядок байт используется C++.

Автор: math64 19.6.2007, 12:29
Во всех известных мне компиляторах time_t  это 32 разрядный long, число секунд с 1 января 1970 года (0x7FFFFFFF - около 2036 года). В Java время считается от той же даты, но в миллисекундах и long - 64 разрядный. Нужно считать в int, учитывая litle/big endian, скопировать int в long, замаскировать старшие биты и умножить на 1000.
Строки считать в массив байт, найти конечный 0 и конвертировать в String: new String(bytes, 0, length, "Cp1251");
Между полями структуры могут для выравнивания быть вставлены пустые байты, которые нужно пропускать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)