はじめてのDelphi(その6−2)

戻る

ここでは、VBC++BuilderDelphiVCのバイナリファイルの書き込み/読み込みの違いを見てみます。

バイナリファイル

  • レコード形式(1レコード16byte)のデータを4レコード書き込みします。
  • 書き込みしたファイルを読み出し、テキストボックス(VB)/メモ(C++Builder/Delphi)にセットします。
  • また、書き込みしたデータファイルイメージをダンプします。

 


VBの場合

  • フォームにテキストボックス(Text1)を置いてください。
    MultiLine プロパティTrue にしておきます。
  • コマンドボタン1は、ランダムアクセス形式の書き込み/読み込みを行います。
  • コマンドボタン2は、バイナリアクセス形式の書き込み/読み込みを行います。
  • ランダムアクセス、バイナリアクセスともに、Put #、Get #を利用しますが、パラメータの違いに注意してください。
  • ダンプを奇麗に表示するため、テキストボックス(Text1)のフォントを”MS ゴシック 10ポイント”にしてください。

先頭へ

Module1.bas

Option Explicit

Type TestRecord                     ' ユーザー定義型を定義します。
    ID As Long
    Name As String * 12
End Type

Form1.frm


Private Sub Command1_Click()
    Dim PutRecord(1 To 4) As TestRecord ' 変数を宣言します。
    Dim GetRecord As TestRecord         ' 変数を宣言します。
    Dim FName As String     ' ファイル名
    Dim cnt As Integer      ' カウンタ
    Dim msg As String
    
    '* 初期化
    FName = "FILETEST1.BIN"  ' ".BIN"はバイナリーの意味
    For cnt = 1 To 4
        PutRecord(cnt).ID = cnt
    Next cnt
    PutRecord(1).Name = "岡部"
    PutRecord(2).Name = "斎藤"
    PutRecord(3).Name = "原田"
    PutRecord(4).Name = "船木"
    msg = ""
    
    '* ランダムアクセスファイル書き込み
    Open FName For Random As #1 Len = Len(PutRecord(1))   ' ファイルを開きます。
    For cnt = 1 To 4
        Put #1, cnt, PutRecord(cnt)               ' 書き込みます。
    Next cnt
    Close #1                                    ' ファイルを閉じます。
    
    '* ランダムアクセスファイル読み込み
    Open FName For Random As #1 Len = Len(GetRecord)   ' ファイルを開きます。
    cnt = 1
    Do While cnt <= (LOF(1) / Len(GetRecord))    ' ファイルの終端までループを繰り返します。
        Get #1, cnt, GetRecord                ' レコード毎に読み込みます。
        msg = msg + Str(GetRecord.ID) + ","
        msg = msg + LeftB(GetRecord.Name, 12) + vbCrLf
        cnt = cnt + 1
    Loop
    Close #1                                ' ファイルを閉じます。
    
    '* バイナリファイルのダンプ作成
    '* (奇麗に表示するためにTextBoxのフォントを”MS ゴシック 10ポイント”にしておく)
    Call FileDump(FName, msg)
    
    '* 読み込み結果表示
    Text1.Text = msg
    Call MsgBox("バイナリ Save/Load完了")
    
End Sub

Private Sub Command2_Click()
    Dim PutRecord(1 To 4) As TestRecord ' 変数を宣言します。
    Dim GetRecord As TestRecord         ' 変数を宣言します。
    Dim FName As String     ' ファイル名
    Dim cnt As Integer      ' カウンタ
    Dim msg As String
    
    '* 初期化
    FName = "FILETEST2.BIN"  ' ".BIN"はバイナリーの意味
    For cnt = 1 To 4
        PutRecord(cnt).ID = cnt
    Next cnt
    PutRecord(1).Name = "岡部"
    PutRecord(2).Name = "斎藤"
    PutRecord(3).Name = "原田"
    PutRecord(4).Name = "船木"
    msg = ""
    
    '* バイナリファイル書き込み
    Open FName For Binary Access Write As #1    ' ファイルを開きます。
    For cnt = 1 To 4
        Put #1, , PutRecord(cnt)                ' 書き込みます。
    Next cnt
    Close #1                                    ' ファイルを閉じます。
    
    '* バイナリファイル読み込み
    Open FName For Binary Access Read As #1 ' ファイルを開きます。
    Do While LOF(1) <> Loc(1)               ' ファイルの終端までループを繰り返します。
        Get #1, , GetRecord                 ' バイナリレコード毎に読み込みます。
        msg = msg + Str(GetRecord.ID) + ","
        msg = msg + LeftB(GetRecord.Name, 12) + vbCrLf
    Loop
    Close #1                                ' ファイルを閉じます。
    
    '* バイナリファイルのダンプ作成
    '* (奇麗に表示するためにTextBoxのフォントを”MS ゴシック 10ポイント”にしておく)
    Call FileDump(FName, msg)
    
    '* 読み込み結果表示
    Text1.Text = msg
    Call MsgBox("バイナリ Save/Load完了")
    
End Sub

Private Sub FileDump(ByVal FName As String, ByRef msg As String)
'* 指定ファイルのダンプイメージ文字列を作成します
'* [in]
'*    FName : ダンプイメージするファイル名
'*    msg   : ダンプイメージをセットする文字列変数
'* [out]
'*    なし(ダンプイメージは msg にセットする)
'* [注意]
'*   関数内でファイルをオープンします。目的のファイルはファイルクローズ
'*   した状態で呼び出してください。
'*   msg は初期化しません。呼び出し側で初期化するようにしてください。
    Dim cnt As Integer      ' カウンタ
    Dim DumpCode As Byte
    
    msg = msg + vbCrLf + vbCrLf
    msg = msg + "ADDR : 00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F" + vbCrLf
    msg = msg + "-----:-------------------------------------------------" + vbCrLf
    cnt = 0
    Open FName For Binary Access Read As #1 ' ファイルを開きます。
    Do While LOF(1) <> Loc(1)               ' ファイルの終端までループを繰り返します。
        Get #1, , DumpCode                  ' バイナリを1バイト毎に読み込みます。
        If cnt Mod 16 = 0 Then
            ' アドレス(16バイト毎)のセット
            msg = msg + Right("0000" + Hex(cnt), 4) + " : "
        End If
        cnt = cnt + 1
        msg = msg + Right("00" + Hex(DumpCode), 2)
        If cnt Mod 16 = 0 Then
            ' 16バイト毎に改行
            msg = msg + vbCrLf
        Else
            If cnt Mod 8 = 0 Then
                ' 8バイトの所はスペースを2個入れる
                msg = msg + "  "
            Else
                msg = msg + " "
            End If
        End If
    Loop
    Close #1                                ' ファイルを閉じます。
            
    msg = msg + vbCrLf
End Sub


C++Builderの場合

  • フォームにメモコンポーネント(Memo1)を置いてください。
  • ボタン1は C 標準ライブラリによるバイナリの書き込み/読み込みです。
    WriteRec[]ReadRec はローカル変数として宣言しているのでメモリを memset() でクリアしています。
  • ボタン2は TFileStream を利用した例です。
    WriteRec[]ReadRec はローカル変数として宣言しているのでメモリを memset() でクリアしています。
  • ダンプを奇麗に表示するため、メモコンポーネント(Memo1)のフォントを”MS ゴシック 10ポイント”にしてください。

先頭へ

Unit1.h

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:  // IDE 管理のコンポーネント
    TButton *Button1;
    TButton *Button2;
    TMemo *Memo1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
private:  // ユーザー宣言
    void FileDump( const AnsiString& FName, AnsiString& msg );
public:   // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

Unit1.cpp


