레코드 파일을 이용하여, 간단하게 자료를 입력하고 찾고 삭제하는 모듈을 만들려고 합니다. 그런데, 입력하고, 삭제하는 부분이 막막하네여...(T.T)
아래있는 부분은 소스 파일입니다.
unit Global;
interface
uses Classes, dialogs, sysutils;
const
c_Title = 'test';
FName = 'Reserve.DAT';
type
// 개인 정보를 담을 레코드를 정의한다.
// 정보를 담을 레코드를 정의한다.
TReserve = packed record
RDate : String[10];
RTime : String[5];
RProject : String[16];
ROrgID : String[16];
State : String[1]; //0 : 진행 대기, 1 : 진행 중, 2 : 진행 완료
end;
// TFileStream 상속 객체의 정의. 이 객체가 TPersonRec의 파일 I/O를 담당한다.
TRecordStream = class(TFileStream)
private
function GetNumRecs: Longint;
function GetCurRec: Longint;
procedure SetCurRec(RecNo: Longint);
protected
function GetRecSize: Longint; virtual;
public
function SeekRec(RecNo: Longint; Origin: Word): Longint;
function WriteRec(const Rec): Longint;
function AppendRec(const Rec): Longint;
function ReadRec(var Rec): Longint;
procedure First;
procedure Last;
procedure NextRec;
procedure PreviousRec;
// NumRecs는 스트림의 레코드 개수를 뜻하는 속성
property NumRecs: Longint read GetNumRecs;
// CurRec는 스트림의 현재 레코드를 뜻하는 속성
property CurRec: Longint read GetCurRec write SetCurRec;
end;
implementation
function TRecordStream.GetRecSize:Longint;
begin
{ 이 함수는 이 스트림이 인식하는 레코드(TPersonRec)의 크기를 돌려준다. }
Result := SizeOf(TReserve);
end;
function TRecordStream.GetNumRecs: Longint;
begin
// 이 함수는 스트림 안에 있는 레코드 수를 돌려준다.
Result := Size div GetRecSize;
end;
function TRecordStream.GetCurRec: Longint;
begin
{ 이 함수는 현재 레코드의 위치를 돌려준다. 파일 포인터는 항상 레코드의
시작 위치에 있으므로 1을 더해야 레코드 위치가 제대로 계산된다. }
Result := (Position div GetRecSize) + 1;
end;
procedure TRecordStream.SetCurRec(RecNo: Longint);
begin
{ 이 프로시저는 스트림 안에서의 레코드 위치를 RecNo 인자로 지정된
위치로 설정한다. }
if RecNo > 0 then
Position := (RecNo - 1) * GetRecSize
else
Raise Exception.Create('Cannot go beyond beginning of file.');
end;
function TRecordStream.SeekRec(RecNo: Longint; Origin: Word): Longint;
begin
{ 이 함수는 파일 포인터를 RecNo로 지정된 위치로 옮긴다. }
{ 주의: 이 메소드에는 파일 포인터가 스트림 파일의 시작/끝을 넘을 때 생기는
에러를 처리하지 않는다. }
Result := Seek(RecNo * GetRecSize, Origin);
end;
function TRecordStream.WriteRec(Const Rec): Longint;
begin
// 이 함수는 레코드 Rec를 스트림에 기록한다.
Result := Write(Rec, GetRecSize)
end;
//문제의 부분......
function TRecordStream.AppendRec(Const Rec): Longint;
begin
// 이 함수는 레코드 Rec를 스트림에 기록한다.
// Seek(-Size , 1);
Result := Write(Rec, GetRecSize);
end;
function TRecordStream.ReadRec(var Rec): Longint;
begin
{ 이 함수는 스트림으로부터 레코드 Rec을 읽고 파일 포인터의 위치를
레코드의 시작 위치로 다시 되돌린다. }
Result := Read(Rec, GetRecSize);
Seek(-GetRecSize, 1);
end;
procedure TRecordStream.First;
begin
{ 이 함수는 파일 포인터의 위치를 스트림의 시작 위치로 옮긴다. }
Seek(0, 0);
end;
procedure TRecordStream.Last;
begin
// 이 프로시저는 파일 포인터를 스트림의 끝으로 옮긴다.
Seek(0, 2);
Seek(-GetRecSize, 1);
end;
procedure TRecordStream.NextRec;
begin
{ 이 프로시저는 파일 포인터를 다음 레코드 위치로 옮긴다. }
{ 파일의 끝을 지나지 않는다면 다음 레코드로 넘어간다. }
if ((Position + GetRecSize) div GetRecSize) = GetNumRecs then
raise Exception.Create('Cannot read beyond end of file')
else
Seek(GetRecSize, 1);
end;
procedure TRecordStream.PreviousRec;
begin
{ 이 프로시저는 파일 포인터를 스트림의 이전 레코드로 옮긴다. }
{ 파일의 시작을 넘지 않는다면 이전 레코드로 돌아간다. }
if (Position - GetRecSize >= 0) then
Seek(-GetRecSize, 1)
else
Raise Exception.Create('더 이상의 레코드는 존재하지 않습니다.');
end;
end.
이렇게 하면, 새로운 레코드가 기록되는게 아니라, over write 해 버립니다.
제발 도와 주세요.
TRecordStream.WriteRec은 현재의 파일위치에 그대로 쓰니까 오버라이트가 되죠.
쓰기 전에 파일의 맨 끝으로 이동을 해주어야 하지 않나요?
function TRecordStream.WriteRec(Const Rec): Longint;
begin
Seek(0, soFromEnd); // 파일포인터를 파일의 끝으로 이동시킨다.
// 이 함수는 레코드 Rec를 스트림에 기록한다.
Result := Write(Rec, GetRecSize)
end;
^^ 항상 즐코하세요.
종상이 wrote:
> 레코드 파일을 이용하여, 간단하게 자료를 입력하고 찾고 삭제하는 모듈을 만들려고 합니다. 그런데, 입력하고, 삭제하는 부분이 막막하네여...(T.T)
>
> 아래있는 부분은 소스 파일입니다.
>
> unit Global;
>
> interface
> uses Classes, dialogs, sysutils;
>
> const
> c_Title = 'test';
> FName = 'Reserve.DAT';
>
> type
>
> // 개인 정보를 담을 레코드를 정의한다.
> // 정보를 담을 레코드를 정의한다.
> TReserve = packed record
> RDate : String[10];
> RTime : String[5];
> RProject : String[16];
> ROrgID : String[16];
> State : String[1]; //0 : 진행 대기, 1 : 진행 중, 2 : 진행 완료
> end;
>
> // TFileStream 상속 객체의 정의. 이 객체가 TPersonRec의 파일 I/O를 담당한다.
>
> TRecordStream = class(TFileStream)
> private
> function GetNumRecs: Longint;
> function GetCurRec: Longint;
> procedure SetCurRec(RecNo: Longint);
> protected
> function GetRecSize: Longint; virtual;
> public
> function SeekRec(RecNo: Longint; Origin: Word): Longint;
> function WriteRec(const Rec): Longint;
> function AppendRec(const Rec): Longint;
> function ReadRec(var Rec): Longint;
> procedure First;
> procedure Last;
> procedure NextRec;
> procedure PreviousRec;
> // NumRecs는 스트림의 레코드 개수를 뜻하는 속성
> property NumRecs: Longint read GetNumRecs;
> // CurRec는 스트림의 현재 레코드를 뜻하는 속성
> property CurRec: Longint read GetCurRec write SetCurRec;
> end;
>
> implementation
>
> function TRecordStream.GetRecSize:Longint;
> begin
> { 이 함수는 이 스트림이 인식하는 레코드(TPersonRec)의 크기를 돌려준다. }
> Result := SizeOf(TReserve);
> end;
>
> function TRecordStream.GetNumRecs: Longint;
> begin
> // 이 함수는 스트림 안에 있는 레코드 수를 돌려준다.
> Result := Size div GetRecSize;
> end;
>
> function TRecordStream.GetCurRec: Longint;
> begin
> { 이 함수는 현재 레코드의 위치를 돌려준다. 파일 포인터는 항상 레코드의
> 시작 위치에 있으므로 1을 더해야 레코드 위치가 제대로 계산된다. }
> Result := (Position div GetRecSize) + 1;
> end;
>
> procedure TRecordStream.SetCurRec(RecNo: Longint);
> begin
> { 이 프로시저는 스트림 안에서의 레코드 위치를 RecNo 인자로 지정된
> 위치로 설정한다. }
> if RecNo > 0 then
> Position := (RecNo - 1) * GetRecSize
> else
> Raise Exception.Create('Cannot go beyond beginning of file.');
> end;
>
> function TRecordStream.SeekRec(RecNo: Longint; Origin: Word): Longint;
> begin
> { 이 함수는 파일 포인터를 RecNo로 지정된 위치로 옮긴다. }
>
> { 주의: 이 메소드에는 파일 포인터가 스트림 파일의 시작/끝을 넘을 때 생기는
> 에러를 처리하지 않는다. }
> Result := Seek(RecNo * GetRecSize, Origin);
> end;
>
> function TRecordStream.WriteRec(Const Rec): Longint;
> begin
> // 이 함수는 레코드 Rec를 스트림에 기록한다.
> Result := Write(Rec, GetRecSize)
> end;
>
> //문제의 부분......
> function TRecordStream.AppendRec(Const Rec): Longint;
> begin
> // 이 함수는 레코드 Rec를 스트림에 기록한다.
> // Seek(-Size , 1);
> Result := Write(Rec, GetRecSize);
> end;
>
> function TRecordStream.ReadRec(var Rec): Longint;
> begin
> { 이 함수는 스트림으로부터 레코드 Rec을 읽고 파일 포인터의 위치를
> 레코드의 시작 위치로 다시 되돌린다. }
> Result := Read(Rec, GetRecSize);
> Seek(-GetRecSize, 1);
> end;
>
> procedure TRecordStream.First;
> begin
> { 이 함수는 파일 포인터의 위치를 스트림의 시작 위치로 옮긴다. }
> Seek(0, 0);
> end;
>
> procedure TRecordStream.Last;
> begin
> // 이 프로시저는 파일 포인터를 스트림의 끝으로 옮긴다.
> Seek(0, 2);
> Seek(-GetRecSize, 1);
> end;
>
> procedure TRecordStream.NextRec;
> begin
> { 이 프로시저는 파일 포인터를 다음 레코드 위치로 옮긴다. }
> { 파일의 끝을 지나지 않는다면 다음 레코드로 넘어간다. }
> if ((Position + GetRecSize) div GetRecSize) = GetNumRecs then
> raise Exception.Create('Cannot read beyond end of file')
> else
> Seek(GetRecSize, 1);
> end;
>
> procedure TRecordStream.PreviousRec;
> begin
> { 이 프로시저는 파일 포인터를 스트림의 이전 레코드로 옮긴다. }
>
> { 파일의 시작을 넘지 않는다면 이전 레코드로 돌아간다. }
> if (Position - GetRecSize >= 0) then
> Seek(-GetRecSize, 1)
> else
> Raise Exception.Create('더 이상의 레코드는 존재하지 않습니다.');
> end;
>
> end.
>
> 이렇게 하면, 새로운 레코드가 기록되는게 아니라, over write 해 버립니다.
> 제발 도와 주세요.