
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」を今後見る人のためにも)
「独自のバイナリ形式のファイル入出力の方法」とか何とかの名前つけて
別途質問を立ててそっちで
「とりあえずこんな感じでやってみたのですが、これこれこうなってうまくいきません」
とか
「一応出来てることはできていますが、もっといい方法はありますでしょうか?」
などの形跡などを書きつつ質問をしていただければ
その時時間があれば、私も答えてみましょう。
何から何まで面倒みていただいてありがとうございました。
そうですね、
今回の初めの質問内容から逸脱しすぎました。
他の方の少しでも参考になるように、
この辺りでやめておきます。
また機会があればよろしくお願いします。
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と思いますが
以上の内容を踏まえてまだ出来ない場合は教えてください。
この回答への補足
何度も詳しくありがとうございます。
ほんとに助かります。
無事取り出すことが出来るようになりました。
ついで、というとあれですが、
もうひとつ質問させていただいてもよろしいでしょうか?
実は、
このようなバイナリ列を、
複数(5つくらい)プログラム内で書き込み、読み込みする必要があるのですが、
一つのファイルに5つ書きこんで、順番に読み込むにはどうしたらいいでしょうか?
具体的には5つの変数を用意して、
それぞれに対応したバイナリーデータをファイルから読み込んで格納する、
といったことをしたいです。
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 );
正しくはこんな感じかな。
この回答への補足
皆様回答ありがとうございます。
早速以下のようにプログラムをかきなおしてみました。
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_sam …
データ列の詳しいフォーマットの情報はまだ発見していませんが
単一の文字列とは思えません。
無理やり文字列にキャストして…というのも不可能ではないですが
この場合は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
となっていますね。
No.1
- 回答日時:
>Visual C++で、
バージョンはなんですか?
あるいは、使用している文字セットは?
「マルチ バイト文字セットを使用する」か「Unicode 文字セットを使用する」か……
>このデバイスの操作APIが、
>赤外線信号をunsigned char*型で受け取ります。
「文字列」として受け取れるのですか?
「バイト列」だった場合は、そのままではiniファイルには書き込み出来ませんが。
>渡せる方がLPCTSTR型となっていますが、これがよくわかりません。
入っているのが文字列で文字セットが適切であればキャストして渡すような感じになります。
デバイスから受け取るのがunsigned char*であれば…文字セットは「マルチバイト」の方になるかと思いますけど。
バイト列なら先に書いた通り無理です。
# バイト列を16進文字列で文字とすれば可能でしょう。変換の手間(とコスト)が掛かりますが。
バイト列ならfwrite/fread(あるいはWriteFile/ReadFileなどのAPI)で読み書きとした方が楽…でしょうね。
# 人間が見たい場合は面倒でしょうけど。
この回答への補足
2010で「マルチ バイト文字セットを使用する」になっています。
http://1c3.world.coocan.jp/wiki/index.php?%A5%B3 …
こちらのページで公開されているAPIを使っているのですが、
試しに
unsigned char *signal;
Receive(signal); //APIの関数
printf("%s\n",signal);
としてみたら文字化けしました。
これってバイト列を受信しているからなんでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 共用体について コマンドライン引数で値を2つ入力したときに、argv[2]の値をUNI u1 4 2022/04/25 20:34
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- C言語・C++・C# C言語について コマンドラインで >変数 12.00 (char型) と、小数点付きの値を共用体に渡 1 2022/04/22 16:56
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- その他(プログラミング・Web制作) Windowsのマクロプログラムで、こんなことできますか? 3 2022/06/28 14:30
- Excel(エクセル) EXCELマクロでandroidタブレットから取りんだJPEGファイルをうまくセルに貼り付けられない 2 2022/07/31 15:03
- ノートパソコン ハードディスクが壊れたPCのオークションへの出品の仕方を教えてください 9 2022/11/16 08:13
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- ドライブ・ストレージ 古い外付けHDDから新品外付けHDDへのデータ移行方法 (Mac) 2 2022/12/11 02:01
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fstream型オブジェクトを関数の...
-
C言語にて構造体のメンバがNULL...
-
CStringからchar*への型変換に...
-
fread()関数とfwrite()関数につ...
-
new charとnew char[N]の違いは?
-
全体をNULLクリアするより、最...
-
char型にint型の数値を代入する。
-
C言語のintとcharの違いってな...
-
小数点入りの文字列をfloat型に...
-
文字列置換のアルゴリズムを教...
-
'\\0'とはなんですか?
-
動的メモリの初期化方法について。
-
コマンドライン引数 *argv[]は...
-
csvファイルを構造体に格納した...
-
C++17で、unsigned char * 配列...
-
C言語を用いた環境変数の作成/...
-
C言語 配列の長さの上限
-
関数から配列を返すには?
-
Run-Time Check Failure #3とい...
-
先頭アドレスとは何ですか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
char型にint型の数値を代入する。
-
C言語にて構造体のメンバがNULL...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
C++17で、unsigned char * 配列...
-
DWORDとcharの変換
-
文字列内の数字削除
-
new charとnew char[N]の違いは?
-
文字型配列に格納した空白の切捨て
-
C++Builder 2009 テキスト...
-
csvファイルをfscanfで読み込む...
-
文字列の途中から途中までを抽出
-
[C] 構造体メンバーのカンマ区...
-
エクセルのMID関数は、C言語では?
-
小数点入りの文字列をfloat型に...
-
wsprintf( ポインタ , "%d" , "...
おすすめ情報