//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
struct TestRecord {
    long  id;
    char  name[12];
};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// fopen,fclose,fwrite,fread 等を使用
    TestRecord  WriteRec[4];
    TestRecord  ReadRec;
    char  *FName;
    int   cnt;
    AnsiString   msg;
    FILE  *sfs, *lfs;

    // 初期化前のチェック sizeof( TestRecord ) = 16
    msg = "sizeof( TestRecord ) = " + IntToStr( sizeof( TestRecord ) );
    ShowMessage( msg );

    // 初期化
    FName = "FILETEST1.BIN";
    Memo1->Clear();
    for( cnt = 0; cnt <= 3; cnt ++ ){
        memset( &WriteRec[ cnt ], 0, sizeof( TestRecord ) );
        WriteRec[ cnt ].id = cnt + 1;
    }
    sprintf( WriteRec[0].name, "岡部" );
    sprintf( WriteRec[1].name, "斎藤" );
    sprintf( WriteRec[2].name, "原田" );
    sprintf( WriteRec[3].name, "船木" );
    msg = "Button1:binary file fwrite/fread Sample\xd\xa\xd\xa";

    // バイナリファイル書き込み
    sfs = fopen( FName, "wb" );
    if( sfs == (FILE *)0 ){
        ShowMessage( "書き込み時のopen失敗" );
        return;    // オープン失敗
    }
    for( cnt = 0; cnt <= 3; cnt ++ )
        fwrite( &WriteRec[ cnt ], 1, sizeof( TestRecord ), sfs );
    fclose( sfs );

    // バイナリファイル読み込み
    lfs = fopen( FName, "rb" );
    if( lfs == (FILE *)0 ){
        ShowMessage( "読み込み時のopen失敗" );
        return;    // オープン失敗
    }
    while( feof( lfs ) == 0 ){  // 終端に達するまでループ
        memset( &ReadRec, 0, sizeof( TestRecord ) );
        if( fread( &ReadRec, 1, sizeof( TestRecord ), lfs ) != sizeof( TestRecord ) )
            break;
        msg = msg + IntToStr( ReadRec.id ) + ",";
        msg = msg + ReadRec.name + "\xd\xa";
    }
    fclose( lfs );

    // ダンプ作成
    // (Memo1のフォントを”MS ゴシック 10ポイント”にしておくこと)
    FileDump( FName, msg );

    // 結果表示
    Memo1->Text = msg;
    ShowMessage( "バイナリSave/Load完了" );

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// TFileStream(VCL)の使用例
    TestRecord  WriteRec[4];
    TestRecord  ReadRec;
    char  *FName;
    int   cnt;
    AnsiString   msg;
    TFileStream  *sfs, *lfs;

    // 初期化
    FName = "FILETEST2.BIN";
    Memo1->Clear();
    for( cnt = 0; cnt <= 3; cnt ++ ){
        memset( &WriteRec[ cnt ], 0, sizeof( TestRecord ) );
        WriteRec[ cnt ].id = cnt + 1;
    }
    sprintf( WriteRec[0].name, "岡部" );
    sprintf( WriteRec[1].name, "斎藤" );
    sprintf( WriteRec[2].name, "原田" );
    sprintf( WriteRec[3].name, "船木" );
    msg = "Button2:binary file TFileStream(VCL) Sample\xd\xa\xd\xa";

    // バイナリファイル書き込み
    sfs = new TFileStream( FName, fmCreate );
    for( cnt = 0; cnt <= 3; cnt ++ )
        sfs->Write( &WriteRec[ cnt ], sizeof( TestRecord ) );
    delete sfs;

    // バイナリファイル読み込み
    lfs = new TFileStream( FName, fmOpenRead );
    while( 1 ){  // 無限ループ
        memset( &ReadRec, 0, sizeof( TestRecord ) );
        if( lfs->Read( &ReadRec, sizeof( TestRecord ) ) != (long)sizeof( TestRecord ) )
            break;
        msg = msg + IntToStr( ReadRec.id ) + ",";
        msg = msg + ReadRec.name + "\xd\xa";
    }
    delete lfs;

    // ダンプ作成
    // (Memo1のフォントを”MS ゴシック 10ポイント”にしておくこと)
    FileDump( FName, msg );

    // 結果表示
    Memo1->Text = msg;
    ShowMessage( "バイナリSave/Load完了" );

}
//---------------------------------------------------------------------------
// FileDump()
//   指定ファイルのダンプイメージ文字列を作成します
// [in]
//   FName : ダンプイメージするファイル名
//   msg   : ダンプイメージをセットする文字列変数(AnsiString のみ)
// [out]
//   なし(ダンプイメージは msg にセットする)
// [注意]
//   関数内でファイルをオープンします。目的のファイルはファイルクローズ
//   した状態で呼び出してください。
//   msg は初期化しません。呼び出し側で初期化するようにしてください。
//
void    TForm1::FileDump( const AnsiString& FName, AnsiString& msg )
{
    int   cnt;
    unsigned char  dat;
    FILE  *fs;

    msg = msg + "\xd\xa\xd\xa";
    msg = msg + "ADDR : 00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F\xd\xa";
    msg = msg + "-----:-------------------------------------------------\xd\xa";

    // バイナリファイル読み込み
    fs = fopen( FName.c_str(), "rb" );
    if( fs == (FILE *)0 ){
        ShowMessage( "FileDump()でopen失敗" );
        return;    // オープン失敗
    }
    cnt = 0;
    while( feof( fs ) == 0 ){  // 終端に達するまでループ
        if( fread( &dat, 1, 1, fs ) != 1 )
            break;

        if( cnt % 16 == 0 )
            // アドレス(16バイト毎)のセット
            msg = msg + IntToHex( cnt, 4 ) + " : ";

        cnt += 1;
        msg = msg + IntToHex( dat, 2 );
        if( cnt % 16 == 0 ){
            // 16バイト毎に改行
            msg = msg + "\xd\xa";
        }
        else{
            if( cnt % 8 == 0 )
                // 8バイトの所はスペースを2個入れる
                msg = msg + "  ";
            else
                msg = msg + " ";
        }
    }
    fclose( fs );

    msg = msg + "\xd\xa";
}
//---------------------------------------------------------------------------


Delphiの場合

  • フォームにメモコンポーネント(Memo1)を置いてください。
  • ボタン1は PASCAL によるランダムアクセスの書き込み/読み込みです。
  • ボタン2は TFileStream を利用した例です。
  • ダンプを奇麗に表示するため、メモコンポーネント(Memo1)のフォントを”MS ゴシック 10ポイント”にしてください。
  • Name: array[0..11] of Char; を array[1..12] とするとStringから代入ができませんので注意してください。

先頭へ


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
    procedure FileDump( FName: String; var msg: String );
  public
    { Public 宣言 }
  end;

type
  TestRecord = record
    Id: Integer;
    Name: array[0..11] of Char;// 注意!:0から始まる場合のみStringから代入できる
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  WriteRec: array[1..4] of TestRecord;
  ReadRec: TestRecord;
  FName: String;
  cnt: Integer;
  msg: String;
  sbf, lbf: file;
begin
// AssignFile,BlockWrite,BlockRead

    // 初期化前のチェック SizeOf( TestRecord ) = 16
    msg := 'SizeOf( TestRecord ) = ' + IntToStr( SizeOf( TestRecord ) );
    ShowMessage( msg );

    // 初期化
    FName := 'FILETEST1.BIN';
    Memo1.Clear();
    for cnt := 1 to 4 do
        WriteRec[ cnt ].Id := cnt;
    WriteRec[ 1 ].Name := '岡部';
    WriteRec[ 2 ].Name := '斎藤';
    WriteRec[ 3 ].Name := '原田';
    WriteRec[ 4 ].Name := '船木';
    msg := 'Button1:binary file BlockWrite/BlockRead Sample'#13#10#13#10;

    // バイナリファイル書き込み(レコード扱い)
    AssignFile( sbf, FName );
    Rewrite( sbf, SizeOf( TestRecord ) );
    for cnt := 1 to 4 do
        BlockWrite( sbf, WriteRec[ cnt ], 1 );
    CloseFile( sbf );

    // バイナリファイル読み込み(レコード扱い)
    AssignFile( lbf, FName );
    Reset( lbf, SizeOf( TestRecord ) );
    while True do  // 無限ループ
    begin
        BlockRead( lbf, ReadRec, 1, cnt );
        if cnt <> 1 then
            Break;
        msg := msg + IntToStr( ReadRec.Id ) + ' , ';
        msg := msg + ReadRec.Name + #13#10;
    end;
    CloseFile( lbf );

    // ダンプ作成
    // (Memo1のフォントを”MS ゴシック 10ポイント”にしておくこと)
    FileDump( FName, msg );

    // 結果表示
    Memo1.Text := msg;
    ShowMessage( 'バイナリSave/Load完了' );

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  WriteRec: array[1..4] of TestRecord;
  ReadRec: TestRecord;
  FName: String;
  cnt, size: Integer;
  msg: String;
  sbf, lbf: TFileStream;
begin
// TFileStream(VCL)の使用例

    // 初期化
    FName := 'FILETEST2.BIN';
    Memo1.Clear();
    for cnt := 1 to 4 do
        WriteRec[ cnt ].Id := cnt;
    WriteRec[ 1 ].Name := '岡部';
    WriteRec[ 2 ].Name := '斎藤';
    WriteRec[ 3 ].Name := '原田';
    WriteRec[ 4 ].Name := '船木';
    msg := 'Button2:binary file TFileStream(VCL) Sample'#13#10#13#10;

    // バイナリファイル書き込み
    sbf := TFileStream.Create( FName, fmCreate );
    for cnt := 1 to 4 do
        sbf.Write( WriteRec[ cnt ], SizeOf( TestRecord ) );
    sbf.Free;

    // バイナリファイル読み込み
    lbf := TFileStream.Create( FName, fmOpenRead );
    while True do  // 無限ループ
    begin
        size := lbf.Read( ReadRec, SizeOf( TestRecord ) );
        if size <> SizeOf( TestRecord ) then
            Break;
        msg := msg + IntToStr( ReadRec.Id ) + ' , ';
        msg := msg + ReadRec.Name + #13#10;
    end;
    lbf.Free;

    // ダンプ作成
    // (Memo1のフォントを”MS ゴシック 10ポイント”にしておくこと)
    FileDump( FName, msg );

    // 結果表示
    Memo1.Text := msg;
    ShowMessage( 'バイナリSave/Load完了' );

end;

//---------------------------------------------------------------------------
// FileDump()
//   指定ファイルのダンプイメージ文字列を作成します
// [in]
//   FName : ダンプイメージするファイル名
//   msg   : ダンプイメージをセットする文字列変数(String のみ)
// [out]
//   なし(ダンプイメージは msg にセットする)
// [注意]
//   関数内でファイルをオープンします。目的のファイルはファイルクローズ
//   した状態で呼び出してください。
//   msg は初期化しません。呼び出し側で初期化するようにしてください。
//
procedure TForm1.FileDump( FName: String; var msg: String );
var
    cnt: Integer;
    dat: Byte;
    fs:  TFileStream;
begin
    msg := msg + #13#10#13#10;
    msg := msg + 'ADDR : 00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F'#13#10;
    msg := msg + '-----:-------------------------------------------------'#13#10;

    // バイナリファイル読み込み
    fs := TFileStream.Create( FName, fmOpenRead );
    cnt := 0;
    while true do  // 無限ループ
    begin
        if fs.Read( dat, 1 ) <> 1 then
            Break;

        if cnt mod 16 = 0 then
            // アドレス(16バイト毎)のセット
            msg := msg + IntToHex( cnt, 4 ) + ' : ';

        cnt := cnt + 1;
        msg := msg + IntToHex( dat, 2 );
        if cnt mod 16 = 0 then
            // 16バイト毎に改行
            msg := msg + #13#10
        else
            if cnt mod 8 = 0 then
                // 8バイトの所はスペースを2個入れる
                msg := msg + '  '
            else
                msg := msg + ' ';
    end;
    fs.Free;

    msg := msg + #13#10;
end;
//---------------------------------------------------------------------------

end.


