お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"ファイル分割と結合"





みなさんこんちわ、十兵衛です。

サイズの大きなファイルを分割し、その一部(先頭)を自作プログラムに結合させ、
実行時に分割されたファイルを結合し元のファイルを組み立てます。
尚、このプログラムはnifty:FDELPHI LIB16 No47に登録されているもののソース
コードです。実行時のダイアログ表示がおかしくなる不具合があります(^^;
実行検証はNT4.0とWIN95です。それ以外の環境では動作させたことがありません。


unit MorSep1;

interface

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

type
  //データ管理レコード宣言
  //ExeSize  自分自身の実行ファイルサイズ
  //DataSize 結合対象のデータファイルサイズ
  //DataName 結合対象のデータ名
  //FileCnt  分割されたファイル数
  TFileRec = packed record
    ExeSize,DataSize:Integer;
    DataName:string[128];
    FileCnt:Integer;
  end;

  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    OpenDialog1: TOpenDialog;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private 宣言 }
    FFlg:Boolean;
    FStr1,FStr2:TMemoryStream;
    procedure RecRead(var ARec:TFileRec);
    procedure FileSeparate(AFileName:TFileName);
    procedure FileConcat;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
const
  CFileSize:Integer = 1000000;

implementation

{$R *.DFM}

procedure TForm1.RecRead(var ARec: TFileRec);
begin
  FStr1.Position := FStr1.Size-SizeOf(ARec);
  FStr1.ReadBuffer(ARec,SizeOf(ARec));
  FStr1.Position := FStr1.Size-(ARec.DataSize+SizeOf(ARec));
  FStr2.CopyFrom(FStr1,ARec.DataSize);
end;

procedure TForm1.FileConcat;
var
  FRec:TFileRec;
  FFileName:string;
  IDX:Integer;
  FStr:TMemoryStream;
begin
  FStr := TMemoryStream.Create;
  try
    RecRead(FRec);

    if MessageDlg('「'+FRec.DataName+'」を復元します'+
                #13#10+'よろしいですか',
                mtInformation,mbOKCancel,0) <> mrOK then Exit;

    Label2.Caption := FRec.DataName;
    ProgressBar1.Step := ProgressBar1.Max div FRec.FileCnt;
    for IDX := 1 to FRec.FileCnt-1 do begin
      FFileName := ChangeFileExt(Application.ExeName,'');
      FFileName := Copy(FFileName,1,Length(FFileName)-3);
      FFileName := FFileName + Format('%.3d',[IDX])+'.Dat';
      if not FileExists(FFileName) then begin
         ShowMessage('ファイルがありません'+#13#10+
                      ExtractFileName(FFileName));
         Break;
      end;
      Label4.Caption := ExtractFileName(FFileName);
      FStr.Clear;
      FStr.LoadFromFile(FFileName);
      FStr.Position := 0;
      FStr2.Position := FStr2.Size;
      FStr2.CopyFrom(FStr,FStr.Size);
      ProgressBar1.StepIt;
      Application.ProcessMessages;
    end;
    ProgressBar1.Position := ProgressBar1.Max;
    FStr2.SaveToFile(ExtractFilePath(Application.ExeName)+
                     FRec.DataName);
    ShowMessage('ファイルの結合が終了しました');
  finally
    FStr.Free;
    Application.Terminate;
  end;
end;

procedure TForm1.FileSeparate(AFileName: TFileName);
var
  FStr:TFileStream;
  FRec:TFileRec;
  IDX,Cnt:Integer;
begin
  FStr := TFileStream.Create(AFileName,fmOpenRead);
  try
    FRec.ExeSize := FStr1.Size;
    FRec.DataName := ExtractFileName(AFileName);
    FRec.DataSize :=
                  CFileSize - (FRec.ExeSize + SizeOf(FRec));
    Cnt := ((FStr.Size-FRec.DataSize) div CFileSize) + 1;
    if ((FStr.Size-FRec.DataSize) mod CFileSize) > 0 then
                                                   Inc(Cnt);
    Application.ProcessMessages;
    FRec.FileCnt := Cnt;
    FStr1.Position := FStr1.Size;
    FStr.Position := 0;
    FStr1.CopyFrom(FStr,FRec.DataSize);
    FStr1.WriteBuffer(FRec,SizeOf(FRec));
    FStr1.SaveToFile(ChangeFileExt(AFileName,'')+'000'+'.exe');
    ProgressBar1.Step := ProgressBar1.Max div FRec.FileCnt;
    for IDX := 1 to Cnt-1 do begin
      FStr2.Clear;
      if (FStr.Size-FStr.Position) > (CFileSize) then begin
          FStr2.CopyFrom(FStr,CFileSize);
      end else begin
          FStr2.CopyFrom(FStr,FStr.Size-FStr.Position);
      end;
      FStr2.SaveToFile(ChangeFileExt(AFileName,'')+
                       Format('%.3d',[IDX])+'.Dat');
      ProgressBar1.StepIt;
      Application.ProcessMessages;
    end;
    ProgressBar1.Position := ProgressBar1.Max;
    ShowMessage('ファイルの分割が終了しました');
  finally
    FStr.Free;
    Application.Terminate;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  FStr:string;
begin
  //
  FStr1 := TMemoryStream.Create;
  FStr2 := TMemoryStream.Create;
  FStr1.LoadFromFile(Application.ExeName);
  //
  FStr := ChangeFileExt(ExtractFileName(
                               Application.ExeName),'');
  FStr := Copy(FStr,Length(FStr)-2,3);
  FFlg := AnsiCompareText(FStr,'000') = 0;
  if FFlg then begin
    Label1.Caption := 'ファイルを結合中';
    Label2.Caption := '';
    Label3.Caption := '処理ファイル名';
    Label4.Caption := '';
  end else begin
    Button1.Visible := True;
    Label2.Caption := 'ファイルを選択してください';
    Label3.Visible := False;
    Label4.Visible := False;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FStr1.Free;
  FStr2.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.FileName := '';
  if not OpenDialog1.Execute then begin
    Label2.Caption := 'ファイルを選択してください';
    Exit;
  end;
  if MessageDlg('選択された「'+ExtractFileName(
                 OpenDialog1.FileName)+
                '」を分割します'+#13#10+'よろしいですか',
                mtInformation,mbOKCancel,0) = mrOK then begin
     CFileSize := StrToIntDef(InputBox('ファイルサイズ',
              'ファイルサイズを入力してください'+#13#10+
              '標準で'+IntToStr(CFileSize)+'Byteです',
              IntToStr(CFileSize)),CFileSize);
     Label2.Caption := ExtractFileName(OpenDialog1.FileName);
     Self.FileSeparate(OpenDialog1.FileName);
     Application.Terminate;
  end else Label2.Caption := 'ファイルを選択してください';
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  if not FFlg then Exit;
  Self.FileConcat;
end;

end.


ではでは(^^)/



 


Original document by 十兵衛          氏 ID:(BZT01311)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum