#1 13-06-2010 22:56

~AquaZ~
Registered: 01-03-2010
Posts: 726

Запись в двоичные файлы

Замутил прогу, нужно сохранить несколько чисел в двоичный файл. Уже чётко написал, какие данные будут по сколько байт, теперь мне нужно сохранять их в двоичном виде и считывать. Как реализовать на Си++?

З.Ы. WORD - 2 unsigned байта (0-255), BYTE - 1 unsigned байт (0-127)?
З.З.Ы. Желательно VCL-ским классом TFileStream.

Last edited by ~AquaZ~ (13-06-2010 23:00)

Offline

#2 14-06-2010 00:12

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Запись в двоичные файлы

Использование TFileStream для подобной задачи - чистый оверкилл.

// запись
WORD w = 0x1234;
BYTE b = 0x56; 
FILE * f = fopen ("file.bin", "wb");
if (f) { // если файл открылся
  fwrite (&w, sizeof (WORD), 1, f); 
  fwrite (&w, sizeof (BYTE), 1, f);
  fclose (f);
}

// чтение
WORD w;
BYTE b;
FILE * f = fopen ("file.bin", "rb");
if (f) {
  fread (&w, sizeof (WORD), 1, f);
  fread (&b, sizeof (BYTE), 1, f);
  fclose (f);
}

По-хорошему, нужно проверять результат fread/write - они возвращают количество прочитанных записанных байтов.

PS. WORD => 0..65535, BYTE => 0..255

Offline

#3 14-06-2010 05:24

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Спасибо!!!! good
А какой нужен заголовочный файл? rolleyes
З.Ы. Мой З.Ы. из первого поста был чисто бредом smile mad

Last edited by ~AquaZ~ (14-06-2010 05:39)

Offline

#4 14-06-2010 08:30

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Запись в двоичные файлы

stdio.h

Offline

#5 15-06-2010 07:12

Alien
Registered: 12-10-2008
Posts: 564

Re: Запись в двоичные файлы

Хм. Если C++, то лучше подключать cstdio.
А вообще, в C++ принято пользоваться стримами.

#include <fstream>

int main()
{
	unsigned char  b = 0x12;
	unsigned short w = 0x3456;

	// запись
	std::ofstream out;
	out.open("file.bin", std::ios::binary | std::ios::out);
	if (out.is_open())
	{
		out.write(reinterpret_cast<const char *>(&b), sizeof(b));
		out.write(reinterpret_cast<const char *>(&w), sizeof(w));
		out.close();
	}

	// чтение
	std::ifstream in;
	in.open("file.bin", std::ios::binary | std::ios::in);
	if (in.is_open())
	{
		in.read(reinterpret_cast<char *>(&b), sizeof(b));
		in.read(reinterpret_cast<char *>(&w), sizeof(w));
		in.close();
	}
	
	return 0;
}

Плохо только, что при бинарном вводе-выводе приходится приводить типы.

Last edited by Alien (15-06-2010 07:27)

Offline

#6 15-06-2010 11:14

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Не, у listener'a код компактнее smile

Offline

#7 25-09-2010 19:04

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

while (fread(&c, sizeof(char), 1, f))
{
	ShowMessage(c);
}
fclose (f);

Файл открывается, но вылазят каракули (по 1 штуке). Как прочитать в CHAR по букве?

Offline

#8 25-09-2010 19:36

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Запись в двоичные файлы

а вообще, компиляторы с++ много лишнего лепят))) тут чистого си за глаза хватит :-D


GIMS developer

Offline

#9 25-09-2010 21:16

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Да, единственное полезное - try-catch. Хотя и то головняк, можно было бы вместо throw возвращать объект класса Error или что-то вроде того.
[large]Вопрос всё ещё открыт.[/large]

Last edited by ~AquaZ~ (25-09-2010 21:18)

Offline

#10 25-09-2010 23:42

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Запись в двоичные файлы

@~AquaZ~ - Сформулируй четко, что тебе нужно.
Такого не хватит?