VCの場合

 比較参考用です(^^; ダイアログベースのアプリケーションでテストしています。

  • ダイアログにボタン(IDC_BUTTON1)とエディットボックス(IDC_EDIT1)を置いてください。
  • エディットボックス(IDC_EDIT1)を右クリックし、[プロパティ|スタイル]で[複数行]にチェックを付けてください。
  • エディットボックス(IDC_EDIT1)を右クリックし、[ClassWizard|メンバ変数]でコントロールID[IDC_EDIT1]を選び[変数の追加(A)]を押してください。
    [カテゴリ(C)]が”値”、[変数のタイプ(T)]が”CString”であることを確認し、[メンバ変数(N)]に”m_Edit1”と入力します。
  • エディットボックス(IDC_EDIT1)を右クリックし、[ClassWizard|メンバ変数]でコントロールID[IDC_EDIT1]を選び[変数の追加(A)]を押してください。
    [カテゴリ(C)]を”コントロール”にして、[変数のタイプ(T)]が”CEdit”であることを確認し、[メンバ変数(N)]に”m_ctlEdit1”と入力します。
  • ボタン(IDC_BUTTON1)を右クリックし、[ClassWizard|メッセージマップ]でメッセージ[BN_CLICKED]を選び[関数の追加(A)]を押してください。追加する関数名を”OnButton1”にします。
  • ↑ああ、面倒だ(笑) 詳しくはVCのマニュアルまたは入門書を読んでください。
  • エディットボックス(IDC_EDIT1)のフォントを”MS ゴシック 10ポイント”するには、OnInitDialog() 内でコントロールの操作を行うコードが必要です。
    また、フォントを設定している CFont はメンバ変数として、ダイアログと同じ寿命を持つようにする必要性があります。

ヒント: CEdit などのコントロールのメンバ変数、関数に目的の機能がない場合、上位の CWnd クラスを調べてみましょう。

先頭へ

VC5Dlg.h

// VC5Dlg.h : ヘッダー ファイル
//

#if !defined(AFX_VC5DLG_H__F9639B26_A32F_11D1_A113_00A0C96F7182__INCLUDED_)
#define AFX_VC5DLG_H__F9639B26_A32F_11D1_A113_00A0C96F7182__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

/////////////////////////////////////////////////////////////////////////////
// CVC5Dlg dialog

class CVC5Dlg : public CDialog
{
// 構築
public:
    CVC5Dlg(CWnd* pParent = NULL);    // 標準のコンストラクタ

// Dialog Data
    //{{AFX_DATA(CVC5Dlg)
    enum { IDD = IDD_VC5_DIALOG };
    CEdit      m_ctlEdit1;
    CString    m_Edit1;
    //}}AFX_DATA

    // ClassWizard は仮想関数のオーバーライドを生成します。
    //{{AFX_VIRTUAL(CVC5Dlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV のサポート
    //}}AFX_VIRTUAL

// インプリメンテーション
protected:
    HICON m_hIcon;

    // 生成されたメッセージ マップ関数
    //{{AFX_MSG(CVC5Dlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnButton1();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

    // ユーザ定義のメンバ変数
    CFont m_font;
    // ユーザ定義のメンバ関数
    void  FileDump( const CString& FName, CString& msg );
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio は前行の直前に追加の宣言を挿入します。

#endif // !defined(AFX_VC5DLG_H__F9639B26_A32F_11D1_A113_00A0C96F7182__INCLUDED_)

VC5Dlg.cpp

// VC5Dlg.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "VC5.h"
#include "VC5Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CVC5Dlg ダイアログ

CVC5Dlg::CVC5Dlg(CWnd* pParent /*=NULL*/)
    : CDialog(CVC5Dlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CVC5Dlg)
    m_Edit1 = _T("");
    //}}AFX_DATA_INIT
    // メモ: LoadIcon は Win32 の DestroyIcon のサブシーケンスを要求しません。
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CVC5Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CVC5Dlg)
    DDX_Control(pDX, IDC_EDIT1, m_ctlEdit1);
    DDX_Text(pDX, IDC_EDIT1, m_Edit1);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CVC5Dlg, CDialog)
    //{{AFX_MSG_MAP(CVC5Dlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVC5Dlg メッセージ ハンドラ

BOOL CVC5Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // このダイアログ用のアイコンを設定します。フレームワークはアプリケーションのメイン
    // ウィンドウがダイアログでない時は自動的に設定しません。
    SetIcon(m_hIcon, TRUE);         // 大きいアイコンを設定
    SetIcon(m_hIcon, FALSE);        // 小さいアイコンを設定
    
    // TODO: 特別な初期化を行う時はこの場所に追加してください。
    // エディットボックスを固定ピッチの”MS ゴシック”に変更
    m_font.CreatePointFont( 100, "MS ゴシック" );
    m_ctlEdit1.SetFont( &m_font, TRUE );
    
    return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

// もしダイアログボックスに最小化ボタンを追加するならば、アイコンを描画する
// コードを以下に記述する必要があります。MFC アプリケーションは document/view
// モデルを使っているので、この処理はフレームワークにより自動的に処理されます。

