読者です 読者をやめる 読者になる 読者になる

ファイルを指定したサイズで分割する

Delphi

ファイルを指定したサイズで分割するコンソールアプリケーションをDelphiで作ってみました。
DelphiのバージョンはXE3。
ソースコードはBitbucketに置いてます。
tokibito / filesplit — Bitbucket
ファイル分割は、ファイル内容のコピー先を複数にすることで実現できます。
以下コードの一部。

procedure TSplitFile.Execute;
(* 分割処理を実行 *)
var
  FileNameTo: String;
  FileNumber: Integer;
  FileFrom, FileTo: TFileStream;
  Buffer: TMemoryStream;
  CopySize, ReadSize, WroteSize, CopiedSize, CopiedTotal: Int64;
begin
  Writeln('Split size: ' + IntToStr(FSize));
  Writeln('Target file: ' + FFileName);
  if not FileExists(FFileName) then
  begin
    Writeln('Target file does not exist.');
    Exit;
  end;
  (* コピー用のバッファを用意 *)
  Buffer := TMemoryStream.Create;
  try
    Buffer.Size :=  FBufferSize;
    CopiedTotal := 0;
    FileNumber := 0;
    FileFrom := TFileStream.Create(FFileName, fmOpenRead);
    try
      (* コピー元ファイルのサイズが0なら終了 *)
      if FileFrom.Size = 0 then
        Exit;
      while True do
      begin
        (* 分割ファイルごとのコピー済みサイズをリセット *)
        CopiedSize := 0;
        (* コピー先ファイル名を取得 *)
        FileNameTo := GetFileNameTo(FileNumber);
        Writeln(Format('Creating %s...', [FileNameTo]));
        (* コピー先ファイルを開く *)
        FileTo := TFileStream.Create(FileNameTo, fmCreate);
        try
          while True do
          begin
            (* コピーするサイズを決定 *)
            CopySize := FSize - CopiedSize;
            (* コピーするサイズが大きい場合はバッファサイズの上限を使う *)
            if CopySize > FBufferSize then
              CopySize := FBufferSize;
            (* バッファに読み込み *)
            ReadSize := FileFrom.Read(Buffer.Memory^, CopySize);
            (* コピー先へ書き込み *)
            WroteSize := FileTo.Write(Buffer.Memory^, ReadSize);
            (* コピー済みサイズを更新 *)
            Inc(CopiedSize, WroteSize);
            Inc(CopiedTotal, WroteSize);
            (* コピー元ファイルを最後まで読み込んだ場合は終了 *)
            if CopiedTotal = FileFrom.Size then
              Exit;
            (* 分割サイズまでコピーした場合は次のファイルへ *)
            if CopiedSize = FSize then
            begin
              Inc(FileNumber);
              Break;
            end;
          end;
        finally
          FreeAndNil(FileTo);
        end;
      end;
    finally
      FreeAndNil(FileFrom);
    end;
  finally
    FreeAndNil(Buffer);
  end;
end;

大きなファイルの分割でもメモリを使い切ってしまうことがないように、バッファサイズは1MBに固定しています。

実行結果

500000バイトずつにファイルを分割する場合。-sのあとに500000と指定します。

C:\Users\tokibito\_bitbucket\filesplit>filesplit -s 500000 "C:\Users\tokibito\Desktop\test\test.jpg"
Split size: 500000
Target file: C:\Users\tokibito\Desktop\test\test.jpg
Creating C:\Users\tokibito\Desktop\test\test.jpg.000...
Creating C:\Users\tokibito\Desktop\test\test.jpg.001...
Creating C:\Users\tokibito\Desktop\test\test.jpg.002...
Creating C:\Users\tokibito\Desktop\test\test.jpg.003...
Creating C:\Users\tokibito\Desktop\test\test.jpg.004...