while ( (int c = fgetc (f) != EOF) putc (c, stdout);

А что касается try/catch...  Возвращать объект Error откуда и куда?
Типичный пример (не забываем, что при обработке throw нужно вызвать дестукторы obj1_1, obj1_2, obj2 и obj3).

void a (Object1& obj1, Object2& obj2) {
  Object3 obj3;
  throw SomeError();
} 

void b (Object1& obj1) {
  Object2 obj2;
  a (obj1, obj2)
}

void c () {
  Object1 obj1_1;
  Object1 obj1_2;
  b (obj1);
  b (obj2);
}

void d () {
  try { 
   c ();
  } catch (SomeError e) {
    // do something
  }
}

Offline

#11 26-09-2010 06:55

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Сформулируй четко, что тебе нужно.

В цикле прочитать файл по одному знаку.

Offline

#12 26-09-2010 07:14

Alien
Registered: 12-10-2008
Posts: 564

Re: Запись в двоичные файлы

listener wrote:
void d () {
  try { 
   d ();
  } catch (SomeError e) {
    // do something
  }
}

Через пару секунд рекурсивных вызовов возникнет ошибка stack-overflow, а не SomeError.:D
~AquaZ~, в unicode попробуй считать. И убедись, что открываешь файл в текстовом режиме. В некоторых кодировках в начало файла добавляется идентификатор этой кодировки. Например, файл в кодировке UTF-8 будет всегда начинаться с байтов EF BB BF. Вот тебе и каракули.=)

Offline

#13 26-09-2010 15:44

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Запись в двоичные файлы

@~AquaZ~ - Если файл обычный текстовый, то приведенной строчки должно хватить.
(она читает файл посимвольно и выводит на экран)
Для юникодных, в MSVC можно указать fopen_s флаги автотрансляции кодировки.

@Alien - угу. опечатался. c(), конечно.

Offline

#14 26-09-2010 18:21

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

while (char с = fgetc(f) != EOF)
{
	ShowMessage(c);
}

[BCC32 Error] Unit1.cpp(36): E2451 Undefined symbol 'c'

Offline

#15 26-09-2010 20:56

Sanchez
Registered: 18-08-2006
Posts: 280

Re: Запись в двоичные файлы

~AquaZ~ wrote:

В цикле прочитать файл по одному знаку.

#include <iostream>
#include <fstream>
using namespace std;

int main (int argc, char *argv[])
{
	char ch;
	
	if (argc != 2)
	{
		cout << "Usage: <filename>\n";
		return 1;
	}
	
	ifstream in(argv[1], ios::in | ios::binary);
	if (!in)
	{
		cout << "Cannot open file.\n";
		return 1;
	}
	
	while (in.get(ch))
		cout << ch;
	
	in.close();
	
	return 0;
}

Offline

#16 26-09-2010 21:41

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Как-то по-древнему смотрится...

Offline

#17 27-09-2010 07:18

Alien
Registered: 12-10-2008
Posts: 564

Re: Запись в двоичные файлы

Классический C++. В том виде, в каком он был в середине 80-х. Код listener'а еще древнее - прямиком из 70-х.:lol:

Offline

#18 27-09-2010 12:17

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Запись в двоичные файлы

@~AquaZ~ - вынеси объявление c. И скобки не забывай: если я правильно помню, у сравнения приоритет выше, чем у присваивания.

Offline

#19 04-10-2010 04:16

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

Хы, опять я. А как побитово прочитать файл?

Offline

#20 10-10-2010 07:02

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Запись в двоичные файлы

ЫЫЫ, есть тут кто? Кто-нибудь знает, как прочитать файл побитово?

Offline

#21 10-10-2010 17:01

Alien
Registered: 12-10-2008
Posts: 564

Re: Запись в двоичные файлы

ты чего пургу несешь? Даже в аппаратной части фигурируют многобитные шины данных и всякое такое. Машина за раз читает байт/слово/двойное слово и т.д. Что уж говорить о программной части, в которой биты обрабатываются только как части битфилдов.
А вообще, большие объемы данных рекомендуется считывать с диска частями размером в сегмент файловой системы. Для NTFS - 4 КБ, для CDFS - 2 КБ...

Offline

Board footer

Powered by FluxBB