• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:WritePrivateProfileString)

Visual C++でunsigned char*型の変数をファイルに保存する方法

このQ&Aのポイント
  • Visual C++で、unsigned char*型の変数を一旦ファイルに保存し、後にそれを読み込んで使用する方法を知りたいです。
  • テレビのリモコンプログラムでPC-OP-RS1を使って赤外線信号をunsigned char*型で受け取ります。この変数をファイルに保存し、必要な時に読み込んで使用したいです。
  • GetPrivateProfileStringとWritePrivateProfileString関数を利用する方法が考えられますが、渡せる型がLPCTSTRなのでunsigned char*型を渡す方法が分かりません。別の方法があれば教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.6

今回は最初「文字列かな」と思って書いたところから始まったのであれですが 「数個程度のデータ」が詰まったバイナリのfileout, fileinを扱うとハッキリ分かっているなら 実際には私だったらfopen_s,fwrite,fcloseあたりで手軽に済ませる可能性が高いです。 これを応用していけば市販アプリでよくあるような「独自の巨大なファイル形式」の作成もできます。 巨大なファイルになる場合は、私は読み取り時は少なくとも「メモリマップドファイル」をお勧めします。ファイルシークは時間ががかりますので。 参考 ・ファイルをメモリのように「メモリマップドファイルクラス」 http://marupeke296.com/DXCLS_MemoryMappedFile.html その場合はどっかにファイルの構成(仕様)が分かるような仕様書をメモしておくと後々楽です。(経験談) めちゃめちゃ本格的なことを追求していえば コンストラクタが絡むと「例外安全」という問題が若干無視できなくなるのと (現状ではstd::ofstreamやstd::istreamの仕様に依存することになる) char*にキャストしているのが「美しくない」という印象もあるので まぁその辺を自分でラッパークラス作っちゃって、内部で何使ってようが、書き変えたくなったら呼び出し側はノータッチで後で簡単に変えられるように出来るのがC++の本当の良さですが。 「WritePrivateProfileString」という題名で 独自バイナリファイルの入出力の話が出てるとは 普通は考えにくいでしょうから(「教えてgoo」を今後見る人のためにも) 「独自のバイナリ形式のファイル入出力の方法」とか何とかの名前つけて 別途質問を立ててそっちで 「とりあえずこんな感じでやってみたのですが、これこれこうなってうまくいきません」 とか 「一応出来てることはできていますが、もっといい方法はありますでしょうか?」 などの形跡などを書きつつ質問をしていただければ その時時間があれば、私も答えてみましょう。

cubicroot
質問者

お礼

何から何まで面倒みていただいてありがとうございました。 そうですね、 今回の初めの質問内容から逸脱しすぎました。 他の方の少しでも参考になるように、 この辺りでやめておきます。 また機会があればよろしくお願いします。

その他の回答 (5)

回答No.5

大抵のライブラリって outだったらinがあり writeだったreadがあるものです。 なので、とりあえずおんなじよ~にかいて見てください unsigned char *data2; data2 = (unsigned char*)malloc(240); std::ifstream ifs("binary.dat",std::ios::binary); ifs >> data2; のとこを unsigned char *data2; data2 = (unsigned char*)malloc(240); std::ifstream ifs("binary.dat",std::ios::binary); ifs.read( (char*)data2, 240 ); 一応、省略されてるだけだろうとは思いますが mallocで確保した場合は、データを使い終わってから freeで解放することを忘れないでください。 free( data2 ); //その後data2ポインタを使いまわす場合はdata2 = NULL;としておくのが推奨 この場合はたった240バイト固定、ということで 環境にもよりますが、大抵は unsigned char data2[240]; とローカル変数にしてしまっても全然OKと思いますが 以上の内容を踏まえてまだ出来ない場合は教えてください。

cubicroot
質問者

補足

何度も詳しくありがとうございます。 ほんとに助かります。 無事取り出すことが出来るようになりました。 ついで、というとあれですが、 もうひとつ質問させていただいてもよろしいでしょうか? 実は、 このようなバイナリ列を、 複数(5つくらい)プログラム内で書き込み、読み込みする必要があるのですが、 一つのファイルに5つ書きこんで、順番に読み込むにはどうしたらいいでしょうか? 具体的には5つの変数を用意して、 それぞれに対応したバイナリーデータをファイルから読み込んで格納する、 といったことをしたいです。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.4

>unsigned char *signal; >Receive(signal);  //APIの関数 >printf("%s\n",signal); >としてみたら文字化けしました。 当たり前ですが、受信する前にsignalは有効な領域指しているんですよね? 普通ならこういう場合、ポインタと一緒に領域のサイズも渡すんですが… 今回は「240バイト固定」のバッファが指定されているのでサイズ情報の引き渡しはないのでしょう。 で……文字列じゃなくてバイト列…ですよね? No.2さんのリンク先見ると。 バイト列ならprintf()での表示は無理でしょう。 その他、細かいことは既に回答されているので……。 # もちろん、私ならこういう場合はふつ~にバイナリデータとして扱いますけどね。 # ファイルに落とした後でならバイナリエディタで眺めることもできますし。

回答No.3

おおっと、最初「文字列かな?」 と思って書いたstd::ofstreamのまま修正してませんでしたね unsigned char buff[240]; //データ受け取り std::ofstream of("test.dat", std::ios::binary); of.write((char*)buff, 240 ); 正しくはこんな感じかな。

cubicroot
質問者

補足

皆様回答ありがとうございます。 早速以下のようにプログラムをかきなおしてみました。 unsigned char *data; data = (unsigned char*)malloc(240); //dataに受信データを書き込む std::ofstream of("binary.dat",std::ios::binary); of.write((char*)data,240); of.close(); unsigned char *data2; data2 = (unsigned char*)malloc(240); std::ifstream ifs("binary.dat",std::ios::binary); ifs >> data2; //data2を送信 しかしこれだと正しい信号が送信できていないようです。 ちなみに、当たり前ですが、data2ではなくdataを送信すると正常に動作します。 どうしたらいいでしょうか。

回答No.2

それってこんな感じのバイナリ列じゃないですか? http://netakiri.net/labo/ctrl_remote_station_sample.shtml データ列の詳しいフォーマットの情報はまだ発見していませんが 単一の文字列とは思えません。 無理やり文字列にキャストして…というのも不可能ではないですが この場合は240Bytesのバイナリをそのまま書きだしてしまった方が、ずっとコード的に分かりやすいと思います。 fopen_s → fwrite → fclose あるいは CreateFile → WriteFile → CloseHandle あるいはC++を使えるのなら #include <fstream> std::ofstream ofs( "ファイル名.txt" ); ofs << データ << std::endl; あるいはメモリマップドファイル などなど、方法は多岐にわたります。 なお、LPCTSTRやGetPrivateProfileStringなどの詳細について しっかり把握したい場合は、今後のためにもこちらを読んでおくことをお勧めします。 ・_T("")マクロだのL""マクロだのLPCTSTRだのの世界一詳しい解説 http://victreal.com/Junk/_T/index.html プロジェクトのプロパティ→構成プロパティ→全般→文字セット のところが「Unicode 文字セットを使用する」 の場合、 _T("abc")はL"abc"に置き換えられ(const wchar_t*) 「マルチ バイト文字セットを使用する」 の場合は _T("abc")は"abc"に置き換えられます(const char*) また、必要部分だけ抜粋すると LPCTSTRはwinNT.hでこのようになっているはずです。 #ifdef UNICODE typedef LPCWSTR PCTSTR, LPCTSTR; #else typedef LPCSTR PCTSTR, LPCTSTR, PCUTSTR, LPCUTSTR; #endif 「Unicode 文字セットを使用する」の場合は上のLPCWSTRと等価になります 「マルチ バイト文字セットを使用する」の場合は下のLPCSTRと等価になります LPCWSTRはconst WCHAR* LPCSTRはconst CHAR* と等価になり また WritePrivateProfileStringはwinbaseで #ifdef UNICODE #define WritePrivateProfileString WritePrivateProfileStringW #else #define WritePrivateProfileString WritePrivateProfileStringA #endif となっています。 WritePrivateProfileStringWの引数はLPCWSTR WritePrivateProfileStringAの引数はLPCSTR となっていますね。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.1

>Visual C++で、 バージョンはなんですか? あるいは、使用している文字セットは? 「マルチ バイト文字セットを使用する」か「Unicode 文字セットを使用する」か…… >このデバイスの操作APIが、 >赤外線信号をunsigned char*型で受け取ります。 「文字列」として受け取れるのですか? 「バイト列」だった場合は、そのままではiniファイルには書き込み出来ませんが。 >渡せる方がLPCTSTR型となっていますが、これがよくわかりません。 入っているのが文字列で文字セットが適切であればキャストして渡すような感じになります。 デバイスから受け取るのがunsigned char*であれば…文字セットは「マルチバイト」の方になるかと思いますけど。 バイト列なら先に書いた通り無理です。 # バイト列を16進文字列で文字とすれば可能でしょう。変換の手間(とコスト)が掛かりますが。 バイト列ならfwrite/fread(あるいはWriteFile/ReadFileなどのAPI)で読み書きとした方が楽…でしょうね。 # 人間が見たい場合は面倒でしょうけど。

cubicroot
質問者

補足

2010で「マルチ バイト文字セットを使用する」になっています。 http://1c3.world.coocan.jp/wiki/index.php?%A5%B3%A5%F3%A5%C8%A5%ED%A1%BC%A5%EBDLL%A4%F2%BA%EE%A4%ED%A4%A6#p92ca3d9 こちらのページで公開されているAPIを使っているのですが、 試しに unsigned char *signal; Receive(signal);  //APIの関数 printf("%s\n",signal); としてみたら文字化けしました。 これってバイト列を受信しているからなんでしょうか?