
No.9ベストアンサー
- 回答日時:
うーん。
それはC言語の基礎ですがC言語は文字列の終端に0をいれます。
buffer[wReadSize/sizeof(wchar_t)] = 0;
と同じことですか。
明示的にUNICODEのNULL文字 L'\0'としています。
別に文字列として扱わないなら必要ありません。
しかし今回は
MessageBox関数に使用する為、bufferを文字列として扱う必要がある為
NULL文字をいれました。
mallocでwReadSize + sizeof(wchar_t) としているのも
NULL文字をいれるため文字数+1文字しているのです。
どんな言語でもそうですが、文字列を扱うには2通りの方法があって
今回のように文字列の終端に終端を表すNULL文字をいれる仕組みと
最初に文字数があってその後ろに文字列がくる仕組みです。
でなければコンピューターはどこまでが文字列なのか判断出来ません。
>この部分ってUNICODEファイルを読むときで必ず必要でしょうか?
>保険のようものでしょうか?
つまりUNICODEかどうかは関係ありませんし保険でも無く
文字列として扱うなら必ず必要ということです。
ありがとうございました。
大変勉強になりました。
文字列の終端のことで気になったのは今回おそらく私のどっかのミスで余計な文字が
読み込まれたので、それをきるために、そのようにされたのかなと思いましたので
質問させていただきました。
解説ですっきりしました。
.NETから入ってnative系の戻るってともてつらいです。。。
.NETが基本的なところ全部やってくれますので。。。スキルが上がりませんね。
これから出てくるPGならもっと不幸かもしれません(ある意味でです)。
#私は.NETが優れていると思います。
No.8
- 回答日時:
HANDLE hFile = CreateFile( "text.txt", GENERIC_READ , 0 , NULL ,
OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL);
DWORD wReadSize = GetFileSize(hFile , NULL);
wchar_t* buffer = (wchar_t*)malloc( wReadSize + sizeof(wchar_t) );
DWORD dw;
ReadFile( hFile , buffer , wReadSize , &dw , NULL );
buffer[wReadSize/sizeof(wchar_t)] = L'\0';
::MessageBox( NULL , buffer , L"test" , MB_OK );
free(buffer);
CloseHandle(hFile);
そのまま回答書いてくださいましたね<(_ _)>
ファイル読めてますね。ありがとうございます。
> buffer[wReadSize/sizeof(wchar_t)] = L'\0';
この部分ってUNICODEファイルを読むときで必ず必要でしょうか?
ほかのコードのファイルでも必要?
それとも、余計なものを確保される可能があるので、保険のようものでしょうか?
No.7
- 回答日時:
開いているファイルのバイト数はいくつでしょうか。
可能であれば、ファイル内の各バイトの値も教えてください。プログラム内で使用している各変数に最終的に設定されている値と、ファイルを読み込んだ後のバッファ内の値はいくつでしょうか。(ハンドルの値、ポインタの値は不要です。)
この回答への補足
メモ帳でUNIOCDE保存したファイル
サイズ 6 バイト
内容 aあ
wReadSize 3
dw 6
です。
なにおわかりでしょうか?
すいません。
補足がもうできませんので、お礼のとこで^^
やっているうちに漢字が取れました。
ありがとうございます。
依然として余計な文字が読み込まれますが。。
各値も漏れてましたね。
aあ 以外の化けている値は以下です。
65021
65021
43947
43947
43947
43947
65262
もしかして、UNICODEの制御文字?
文字コードが理解できてません。。。
No.6
- 回答日時:
回答No.5の補足にあるコードですが、GetFileSizeが返す値は「バイト数」で、Unicode文字の文字数ではありません。
ですので、Unicode文字の文字数を得るにはsizeof(wchat_t)で割ってください。(注:ヘッダ込みの値になります。)この回答への補足
ご回答ありがとうございます。
なんとなくそんな気もしましたので、
テストとして固定で 2 を入れてもやってみたのです。
なんか、とくに結果がかわりませんで、そのまま
ほうっておきました。
おっしゃる通りですね。
それでも結果が変わらないのはなんででしょうか。。?
それと、余計な文字を読み込み以外にポインタ移動や
配列のインデックス指定で漢字が取れません。。
根本的に間違ってますでしょうか?
No.5
- 回答日時:
何を悩んでいるのかわかりませんが、
例えばテキスト文書が1000文字なら
wchar_t buffer[1000];
とでも用意してください。
(wchar_tはワイド文字の型です。U
NICODEを宣言しているならTCHARでも同じです。)
BOOL ReadFile(
HANDLE hFile, // ファイルのハンドル
LPVOID lpBuffer, // データバッファ
DWORD nNumberOfBytesToRead, // 読み取り対象のバイト数
LPDWORD lpNumberOfBytesRead, // 読み取ったバイト数
LPOVERLAPPED lpOverlapped // オーバーラップ構造体のバッファ
);
がReadFileの定義ですが
DWORD dw;
ReadFile( hFile , buffer , sizeof(wchar_t) * 1000 , &dw , NULL );
これで
buffer[1]・・・あ
buffer[2]・・・a
buffer[3]・・・b
buffer[4]・・・い
buffer[5]・・・c
・
・
・
とはいっているはずです。
ところでUNICODE-UCS2は全ては2バイトです。ですから半角とか全角とかは関係ありません。
まずメモ帳等でUNICODE形式を保存すればわかりますがテキストファイル
の最初にFF FE またはFE FFがつきます。これはLittleEndianかBigEndianの指標で
Windowsの標準はlittle endianです。
それを考慮してbuffer[0]からではなくbuffer[1]からにしています。
この回答への補足
以下のようにやってみましたが、やはりできません^^;
ステップ実行すると、確かにbufferに読み込まれるんですが、
最後に意味不明の文字が入ってしまいます。
ファイルはメモ帳でUNICODEで保存しました。
aあ
の2文字が入ってます。
bufferの値は正確に再現できません。化けてますので、おそらく投稿するとさらに違う変な文字になったりしてます。
bufferのポインタを移動するとやはり全角の文字は取れません。。
配列でもやってみましたが、同じ結果でした。
すいません。どんなところがおかしいでしょうか?
きっとおかしいでしょうが、発見できませんです。。。
HANDLE hFile = CreateFile( ファイル名, GENERIC_READ , 0 , NULL ,
OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL);
DWORD wReadSize = GetFileSize(hFile , NULL);
wchar_t* buffer = (wchar_t*)malloc( sizeof(wchar_t) * wReadSize );
DWORD dw;
ReadFile( hFile , buffer , sizeof(wchar_t) * wReadSize , &dw , NULL );
free(buffer);
CloseHandle(hFile);
ご回答ありがとうございます。
> ところでUNICODE-UCS2は全ては2バイトです。ですから半角とか全角とかは関係ありません。
全くおっしゃる通りです。
私のそのように考えていました。
.NETではそのようになってますし。
しかしいざCでやってみるとあれ?なんか。。
え?うん~。。って感じでどうにもできませんでした^^;
今からもう一度やってみます。
また結果を報告いたします。
No.4
- 回答日時:
読み込むファイルのエンコードはShift-JIS、UCS-2(いわゆるユニコード)、UTF-8、UTF-16のどれでしょうか。
参考:
http://www.atmarkit.co.jp/fxml/askxmlexpert/024u …
(マイクロソフトのCコンパイラを使うものと仮定します。)
Shift-JISの場合、2バイト文字の1バイト目であるかどうかは_ismbblead()関数で判定できます。_istlead()は_UNICODEが定義されている場合常にfalseを返すので、今回の場合おそらく使用できません。(_MBCSが定義されている場合_ismbblead()を返します。)
UCS-2(ユニコード)の場合、全角文字でも半角文字でも常に2バイトですから、1バイト目であるかどうかの判定は必要ありません。
UTF-8/16はよく知らないので省略します。
No.3
- 回答日時:
#2です。
例で書いたソースはあくまでもバイトごとに読み込むサンプルとして挙げただけですので、あとはご自分で作ってもらえればと思ったのですが・・・
とりあえずUnicodeの細かい処理は省いて(良くわからないので)1文字=4バイトとした場合のソースを書いておきます。
単純に文字で表示させます。
for( i = 0; i < len; i+=4 ){
printf( "%.4s\n", &p[i] );
}
一旦バッファに取り込むなら。
char w[5];
for( i = 0; i < len; i+=4 ){
strncpy( w, &p[i], 4 );
printf( "%s\n", w );
}
こんなんでよろしいでしょうか?
的外れなら補足お願いします。
この回答への補足
へんな質問ですいません。
全角、半角が混ざっているファイルですので、
forのループごとに同じ量の移動ができないです。
全角かどうかの判定がしたいですが、
ソース内部でUNICODEを#defineしているため
_istleadでしたっけ?が使えないようです。
どんな方法でもいいですが、
あabいc
のような文字の場合
あ
a
b
い
c
と取り出したいだけです。
No.2
- 回答日時:
例えば char* p に読み込んだとしたら、p[0] が0バイト目のデータです。
全データを16進で表示するサンプルを書いておきます。
len は ReadFile の4番目の引数の値(読み込んだバイト数)と思ってください。
例:
for( i = 0; i < len; i++ ){
printf( "%02x\n", p[i] );
}
もしくはポインタを使うならこうなります。
for( i = 0; i < len; i++, p++ ){
printf( "%02x\n", *p );
}
ご回答ありがとうございます。
すいませんです。いい忘れました。
全角、半角は混ざったファイルで
読み込んだ内容を"文字"として一つずと取り出すには
どうしたらいいでしょうか。書いていただいたサンプルがもしすでにそうなっていれば
もうすこし解説をいただけないでしょうか?
どうしても、一バイトずつ表示しているように見えてしまいます。
これでは2バイト文字は。。。?
すいません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
COBOLのCOMP形式について
-
UTF-8で5~6バイトになる文字コ...
-
文字コードの利点・欠点について
-
10Mバイトて文字数に すると何...
-
char str[256]の256の意味は?
-
VBSでテキストファイルの文字列...
-
文字コード結果が違うのはなぜ...
-
VBでShift_JISへurlエンコード...
-
1バイト文字から2バイト文字に変換
-
機種依存文字をチェックしたい。
-
文字列の最後の一字を削除
-
エクセルシート名の制限を変更...
-
この関数はどのプログラミング...
-
VBAでShift-JISのURLエンコード
-
C++ Builderで文字列をバイトに...
-
windowsのファイルパス最大文字数
-
バイト列とバイナリ列の違いが...
-
Excel VBA メール作成について ...
-
matlabで、平均値を求める方法...
-
C言語の勉強しています。すみま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
UTF-8で5~6バイトになる文字コ...
-
10Mバイトて文字数に すると何...
-
COBOLのCOMP形式について
-
char str[256]の256の意味は?
-
エクセルシート名の制限を変更...
-
ピクセル,dpiから容量(バイト...
-
機種依存文字をチェックしたい。
-
バイト列とバイナリ列の違いが...
-
C++ Builderで文字列をバイトに...
-
SQLで1バイト、2バイト混在...
-
URLは最高何文字まで可能なので...
-
64bit対応
-
「1TB」のHDDに日本語は何字入...
-
COBOL PICTUREで X,S,Vの意味
-
【VB2005】テキストボックス内...
-
バイナリとBCDコード
-
VC++で日本語(マルチバイト)フ...
-
全角半角を調べるライブラリ関...
-
シフトJISの2バイト文字
-
Javaで日本語1文字のバイト数
おすすめ情報