void CVC5Dlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 描画用のデバイス コンテキスト

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // クライアントの矩形領域内の中央
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // アイコンを描画します。
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// システムは、ユーザーが最小化ウィンドウをドラッグしている間、
// カーソルを表示するためにここを呼び出します。
HCURSOR CVC5Dlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

// テストレコード(構造体)
struct TestRecord {
    long  id;
    char  name[12];
};

// Button1クリック時のイベント処理
void CVC5Dlg::OnButton1() 
{
    TestRecord  WriteRec[4];
    TestRecord  ReadRec;
    int   cnt;

    // 初期化
    CString FName = "FILETEST.BIN";
    m_Edit1 = "";  // テキストボックスに関連付けしているメンバー変数
    UpdateData( FALSE );
    for( cnt = 0; cnt <= 3; cnt ++ ){
        memset( &WriteRec[ cnt ], 0, sizeof( TestRecord ) );
        WriteRec[ cnt ].id = cnt + 1;
    }
    sprintf( WriteRec[0].name, "岡部" );
    sprintf( WriteRec[1].name, "斎藤" );
    sprintf( WriteRec[2].name, "原田" );
    sprintf( WriteRec[3].name, "船木" );

    // バイナリファイル書き込み
    CFile *sbf = new CFile( FName, CFile::modeCreate | CFile::modeWrite );
    for( cnt = 0; cnt <= 3; cnt ++ )
        sbf->Write( &WriteRec[ cnt ], sizeof( TestRecord ) );
    delete sbf;

    // バイナリファイル読み込み
    CString LoadBin = "";
    CFile *lbf = new CFile( FName, CFile::modeRead );
    while( 1 ){  // 無限ループ 
        if( lbf->Read( &ReadRec, sizeof( TestRecord ) ) != sizeof( TestRecord ) )
            break;
        CString  sid;
        sid.Format( "%d", ReadRec.id );
        LoadBin = LoadBin + sid + ",";
        LoadBin = LoadBin + ReadRec.name + "\xd\xa";
    }
    delete lbf;

    // ダンプ作成
    FileDump( FName, LoadBin );

    // 読み込み結果表示
    m_Edit1 = LoadBin;
    UpdateData( FALSE );
    AfxMessageBox( "バイナリSave/Load完了", MB_OK | MB_ICONINFORMATION );
}
//---------------------------------------------------------------------------
// FileDump()
//   指定ファイルのダンプイメージ文字列を作成します
// [in]
//   FName : ダンプイメージするファイル名
//   msg   : ダンプイメージをセットする文字列変数(CString のみ)
// [out]
//   なし(ダンプイメージは msg にセットする)
// [注意]
//   関数内でファイルをオープンします。目的のファイルはファイルクローズ
//   した状態で呼び出してください。
//   msg は初期化しません。呼び出し側で初期化するようにしてください。
//
void  CVC5Dlg::FileDump( const CString& FName, CString& msg )
{
    int   cnt;
    unsigned char  dat;
    FILE  *fs;
    CString  hex;

    msg = msg + "\xd\xa\xd\xa";
    msg = msg + "ADDR : 00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F\xd\xa";
    msg = msg + "-----:-------------------------------------------------\xd\xa";

    // バイナリファイル読み込み
    fs = fopen( FName, "rb" );
    if( fs == (FILE *)0 ){
        AfxMessageBox( "FileDump()でopen失敗" );
        return;    // オープン失敗
    }
    cnt = 0;
    while( feof( fs ) == 0 ){  // 終端に達するまでループ
        if( fread( &dat, 1, 1, fs ) != 1 )
            break;

        if( cnt % 16 == 0 ){
            // アドレス(16バイト毎)のセット
            hex.Format( "%04X", cnt );
            msg = msg + hex + " : ";
        }
        cnt += 1;
        hex.Format( "%02X", dat );
        msg = msg + hex;
        if( cnt % 16 == 0 ){
            // 16バイト毎に改行
            msg = msg + "\xd\xa";
        }
        else{
            if( cnt % 8 == 0 )
                // 8バイトの所はスペースを2個入れる
                msg = msg + "  ";
            else
                msg = msg + " ";
        }
    }
    fclose( fs );

    msg = msg + "\xd\xa";
    
}
//---------------------------------------------------------------------------

 

先頭へ/戻る