Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: fstream, проблемка с побайтным чтением файла  (Прочитано 15064 раз)
0 Пользователей и 1 Гость смотрят эту тему.
spiage
Гость
« : 16-08-2004 02:11 » 

Привет!
Столкнулся с такой проблемой при побайтном чтении файла:
Код:
char c;
ifstream ifile("foo.dat", ios::in | ios::binary);
ifile >> c;
Так вот - если код символа > 128, то число получается отрицательным
Для преобразования приходится делать так:
Код:
int i = (int)(unsigned char)c;
Если использовать сразу unsigned char, то чтение идет неверное...
Есть ли у кого мысли по этому поводу?
(Мне действительно необходимо ПОБАЙТНОЕ чтение, работаю напрямую с DBF)
И еще вопрос - можно ли на С++ работать при file I/O сразу со структурой, как в Паскале? Или все же нет такой встроеной возможности?
ICQ для связи: 127834898
Пример:
Код:
type
   Rec = record
      i: byte;
      s:string[12];
      w:word;
   end;
var
   f: file of Rec;
   r: Rec;
begin
........
   read(f, r);
........
end.
« Последнее редактирование: 30-11-2007 22:26 от Алексей1153++ » Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 16-08-2004 05:03 » 

Цитата

Так вот - если код символа > 128, то число получается отрицательным
Для преобразования приходится делать так:


Цитата

Мне действительно необходимо ПОБАЙТНОЕ чтение


попробуй объявить не char c, а:

UCHAR c;

или

BYTE c;

 :arrow:
Цитата

И еще вопрос - можно ли на С++ работать при file I/O сразу со структурой, как в Паскале?

может и нет, не знаю. Наверное надо будет самому писать класс, который будет делать то, что нужно
Записан

spiage
Гость
« Ответ #2 : 16-08-2004 07:31 » 

У меня было:
Цитата

Если использовать сразу unsigned char, то чтение идет неверное...

Ты посоветовал:
Цитата

попробуй объявить не char c, а:

UCHAR c;

или

BYTE c;

 Улыбаюсь
Но я все равно поверил (видно сказывается привычка Windows-пользователя бить в барабаны и устраивать пляски, в надежде, что все получится  Отлично )
Все равно глючит Улыбаюсь
Проскакивает через байт...
А по поводу чтения структур есть у меня мысль, что через указатель с размером, равным структуре, вполне можно проделать такую штуку...
Лишь бы компилятор порядок следования элементов в структуре не нарушал...
Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #3 : 16-08-2004 07:41 » 

spiage, конэчно можно. вот тебе примерчик.
Код:
#include <fstream>
#pragma pack(push,1)
struct s
{
 int i;
 long l;
 float f;
 s() i(10), l(20), f(40)
                  {}
};

void main()
{
 std::fstream fs( "pr.bin", std::ios::binary | std::ios::out | std::ios::in );
 if(!fs.is_open())        
        return;
 s ss;
 fs.write( (char *)&ss,  sizeof(ss));
 fs.read((char *)&ss,  sizeof(ss));
 return;
}
#pragma pack(pop)
« Последнее редактирование: 30-11-2007 22:28 от Алексей1153++ » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Pu
Большой босс

ru
Offline Offline
78


« Ответ #4 : 16-08-2004 07:42 » 

и вот эти строчки помогут с твоей проблеммкой
Код:
#pragma pack(push,1)
.....
#pragma pack(pop)
« Последнее редактирование: 30-11-2007 22:29 от Алексей1153++ » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Pu
Большой босс

ru
Offline Offline
78


« Ответ #5 : 16-08-2004 07:43 » 

можешь спросить меня что эта прагма делает Улыбаюсь
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
spiage
Гость
« Ответ #6 : 16-08-2004 08:21 » 

А вот так  почему?
Код:
BYTE c;
cout << ifile.tellg() << endl;
ifile >> c;
cout << ifile.tellg() << endl;
Ответ:
Код:
46
48
« Последнее редактирование: 30-11-2007 22:29 от Алексей1153++ » Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #7 : 16-08-2004 08:29 » 

