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

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

WritePrivateProfileString

Visual C++で、 unsigned char*型の変数を、一旦ファイルに保存しておいて、 後にそれを読み込んで使用する、ということをしたいのですが、 GetPrivateProfileStringとWritePrivateProfileStringを利用しようと考えました。 具体的にはPC-OP-RS1という製品を使った、 テレビのリモコンプログラムなんですが、 このデバイスの操作APIが、 赤外線信号をunsigned char*型で受け取ります。 これをファイルに記述しておいて、 好きなときに呼び出したいのですが、 前述の2つの関数は、 渡せる方がLPCTSTR型となっていますが、これがよくわかりません。 どうすれば実現できるでしょうか? 別の方法を取ったほうがいいでしょうか?

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

  • ベストアンサー
回答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% (2177/4070)
回答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% (2177/4070)
回答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); としてみたら文字化けしました。 これってバイト列を受信しているからなんでしょうか?

関連するQ&A

  • UNICODE化のための書き換え

    お世話になります。 Visual stdio 2010 C++で作成しております。 以前までは、UNICODEを意識しておらず、  char  const unsigned char* を使用していました。 UNICODE化を意識して  char→TCHAR に変更しているのですが、  const unsigned char* はどのように書き換えればよいのでしょうか? ※LPCTSTRだけだと意味が変わってしまう気がして。。。 お手数ですがよろしくお願い致します。

  • iniファイルに追記がしたいです。

     いつもお世話になっています。  iniファイルの中のあるデータをGetPrivateProfileStringで調べて、その中になければデータを  追記したいです。  WritePrivateProfileStringの場合、iniファイルにあるデータが追記したい内容がないだけで、他のデータが 入っていても、上書きされてしまうんですよね?  もしその中に他のデータが入っていた場合は、追記をしたいのですが、それができるAPI関数って  何かありますか?  iniファイルに関して、ネットで調べていると、WritePrivateProfileStringなどしか出てこなくて・・・。  もしできないようでしたら、追記できるような何かいいアイディアがあれば・・・と思っています。  すみませんが、よろしくお願いします。  わかりづらい文章で申し訳ありません。

  • C言語でPGMファイルの読み込みたいです。

    Visual C++ 6.0でPGM画像を読み込みたいのですが、ファイルの読み込みがわかりません。 コメント行は読み飛ばして以下の変数・配列にそれぞれ格納したいです。 int w,h //画像サイズ unsigned char img[][] //画像データ

  • TextBoxの文字がかけてしまうのですが VB.NET

    VB.NET FrameWork1.1の環境なのですが、 Declare Function WritePrivateProfileString Lib "KERNEL32.DLL" Alias "WritePrivateProfileStringA" ( _ ByVal lpAppName As String, _ ByVal lpKeyName As String, _ ByVal lpString As String, _ ByVal lpFileName As String) As Integer このAPIを使ってファイルに文字列を記録しているのですが、 TextBoxに表示したファイルのフルパスを記録すると このAPIを使った直後にそのTextBoxの文字の後半が欠けてしまいます。 短いパス名なら大丈夫なのですが、長いパス名の場合に欠けてしまいます。 試しに Dim a As String = TextBox1.Text WritePrivateProfileString("TextBox", "1", a, FileName) Console.WriteLine(a) としても同じく欠けてしまいます。 変数aの宣言の型をString ではなく Object にすると 欠けなくなるのですが、変数aやTextBoxの内容は読み取った だけなのになぜ書き換えられてしまうのでしょうか? どの場合でもファイルへの記録は正常に出来ています。 何か問題点などありましたらご教授いただけると助かります。

  • 変数格納

    C言語で、SJISのテキストファイルを読み出してunsigned charなどの変数に格納するにはソースをどのようにすれば出来ますか?テキストファイルの中には、改行、スペース、Tabなどがあります。

  • icon format について

    Visual Studio.NET 2003 MFC を使用しています。 View画面で、アイコンを表示しようと思いました。 アイコン読み込みようのクラスを作成しました。 class icon { public: void IconHeadRead(FILE *fp,int *width,int *height) { unsigned char uc; unsigned short us; unsigned int ui; fread(&us,sizeof(unsigned short),1,fp); fread(&us,sizeof(unsigned short),1,fp); fread(&us,sizeof(unsigned short),1,fp); fread(&uc,sizeof(unsigned char),1,fp);*width=uc; fread(&uc,sizeof(unsigned char),1,fp);*height=uc; fread(&uc,sizeof(unsigned char),1,fp); fread(&uc,sizeof(unsigned char),1,fp); fread(&us,sizeof(unsigned short),1,fp); fread(&us,sizeof(unsigned short),1,fp); fread(&ui,sizeof(unsigned int),1,fp); }; void IconDataRead(FILE *fp,unsigned char *red,unsigned char *green,unsigned char *blue) { unsigned char uc; fread(&uc,sizeof(unsigned char),1,fp);*red=uc; fread(&uc,sizeof(unsigned char),1,fp);*green=uc; fread(&uc,sizeof(unsigned char),1,fp);*blue=uc; }; }; このred,green,blueの値を使用して、 SetPixelでドローしようと思いましたが、 変な表示になります。 width,heightは、正しいようです。 ICON フォーマットについて教えてください。 よろしくお願いします。 同じような要領で、bitmapは保存、読み込みはできました。

  • wParam

    wParamは、unsigned int型で、仮想キーコードを、格納してますよね。 wsprintf()内で(TCHAR)キャストしてますが、 これは、変数strの型がTCHAR型なので(wParamは、unsigned intなので型をあわせるために)やっているんですか? (TCHAR)キャストしないとエラーになりますか?教えてください。 HDC hdc; TCHAR str[255]; swich(umsg){   case WM_CHAR:     wsprintf( str, TEXT("%c"), (TCHAR)wPara );     hdc = GetDC(hwnd);     TextOut(hdc, 0, 0, str, lstrlen(str));     return0 }

  • OCXのメソッドの引数に文字列を返したい

    こんにちは。いつもお世話になっております。 早速ですが質問させて下さい。 VisualC++のClassWizardにて作成したメソッドの引数に文字列を返したいのですがどうすればよいでしょうか。 例えば、「test.ocx」というOCXにGetFileNameというメソッドを追加したとします。 ---<GetFileName>--- UINT GetFileName( LPCTSTR FilePath, //ファイルフルパス LPCTSTR FileName //ファイル名 ) ------------------- ---<VBからの呼び出し>--- FilePath = "C:\Program Files\test.txt" ret = obj.GetFileName(FilePath, FileName) 'ここでFileNameに値を返したい ------------------------ ここでFileNameにOCXから値を返すようにしたいのですが、型(ClassWizardパラメータリストの「タイプ」)は何になるのでしょうか。 数値を返す場合は、「long*」でできたのですが、 文字列を返す方法が分かりません。(「LPCTSTR*」というのもないですし) どうかご教示下さい。 <環境> Windows 2000, Visual C++ 6.0, Visual Basic 6.0

  • WM_CHAR or WM_KEYDOWN の「wParam」について

    よくわかっていないのですが、 switch (message) { case WM_CHAR: というところで、wParamから、文字の情報取得して、 HDC宣言して、TextOut関数使用…、の途中で、 wParamの文字情報は、どのようにすれば TextOut関数に渡せるのでしょうか? Visual C++を勉強したてで、勉強の成果をと思い、 テキストエディタを作ってみたいと思ったのですが、 さて、どうしたらよいのでしょうか? エラー内容は、unsigned int → const char * にできません、ということなのですが、 じゃぁ、型の変換の仕方は?という感じです。 初心者なので、簡単な例をつけて説明してくださると助かります。よろしくお願いします。

  • templateをシリアライズするには?

    templateで作った変数をシリアライズする方法がわからなくて困っています。 例えばhogehogeという変数を用意します。これはtemplateで hogehoge<TYPE>として、型はint、double、char[]、wchar_t[] のいづれかを取れるようにします。 この変数hogehogeをシリアライズしてファイルに保存したいのです。 シリアライズするには、int又はCObject*又はCString型にいったん キャストしてからシリアライズすることになると思うのですが ここで、hogehogeという変数がどの型になっても問題なくシリアラ イズできるようにするにはどうしたらいいのでしょうか?