Q&A

  • 이진 파일 데이터형??!!?
Tmydata=record

name:string[50];

addr:string[100];

memo:string[255];

end;

Tmydata를 이진 파일로 만들건데요. 파일을 읽고 쓸대요...

name과 addr은 문제가 없는데요.

memo 부분에는 ...예를 들면 사용자가 255자를 쓸건지 10000자를 쓸건지 모르는 거자나요

여기서 막히고 있습니다....ㅠ.ㅠ

그 문제를 어떻게 해결 하나요.?



고수님 한수...갈쵸주셔용~~,*.*



1  COMMENTS
  • Profile
    류종택 2001.08.12 21:55
    데이터베이스 역활하는 프로그램을 작성 중이신가보지요??

    가변 사이즈에 대한 데이터처리는 Record 형식으로는 곤란합니다..

    간혹 데이터베이스에서도 가변되는 놈은 따로 화일이나 공간을 만들어서..

    처리하는 경우도 있습니다..

    이렇게 되면.. 프로그램만 복잡해지니..

    제가 권해드리는 방법은..

    Linked List와 비슷 한 방법입니다..



    사이즈1+데이터1, 사이즈2+데이터, ....



    이렇게 하면.. 우선 사이즈를 저장하는 곳은 고정 크기이니..

    그것을 읽고 다음에 읽어들일 데이타의 크기만 읽고..

    다음 사이즈를 읽고 하는 식으로 읽어들일 수 있습니다..



    문제는 이러한 구조는 데이터가 중간에 변한다면..

    그 처리와 포퍼먼스에 상당히 문제가 된다는 것입니다..



    만약 파일 사이즈에 별로 문제가 안된다면..

    아예 최대 사이즈를 설정하고 프로그램을 작성하는 것도 괜찮을 합니다..



    이러한 목적으로 만들었던 콤포넌트 소스를 올려드리니 참고 바랍니다..

    파일을 합치고 다시 떼어내는 것인데요..

    각 파일의 크기가 다를 수 있어.. 님께서 원하시는..

    가변 데이터 저장 및 검색 용도로 가끔 사용하거던요..



    첨부파일이 안되어서리..

    예제는 파일을 같이 올리기는 어렵군요..





    From 류..



    ---------



    unit RyuFileTools;



    interface



    uses

    Windows, Messages, SysUtils, Classes;



    type

    TMergeHeader = Record

    HID : Packed Array [1..8] of Char;

    Size : Int64;

    Position : Int64;

    FileName : Packed Array [1..64] of Char;

    End;

    TBuffer = Record

    Data : Pointer;

    Size : Integer;

    End;



    TRyuFileMerge = class(TComponent)

    private

    { Private declarations }

    FileStream : TFileStream;

    FOpened : Boolean;

    protected

    { Protected declarations }

    public

    { Public declarations }

    Procedure Open(FileName:String);

    Procedure Close;

    Function Opened:Boolean;

    Procedure Add(MergeHeader:TMergeHeader; Source:TStream); OverLoad;

    Procedure Add(Source:TStream); OverLoad;

    Procedure AddData(Data:Pointer; Size:Integer);

    Procedure AddString(Text:String);

    Procedure AddFile(FileName:String);

    published

    { Published declarations }

    end;



    TRyuFileSplit = class(TComponent)

    private

    { Private declarations }

    FileStream : TFileStream;

    protected

    { Protected declarations }

    public

    { Public declarations }

    Buffer : TBuffer;

    List : Array of TMergeHeader;



    Procedure Open(FileName:String); OverLoad;

    Procedure Open(FileName:String; Position:Integer); OverLoad;

    Procedure Close;

    Function FileSize:Integer;

    Function Count:Integer;

    Function Items(Index:Integer):TMergeHeader;

    Procedure Read(Index:Integer; Var Data:TBuffer);

    Procedure ReadNow(Index:Integer; Var Data:TBuffer);

    Procedure SaveToFile(Index:Integer; FileName:String);

    published

    { Published declarations }

    end;



    procedure Register;



    implementation



    procedure Register;

    begin

    RegisterComponents('Ryu', [TRyuFileMerge, TRyuFileSplit]);

    end;



    //// TRyuFileMerge 구현 부분



    Procedure TRyuFileMerge.Open(FileName:String);

    Begin

    FileStream:= TFileStream.Create(FileName, fmCreate);

    FOpened:= True;

    End;



    Procedure TRyuFileMerge.Close;

    Begin

    FOpened:= False;

    Try

    FileStream.Free;

    Except

    End;

    End;



    Function TRyuFileMerge.Opened:Boolean;

    Begin

    Result:= FOpened;

    End;



    Procedure TRyuFileMerge.Add(MergeHeader:TMergeHeader; Source:TStream);

    Begin

    // Header 저장

    FileStream.Write(MergeHeader, SizeOf(TMergeHeader));

    // 데이터 저장

    FileStream.CopyFrom(Source, Source.Size);

    End;



    Procedure TRyuFileMerge.Add(Source:TStream);

    Const

    HID : Packed Array [1..8] of Char = (

    'R', 'y', 'u', 'j', 't', '6', '5', '8'

    );

    Var

    MergeHeader : TMergeHeader;

    Begin

    Move(HID, MergeHeader.HID, 8);

    MergeHeader.Size:= Source.Size;

    Add(MergeHeader, Source);

    End;



    Procedure TRyuFileMerge.AddData(Data:Pointer; Size:Integer);

    Const

    HID : Packed Array [1..8] of Char = (

    'R', 'y', 'u', 'j', 't', '6', '5', '8'

    );

    Var

    MergeHeader : TMergeHeader;

    Begin

    Move(HID, MergeHeader.HID, 8);

    MergeHeader.Size:= Size;



    // Header 저장

    FileStream.Write(MergeHeader, SizeOf(TMergeHeader));

    // 데이터 저장

    FileStream.Write(Data^, Size);

    End;



    Procedure TRyuFileMerge.AddString(Text:String);

    Const

    HID : Packed Array [1..8] of Char = (

    'R', 'y', 'u', 'j', 't', '6', '5', '8'

    );

    Var

    MergeHeader : TMergeHeader;

    Begin

    Move(HID, MergeHeader.HID, 8);

    MergeHeader.Size:= Length(Text);



    // Header 저장

    FileStream.Write(MergeHeader, SizeOf(TMergeHeader));

    // 데이터 저장

    FileStream.Write(Text[1], Length(Text));

    End;



    Procedure TRyuFileMerge.AddFile(FileName:String);

    Const

    HID : Packed Array [1..8] of Char = (

    'R', 'y', 'u', 'j', 't', '6', '5', '8'

    );

    Var

    fsInput : TFileStream;

    MergeHeader : TMergeHeader;

    Begin

    fsInput:= TFileStream.Create(FileName, fmOpenRead);

    Try

    // 파일명만 추출

    FileName:= ExtractFileName(FileName)+#0;



    // Header 작성

    Move(HID, MergeHeader.HID, 8);

    MergeHeader.Size:= fsInput.Size;

    Move(FileName[1], MergeHeader.FileName, Length(FileName));



    Add(MergeHeader, fsInput);

    Finally

    fsInput.Free;

    End;

    End;



    //// TRyuFileSplit 구현 부분



    Procedure TRyuFileSplit.Open(FileName:String);

    Var

    MergeHeader : TMergeHeader;

    Begin

    FileStream:= TFileStream.Create(FileName, fmOpenRead);

    SetLength(List, 0);



    While FileStream.Read(MergeHeader, SizeOf(TMergeHeader)) > 0 do

    Begin

    MergeHeader.Position:= FileStream.Position;



    // 데이터 리스트 작성

    SetLength(List, Length(List)+1);

    List[Length(List)-1]:= MergeHeader;



    FileStream.Seek(MergeHeader.Size, soFromCurrent);

    End;

    End;



    Procedure TRyuFileSplit.Open(FileName:String; Position:Integer);

    Begin

    FileStream:= TFileStream.Create(FileName, fmOpenRead);

    FileStream.Seek(Position, soFromBeginning);

    End;



    Procedure TRyuFileSplit.Close;

    Begin

    Try

    FileStream.Free;

    Except

    End;

    End;



    Function TRyuFileSplit.FileSize:Integer;

    Begin

    Result:= FileStream.Size;

    End;



    Function TRyuFileSplit.Count:Integer;

    Begin

    Result:= Length(List);

    End;



    Function TRyuFileSplit.Items(Index:Integer):TMergeHeader;

    Begin

    Result:= List[Index];

    End;



    Procedure TRyuFileSplit.Read(Index:Integer; Var Data:TBuffer);

    Begin

    Data.Size:= List[Index].Size;



    FileStream.Seek(List[Index].Position, soFromBeginning);

    FileStream.Read(Data.Data^, Data.Size);

    End;



    Procedure TRyuFileSplit.ReadNow(Index:Integer; Var Data:TBuffer);

    Begin

    Data.Size:= List[Index].Size;

    FileStream.Read(Data.Data^, Data.Size);

    End;



    Procedure TRyuFileSplit.SaveToFile(Index:Integer; FileName:String);

    Var

    fsSave : TFileStream;

    Begin

    fsSave:= TFileStream.Create(FileName, fmCreate);

    Try

    FileStream.Seek(List[Index].Position, soFromBeginning);

    fsSave.CopyFrom(FileStream, List[Index].Size);

    Finally

    fsSave.Free;

    End;

    End;



    end.





    홍재민 wrote:

    > Tmydata=record

    > name:string[50];

    > addr:string[100];

    > memo:string[255];

    > end;

    > Tmydata를 이진 파일로 만들건데요. 파일을 읽고 쓸대요...

    > name과 addr은 문제가 없는데요.

    > memo 부분에는 ...예를 들면 사용자가 255자를 쓸건지 10000자를 쓸건지 모르는 거자나요

    > 여기서 막히고 있습니다....ㅠ.ㅠ

    > 그 문제를 어떻게 해결 하나요.?

    >

    > 고수님 한수...갈쵸주셔용~~,*.*

    >