文字列をファイルに書き込むとVB5の場合、コード変換が行われます。
これはVB特有の動作で、将来に向けての内部はユニコードに、互換性を考えてファイルはDBCSに変換されます。
しかし、初心者には分かりにくい仕様であり、テキストファイルの読み書きが遅くなるという問題点を持っています。
C++Builder1.x と Delphi3.x はDBCSを標準にしており、現時点でメモリ内部とファイルは同じコードで読み書きします。
VBの場合
ファイルに書き込んだ"ABCあいう" のデータ | |||||||||
バイト数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1バイト毎のデータの並び (16進) |
41 | 42 | 43 | 82 | A0 | 82 | A2 | 82 | A4 |
文字数 | 1 | 2 | 3 | 4 | 5 | 6 | |||
実際の文字 | "A" | "B" | "C" | "あ" | "い" | "う" |
確認に使用したコード
Private Sub Command1_Click() Dim length As Integer Dim cnt As Integer Dim char1 As String Dim ascii As Integer Dim swork As String Dim rwork(0 To 12) As Byte ' ユニコード分のサイズを用意しておく Dim work As String Dim msg As String '* Stringの内容をチェック swork = "ABCあいう" '* バイナリイメージで書き込む Open "STRINGCHECK.TXT" For Binary Access Write As #1 Put #1, , swork Close #1 msg = "元の文字列=" + swork + Chr(13) + Chr(10) length = LenB(swork) For cnt = 1 To length ' 1バイト取り出して、文字コードに変換する char1 = MidB(swork, cnt, 1) ascii = AscB(char1) ' 文字コードを16進数の文字列に変換する msg = msg + Right("00" + Hex(ascii), 2) + "," Next cnt msg = msg + Chr(13) + Chr(10) '* バイナリイメージをコード変換せずに読み込む Open "STRINGCHECK.TXT" For Binary Access Read As #1 Get #1, , rwork Close #1 '* バイナリイメージをコード変換して読み込む Open "STRINGCHECK.TXT" For Binary Access Read As #1 Input #1, work Close #1 msg = msg + "読み込んだ文字列=" + work + Chr(13) + Chr(10) For cnt = LBound(rwork) To UBound(rwork) ' 1バイト取り出して、文字コードに変換する ascii = rwork(cnt) ' 文字コードを16進数の文字列に変換する msg = msg + Right("00" + Hex(ascii), 2) + "," Next cnt Call MsgBox(msg) End Sub |
C++Builderの場合
ファイルに書き込んだ"ABCあいう" のデータ | |||||||||
バイト数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1バイト毎のデータの並び (16進) |
41 | 42 | 43 | 82 | A0 | 82 | A2 | 82 | A4 |
文字数 | 1 | 2 | 3 | 4 | 5 | 6 | |||
実際の文字 | "A" | "B" | "C" | "あ" | "い" | "う" |
確認に使用したコード
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int cnt; int ascii; char rwork[128]; // AnsiStringの内容をチェック AnsiString swork = "ABCあいう"; AnsiString msg = "元の文字列=" + swork + "\xd\xa"; int len = swork.Length() + 1; for( cnt = 1; cnt <= len; cnt ++ ){ // 1バイト取り出して、文字コードに変換する ascii = int(swork[cnt]) & 0xff; // 文字コードを16進数の文字列に変換する msg += IntToHex(ascii, 2) + ","; } msg += "\xd\xa"; // 書き込み TFileStream *fs; fs = new TFileStream( "STRINGCHECK.TXT", fmCreate ); fs->Write( (void *)&swork[1], len); // 要注意:AnsiStringは[1]が先頭 delete fs; // 読み込み memset( rwork, 0, sizeof(rwork) ); fs = new TFileStream( "STRINGCHECK.TXT", fmOpenRead ); fs->Read( rwork, len); delete fs; msg = msg + "読み込んだ文字列=" + rwork + "\xd\xa"; len = strlen(rwork) + 1; for( cnt = 1; cnt <= len; cnt ++ ){ // 1バイト取り出して、文字コードに変換する ascii = int(swork[cnt]) & 0xff; // 文字コードを16進数の文字列に変換する msg += IntToHex(ascii, 2) + ","; } ShowMessage(msg); } //--------------------------------------------------------------------------- |
Delphiの場合
ファイルに書き込んだ"ABCあいう" のデータ | |||||||||
バイト数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1バイト毎のデータの並び (16進) |
41 | 42 | 43 | 82 | A0 | 82 | A2 | 82 | A4 |
文字数 | 1 | 2 | 3 | 4 | 5 | 6 | |||
実際の文字 | "A" | "B" | "C" | "あ" | "い" | "う" |
確認に使用したコード
procedure TForm1.Button1Click(Sender: TObject); var len: Integer; cnt: Integer; ascii: Integer; swork: AnsiString; rwork: AnsiString; msg: AnsiString; F1: TextFile; Ch: Char; begin // AnsiStringのイメージをそのままファイルに書き込む swork := 'ABCあいう'; msg := '元の文字列=' + swork + #13#10; len := Length( swork ); for cnt := 1 to len do begin // 1バイト取り出して、文字コードに変換する ascii := Ord( swork[cnt] ); // 文字コードを16進数の文字列に変換する msg := msg + IntToHex( ascii, 2) + ','; end; msg := msg + #13#10; // 書き込み AssignFile( F1, 'STRINGCHECK1.TXT' ); Rewrite( F1 ); Write( F1, swork ); CloseFile( F1 ); // 読み込み AssignFile( F1, 'STRINGCHECK1.TXT' ); Reset( F1 ); while not Eof( F1 ) do // ファイルの終端までループ begin Read( F1, Ch ); rwork := rwork + Ch; end; msg := msg + '読み込んだ文字列=' + rwork + #13#10; Reset( F1 ); while not Eof( F1 ) do // ファイルの終端までループ begin Read( F1, Ch ); msg := msg + IntToHex( Ord( Ch ), 2) + ','; end; CloseFile( F1 ); ShowMessage( msg ); end; |
WideString 型の使用例です。無理矢理書き込んで、無理矢理読み込んでいます(^^;
ファイルに書き込んだ"ABCあいう" のデータ | ||||||||||||
バイト数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1バイト毎のデータの並び (16進) |
41 | 00 | 42 | 00 | 43 | 00 | 42 | 30 | 44 | 30 | 46 | 30 |
文字数 | 1 | 2 | 3 | 4 | 5 | 6 | ||||||
実際の文字 | "A" | "B" | "C" | "あ" | "い" | "う" |
確認に使用したコード
procedure TForm1.Button2Click(Sender: TObject); var len: Integer; cnt: Integer; ascii: Integer; swork: WideString; // ワイド文字対応 rwork: WideString; // ワイド文字対応 wCh: WideChar; size: Integer; msg: AnsiString; S: array[0..256] of Char; fs: TFileStream; F1: TextFile; Ch: Char; begin // WideStringのイメージをそのままファイルに書き込む swork := 'ABCあいう'; msg := '元の文字列=' + swork + #13#10; len := Length( swork ); for cnt := 1 to len do begin StrLCopy( S, PChar( @swork[cnt] ), 2 ); // 1バイトづつ取り出して、文字コードに変換する ascii := Ord( S[0] ); msg := msg + IntToHex( ascii, 2) + ','; ascii := Ord( S[1] ); msg := msg + IntToHex( ascii, 2) + ','; end; msg := msg + #13#10; // 書き込み fs := TFileStream.Create( 'STRINGCHECK2.TXT', fmCreate ); for cnt := 1 to len do // 文字数ループ begin wCh := swork[cnt]; fs.Write( wCh, 2 ); end; fs.Free; // 読み込み rwork := ''; fs := TFileStream.Create( 'STRINGCHECK2.TXT', fmOpenRead ); size := fs.Read( wCh, 2 ); while size <> 0 do // 読み込みサイズが0になるまでループ begin rwork := rwork + WideString(wCh); size := fs.Read( wCh, 2 ); end; fs.Free; msg := msg + '読み込んだ文字列=' + rwork + #13#10; AssignFile( F1, 'STRINGCHECK2.TXT' ); Reset( F1 ); while not Eof( F1 ) do // ファイルの終端までループ begin Read( F1, Ch ); msg := msg + IntToHex( Ord( Ch ), 2) + ','; end; CloseFile( F1 ); ShowMessage( msg ); end; |