можно весь пример а не только вом это

BYTE c;
cout << ifile.tellg() << endl;
ifile >> c;
cout << ifile.tellg() << endl;

чем инитится с?
где обявление ifile?
просто возникают вопросы
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
spiage
Гость
« Ответ #8 : 16-08-2004 08:32 » 

#ifndef BYTE
typedef unsigned char BYTE;
#endif
...
ifstream ifile(FileName.c_str(), ios::in | ios::binary);
BYTE c;
...... (несколько _удачных_ чтений в "с")
cout << ifile.tellg() << endl;
ifile >> c;
cout << ifile.tellg() << endl;
ifile.close();
Записан
spiage
Гость
« Ответ #9 : 16-08-2004 09:16 » 

Нет, вы представте - я поменял
Код:
ifile >> с
на
Код:
ifile.get(c)
только в одном месте (где "пролет над байтом" был), и все нормально стало...
Похоже, что это глюк компилятора...
(Пользовался С++Builder 6.0 Build 10.155, Windows 2003 Enterprise Server)
« Последнее редактирование: 30-11-2007 22:30 от Алексей1153++ » Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #10 : 16-08-2004 09:27 » 

spiage, я тебе и говорил, что от этих новшеств - аля << и >> я давно отказался, мне понятнее работа  ifile.get(c), ifile.read(c, sizeof(c)), ifile.write(c, sizeof(c))
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 16-08-2004 09:37 » 

spiage,  Улыбаюсь , вот такой я невнимательный

Pu, а  что эта прагма делаетъ? Улыбаюсь
Записан

Pu
Большой босс

ru
Offline Offline
78


« Ответ #12 : 16-08-2004 09:55 » 

Алексей1153,  прагма указывает на сколько при операциях чтения записи делать выравнивание. если не указать единичку то char вместо 1 байта считает и запишет 4 байта, тк в виндах по умолчанию выравнивание по двойному слову. Я на эту фигню нарвался еще давненько когда с доса пересел под винду. подробнее
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/vclang/html/_PREDIR_pack.htm
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
spiage
Гость
« Ответ #13 : 16-08-2004 10:02 » 

А так хотелось по-умному... Жжешь
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 16-08-2004 13:59 » 

spiage, очень странный эффект случился с реализацией istream на MS МЫ 6.0 -- даже при установке режима чтения binary оператор >> перескакивает через байты конца строки.  Возможно, это причина твоей проблемы.

Можно сделать вот как:
#ifndef BYTE
typedef unsigned __int8 BYTE;
#endif

BYTE & operator >> (istream & inf, BYTE & b) { inf.read((char *)&b,1); return b; }

При таком задании байта и оператора чтения оператор >> не перескакивает через концы строк.

Этот пример показывает технику чтения-записи структур в потоки.  При создании своего класса/структуры надо определить свои операторы << и >> для них.  Правда, предложенный Pu способ прямой записи содержимого структуры через read(p, sizeof(*p)) не подходит для структур и классов, содержащих указатели.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
spiage
Гость
« Ответ #15 : 17-08-2004 02:21 » 

npak, Твой вариант подошел, работает вполне нормально без pragma pack(1), и даже с установленной в настройках компилятора Data alignment = Quorted Word (если я правильно понял - это аналог pragma pack(8 ))
Теперь можно к сказанному тобой добавить, что "странная" реализация istream не только на MS VS 6.0 но и на Borland C++Builder 6.0
У меня есть предположение  :idea: , что это из-за того, что в STL::iostream в шаблоне basic_istream реализация operator>> дана только для одного 8-и битного типа - для типа char, который является знаковым по дефолту...
А учитывая, что эта ошибка проявляется вполне произвольно, думаю, что глюк где-то в реализации... 8)
Если будет время - полезу в кишки STL...  :new_shot:
А по хорошему лучше бы вставить в стандарт операцию с бесзнаковым символом  Отлично
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines