ファイルにバイナリで書き込めない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Iseuma14
記事: 54
登録日時: 8年前

ファイルにバイナリで書き込めない

#1

投稿記事 by Iseuma14 » 7年前

ロベールのC++様(http://www7b.biglobe.ne.jp/~robe/cpphtml/index.html)の2部の11章にの上部にあるプログラムに目を通し、クラスを使ったプログラムの練習として自分の考えた組み方で作ってみたのですが、ファイルに書き込みをするとなぜかバイナリではなく、通常のテキストとして保存されてしまいます。 これは拡張子を.txt、.bin両方にして試してみましたがうまくいきませんでした
以下コードです

コード:

//template.h
#ifndef INCLUDE_TEMPLATE
#define INCLUDE_TEMPLATE

template <typename T>
T numof(T* hoge)
{
	return sizeof(hoge)/sizeof(hoge[0]);
}
#endif

//file.h
#ifndef INCLUDE_FILE
#define INCLUDE_FILE
#include <stdio.h>

class Cfile
{
	private:
		FILE *fp;
		char output[256];
		char input[256];
		bool copy;
		bool modefyflags(const char* psSource,char* psDest,int nsize);
	public:
		Cfile();
		Cfile(const Cfile& rother);
		~Cfile();
		bool Open(const char* ps_file,const char* pz_flag);
		void Close();
		void Read();
		void Write();
		inline bool Cfile::Valid() const //fpが有効か
		{
			return fp != NULL;
		}
};
#endif

//file.cpp
#include<stdio.h>
#include<string.h>
#include"file.h"
#include"template.h"

Cfile::Cfile()
{
	memset(input,(int)'\0',sizeof(input));
	memset(output,(int)'\0',sizeof(output));
	fp = NULL;
	copy = false;
}

Cfile::Cfile(const Cfile& rother)
{
	fp = rother.fp;
	copy = true;
}

Cfile::~Cfile()
{
	if(copy == false)
		Close();
}

bool Cfile::Open(const char* ps_file,const char* ps_flag)
{
	Close();
	char buf_flag[8];
	if(modefyflags(ps_flag,buf_flag,numof(buf_flag)) == false)
		return false;

	fp = fopen(ps_file,ps_flag);
	return (fp != NULL);
}

void Cfile::Close()
{
	if(Valid() == true)
	{
		fclose(fp);
	}
}

bool Cfile::modefyflags(const char* psSource,char* psDest,int nsize)
{
	bool binary;
	binary = (strchr(psSource,'b') != NULL);	//フラグpsSoruceがバイナリ指定ならbinaryにtrueを代入

	if((int)strlen(psSource) > nsize - 1 - !binary)
		return false;

	strcpy(psDest,psSource);
	if(binary == false)
		strcat(psDest,"b");
	return true;
}

void Cfile::Read()
{
	if(Valid() == false)
	{
		printf("ファイルを開いてから行ってください");
		return;
	}
	fread(output,1,256,fp);
	printf("%s\n",output);
}

void Cfile::Write()
{
	if(Valid() == false)
	{
		printf("ファイルを開いてから行ってください");
		return;
	}
	int size = 0;
	printf("書き込む文字を入力");
	scanf("%s",input);
	int i;
	for(i=0;input[i]!='\0';i++)
	{
		size++;
	}
	fwrite(input,1,(size_t)size,fp);
}

//main.cpp
#include<stdio.h>
#include"file.h"

int main()
{
	Cfile file;
	char name[32];
	int mode;
	printf("開きたいファイルを選択\n");
	scanf("%s",name);
	printf("何をなさいますか?\n1,書き込み\n2,読み込み\n");
	scanf("%d",&mode);
	if(mode == 1)
	{
		file.Open(name,"wb");
		file.Write();
	}
	else if(mode == 2)
	{
		file.Open(name,"rb");
		file.Read();
	}
	else
		printf("1か2でお願いします\n");
	return 0;
}
初歩的な質問かもしれませんがよろしくお願いします

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: ファイルにバイナリで書き込めない

#2

投稿記事 by みけCAT » 7年前

テキストファイルはバイナリファイルの一種であり、%sでは「普通の環境」でモードの影響を受けるような制御文字(改行文字)は入力されないはずですが、
Iseuma14さんのいう「バイナリ」とは何ですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#3

投稿記事 by Iseuma14 » 7年前

>>みけCAT様
ご回答ありがとうございます

私の頭の中のイメージではバイナリで書き込むと、
http://www016.upp.so-net.ne.jp/no-opera ... m_009.html
上記サイトの画像にあるようなメモ帳で開くとよくわからない文字が立ち並んだり、中身は二進数で、バイナリエディターを使い、16進ダンプで表示して中身を確認するようなファイルが生成されると考えていたのですがこの認識は誤りということでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: ファイルにバイナリで書き込めない

#4

投稿記事 by みけCAT » 7年前

Iseuma14 さんが書きました:私の頭の中のイメージではバイナリで書き込むと、
http://www016.upp.so-net.ne.jp/no-opera ... m_009.html
上記サイトの画像にあるようなメモ帳で開くとよくわからない文字が立ち並んだり、中身は二進数で、バイナリエディターを使い、16進ダンプで表示して中身を確認するようなファイルが生成されると考えていたのですがこの認識は誤りということでしょうか?
はい、誤りですね。
メモ帳で読み込んだ時に人間にとって意味があるデータになるかは、もちろんファイルの内容によります。
バイナリモードにしたからといって勝手に暗号化などがかかるわけでは(少なくとも「普通」の処理系では)ないでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#5

投稿記事 by Iseuma14 » 7年前

>>みけCAT様
なるほど ということは今回の様にただバイナリモードで開いてfwriteで書き込んでも通常のテキストとして書き込まれてしまうというわけですか

となりますと、バイナリモードで開くというのは何のためにあるのでしょうか
私が頭の中で想定していたようなファイルには二進数で書き込まれているという状態を作るためにはこれとは別で文字列を二進数に変換する部分が必要になるのでしょうか?
ファイル関係でそんなサンプルコード見たことないので違う感じは薄々感じているのですが…
何度も申し訳ございません

かずま

Re: ファイルにバイナリで書き込めない

#6

投稿記事 by かずま » 7年前

Iseuma14 さんが書きました:となりますと、バイナリモードで開くというのは何のためにあるのでしょうか
私が頭の中で想定していたようなファイルには二進数で書き込まれているという状態を作るためにはこれとは別で文字列を二進数に変換する部分が必要になるのでしょうか?
C のプログラム中での改行コードは '\n' すなわち 0x0a ですが、
Windows のテキストファイルの改行コードは CR LF すなわち 0x0d 0x0a です。
VC++ でコンパイルしたプログラムで、バイナリモードで fopen したファイルに
fwrite("abc\n", 1, 4, fp); で書き込むと、61 62 63 0a となりますが、
テキストモードで fopenしたファイルだと、61 62 63 0d 0a となります。
fread では、逆の変換が行われます。

プログラム中のメモリーイメージのデータをそのままファイルに書き込む場合、
勝手に値やバイト数が変更されないようにバイナリモードでオープンします。

61 62 63 0d 0a というのは 16進で書きましたが、もちろんファイルの中では
01100001 01100010 01100011 00001101 00001010 という 2進(バイナリ)です。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: ファイルにバイナリで書き込めない

#7

投稿記事 by みけCAT » 7年前

Iseuma14 さんが書きました:私が頭の中で想定していたようなファイルには二進数で書き込まれているという状態を作るためにはこれとは別で文字列を二進数に変換する部分が必要になるのでしょうか?
テキストエディタで読めるデータを書き込むから、テキストエディタで読めるのです。
とりあえず乱数でも書き込んでみてはいかがですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#8

投稿記事 by Iseuma14 » 7年前

>>かずま様
ご回答ありがとうございます
VC++ でコンパイルしたプログラムで、バイナリモードで fopen したファイルに
fwrite("abc\n", 1, 4, fp); で書き込むと、61 62 63 0a となりますが、
テキストモードで fopenしたファイルだと、61 62 63 0d 0a となります。
私の上記プログラムでも(私の中では)かずま様のご提示していただいたような感じに
なると考えて組んだつもりだったのですが、なぜバイナリモードで開いているにも関わらず、
書き込まれたファイルを覗くと中身はabcとそのままの数値です

改善すべき点のヒントや指摘をいただけると嬉しいです

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#9

投稿記事 by Iseuma14 » 7年前

>>みけCAT様
テキストエディタで読めるデータを書き込むから、テキストエディタで読めるのです。
とりあえず乱数でも書き込んでみてはいかがですか?
理解が及ばず非常に申し訳ないのですが、乱数というのは普通に適当な数値ということでしょうか?
やってみた所結果は変わらずだったのでなんとなく違うというのは感じておりますが

テキストエディタで読めるデータとはどういうことでしょうか?
ファイル書き込みで通常の数値や文字列をバイナリモードで入力しても結果は変わらないということでしょうか?

何度も質問申し訳ないです

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ファイルにバイナリで書き込めない

#10

投稿記事 by MoNoQLoREATOR » 7年前

まず、これを実行してみてください。バイナリファイルが作成されます。

コード:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
	// まず、適当なバイナリデータを作る
	static const int qty_rand = 30;
	int rands[qty_rand];
	for (int i = 0; i < qty_rand; ++i)
	{
		rands[i] = rand();
	}

	//それをファイルに保存する
	FILE * fp = fopen("binary.txt", "wb");
	if (fp == NULL)
	{
		printf("ファイルを開けませんでした\n");
		return -1;
	}
	fwrite(rands, sizeof(int), qty_rand, fp);
	fclose(fp);
	printf("たぶん、正常にファイルが書き出されました\n");

	return 0;
}
そして、作成されたbinary.txtファイルをテキストエディタで開いてみてください。
おそらくIseuma14さんはこんな感じのものを作りたかったのではないでしょうか。

説明に入ります。

まず、拡張子とファイルの形式は全く関係ありません。
ためしにmp4とかをtxtに変えてみてください。
テキストエディタで開いても意味不明な文字の羅列が見えるだけです。
そのファイルをWindows Media Playerにドラッグ&ドロップすると普通に動画が再生されます。

次に、バイナリファイルとテキストファイルの違いについて。
テキストファイルはバイナリファイルの一種です。
コンピューターが取り扱うファイルは全てバイナリファイルです。
その中で、人間が読める文字データのみによって構成されたファイルをテキストファイルと呼びます。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ファイルにバイナリで書き込めない

#11

投稿記事 by MoNoQLoREATOR » 7年前

追伸です。

おそらくなのですが、Iseuma14さんは
abcd というのがテキストデータ
61 62 63 64 というのがバイナリデータ
そしてfopenのときテキストモードやバイナリモードを切り替えることによってそれを変換できる
と考えていらっしゃるのではないでしょうか。(違っていたらすみません)

しかしそれはちょっと違います。
abcdという情報はコンピュータの中では61 62 63 64というデータとして扱われています。
つまりこのときメモリの状態は
00111101 00111110 00111111 01000000
となっています。
これを、例えばメモ帳というソフトウェアがabcdだと認識して画面にabcdという文字を表示しているだけなのです。
2進数で表示するバイナリエディタの場合はこのデータを認識して画面に00111101 00111110 00111111 01000000という文字を表示します。
16進数で表示するバイナリエディタの場合はこのデータを認識して画面に61 62 63 64という文字を表示します。
HDD等に保存されるときも00111101 00111110 00111111 01000000というデータが保存されるだけです。

かずま

Re: ファイルにバイナリで書き込めない

#12

投稿記事 by かずま » 7年前

MoNoQLoREATOR さんが書きました:16進数で表示するバイナリエディタの場合はこのデータを認識して画面に61 62 63 64という文字を表示します。
HDD等に保存されるときも00111101 00111110 00111111 01000000というデータが保存されるだけです。
10進と 16進がこんがらがっているようですが。

コード:

文字   2進    16進  10進
'='  00111101  3d    61
'>'  00111110  3e    62
'?'  00111111  3f    63
'@'  01000000  40    64

'a'  01100001  61    97
'b'  01100010  62    98
'c'  01100011  63    99
'd'  01100100  64   100
Iseuma14さんへ、

fopen のテキストモード("r"/"w")とバイナリモード("rb"/"wb")と、
ファイルのテキストファイルとバイナリファイルとは独立です。

通常は、テキストファイルはテキストモードでオープンし、
バイナリファイルはバイナリモードでオープンしますが、
テキストファイルををバイナリモードでオープンすることも、その反対もできます。

バイナリモードでは、バイト列を何も変換せずに読み書きしますが、
テキストモードでは、改行コードの変換や、入力の EOFコード(0x1A)の認識を行って、
ファイル上のバイト列と、メモリ中のバイト列が同じにならないことがあるということです。

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#13

投稿記事 by Iseuma14 » 7年前

>>かずま様
なるほど、いろいろなサイト様に書かれていたバイナリモードでテキストファイルを開くと
開業などに問題が生じると書かれていたのはこういうことなのですね
ありがとうございます 

Iseuma14
記事: 54
登録日時: 8年前

Re: ファイルにバイナリで書き込めない

#14

投稿記事 by Iseuma14 » 7年前

>>MoNoQLoREATOR様、ご回答ありがとうございます
おそらくなのですが、Iseuma14さんは
abcd というのがテキストデータ
61 62 63 64 というのがバイナリデータ
そしてfopenのときテキストモードやバイナリモードを切り替えることによってそれを変換できる
と考えていらっしゃるのではないでしょうか。(違っていたらすみません)

しかしそれはちょっと違います。
abcdという情報はコンピュータの中では61 62 63 64というデータとして扱われています。
つまりこのときメモリの状態は
00111101 00111110 00111111 01000000
となっています。
これを、例えばメモ帳というソフトウェアがabcdだと認識して画面にabcdという文字を表示しているだけなのです。
2進数で表示するバイナリエディタの場合はこのデータを認識して画面に00111101 00111110 00111111 01000000という文字を表示します。
16進数で表示するバイナリエディタの場合はこのデータを認識して画面に61 62 63 64という文字を表示します。
まさにこの通りでございました
サンプルコードの下に16進数で書かれた実行結果が書かれており、
バイナリモードで書きこむと16進数で書き込まれるものだと勘違いしておりました

皆様、ご回答ありがとうございました
精進します

閉鎖

“C言語何でも質問掲示板” へ戻る