ブロックリードを変えるのに最適な方法を教えて下さい。

解決


AS  2023-02-13 08:38:54  No: 150791  IP: 192.*.*.*

20年以上前、Delphiでプログラムを始めた時、教えてもらった方法は危険ですという表示が出ていました。
今は出てないようですが??
子供の勉強で家計簿プログラムをつくるのを機会に新しい方法を教えてもらおうと思って質問します。
下のデータを使って、
①1~8日までのデータを一括で保存する
②作ったファイルに9日のデータを追加する
③6~9日のデータを読み込む
の3つのプログラムを紹介してください。

正直、本を読んで調べるとかnetで調べるとかしてみましたが、
分からんとしか言えません。
よろしくお願いします。

  a:array[1..5] of DType=
   ((Day:'2023/02/01';InC:100000;Eat:0;Oth:0;Sum:0;Bal:100000),
    (Day:'2023/02/02';InC:0;Eat:1429;Oth:0;Sum:1429;Bal:98571),
    (Day:'2023/02/06';InC:0;Eat:3237;Oth:7240;Sum:10477;Bal:88094),
    (Day:'2023/02/08';InC:0;Eat:685;Oth:0;Sum:685;Bal:87409),
    (Day:'2023/02/09';InC:0;Eat:479;Oth:0;Sum:479;Bal:86930));

編集 削除
AAAAA  2023-02-13 19:35:29  No: 150792  IP: 192.*.*.*


  TR = packed record
    D1: TDateTime;
    B1: Byte;
    I1: Integer;
    S1: array[0..11] of Char;  //String は使わない
  end;



var
    I: Integer;
    R: array[1..8] of TR;
    FileStream: TFileStream;
    Y,M,D: Word;
begin
    DecodeDate(Now,Y,M,D);
    for I:=1 to 8 do
    begin
      R[I].D1 := EncodeDate(Y,M,I);
      R[I].B1 := 10 + I;
      R[I].I1 := 12340 + I;
      StrPCopy(R[I].S1,'AAAAA' + IntToStr(I));
    end;

    FileStream := TFileStream.Create('A.TXT',fmCreate);
    FileStream.Write(R,SizeOf(R));
    FileStream.Free;


var
    I: Integer;
    R: array[9..9] of TR;  //6 - 8
    FileStream: TFileStream;
    Y,M,D: Word;
begin
    DecodeDate(Now,Y,M,D);
    for I:=9 to 9 do
    begin
      R[I].D1 := EncodeDate(Y,M,I);
      R[I].B1 := 20 + I;
      R[I].I1 := 22340 + I;
      StrPCopy(R[I].S1,'CCCCCCC' + IntToStr(I));
    end;

    FileStream := TFileStream.Create('A.TXT',fmOpenReadWrite);
    FIleStream.Position := FileStream.Size;
    FileStream.Write(R,SizeOf(R));
    FileStream.Free;


var
    I: Integer;
    FileStream: TFileStream;
    R: array[6..9] of TR;  //6 - 9
begin
    FileStream := TFileStream.Create('A.TXT',fmOpenRead);
    FIleStream.Position := SizeOf(TR) * 5;
    FileStream.Read(R,SizeOf(R));
    FileStream.Free;

    for I:= Low(R) to High(R) do
    begin
      Memo1.Lines.Add(DateTimeToStr(R[I].D1));
      Memo1.Lines.Add(IntToStr(R[I].B1));
      Memo1.Lines.Add(IntToStr(R[I].I1));
      Memo1.Lines.Add(R[I].S1);
    end;

編集 削除
AS  2023-02-13 23:23:40  No: 150793  IP: 192.*.*.*

AAAAAさん、ありがとうございました。
後で、研究して作ってみます。

また、質問させていただくかも知れませんので、
よろしくお願いします。

編集 削除
AS  2023-02-14 21:31:18  No: 150794  IP: 192.*.*.*

下のように直してもよろしいでしょうか??



var
    I: Integer;
    FileStream: TFileStream;
    R: array[1..4] of TR;  //6 - 9                    //直しました
begin
    FileStream := TFileStream.Create('A.TXT',fmOpenRead);
    FIleStream.Position := SizeOf(TR) *(6-1);   //5;直しました
    FileStream.Read(R,SizeOf(TR*4));     //直しました
    FileStream.Free;

    for I:= Low(R) to High(R) do
    begin
      Memo1.Lines.Add(DateTimeToStr(R[I].D1));
      Memo1.Lines.Add(IntToStr(R[I].B1));
      Memo1.Lines.Add(IntToStr(R[I].I1));
      Memo1.Lines.Add(R[I].S1);
    end;

編集 削除
AS  2023-02-14 21:41:14  No: 150795  IP: 192.*.*.*

訂正します。
 FileStream.Read(R,SizeOf(TR)*4);     //直しました

編集 削除
AS  2023-02-23 08:20:31  No: 150810  IP: 192.*.*.*

参考にして自分のプログラムを作り始めました。
Varの宣言を各procudureで行っていたら、読み込みがうまくいかなったです。
上で一括宣言したらうまく動くようになりました。
すごく長い間悩んでいました。今日できるようになりました。
問題は、追加ができません。
また、読み込みも全部読み込むのならできるんですが、最近3日分を読み込むとかができません。
FIleStream.Positionをどう変えても最初の3日間が読み込まれます。
どこが悪いのか、よろしくお願いします。


procedure TForm1.Button2Click(Sender: TObject);
begin
    for I:=5 to 5 do
    begin
      DD.Day := a[I].day;
      DD.InC := a[I].InC;;
      DD.Eat := a[I].Eat;
      DD.Oth := a[I].Oth;;
      DD.Sum := a[I].Sum;
      DD.Bal := a[I].Bal;;
    end;

    FileStream := TFileStream.Create('c:\Study\家計簿\KakeiBo2023.TXT',fmOpenReadWrite);
    FIleStream.Position := FileStream.Size;
    FileStream.Write(DD,SizeOf(Dtype));
    FileStream.Free;

end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    setlength(R,3);
    FileStream := TFileStream.Create('c:\Study\家計簿\KakeiBo2023.TXT',fmOpenRead);
    FIleStream.Position := Sizeof(Dtype)*4;
    FileStream.Read(R,SizeOf(R));
    FileStream.Free;

    for I:= 0 to 2 do
      Memo1.Lines.Add(IntToStr(R[I].Day)+','+IntToStr(R[I].InC)+','+
          IntToStr(R[I].Eat)+','+IntToStr(R[I].Oth)+','+IntToStr(R[I].Sum)+','+
          IntToStr(R[I].Bal));

end;

編集 削除
AS  2023-02-24 09:35:11  No: 150816  IP: 192.*.*.*

昨日作ったファイルを、今日読み込んだらすべて0が入っています。
このfilestreamってほんとに使えるのですか??

FileStreamを使って、実際にファイル、データを操作されてる方、いますか??
おられましたら、投稿してください。
よろしくお願いします。

編集 削除
AAAAA  2023-02-24 11:58:17  No: 150817  IP: 192.*.*.*

//読み込み
procedure TForm2.Button1Click(Sender: TObject);
var
    I: Integer;
    D: array of TData;
    FileStream: TFileStream;
begin
    SetLength(D,10);

    FileStream := TFileStream.Create('FN.TXT',fmOpenRead);
    for I:=0 to 9 do
    begin
      FileStream.Read(D[I],SizeOf(TDATA));
    end;
    FileStream.Free;

    for I:=0 to 9 do
    begin
      Memo1.Lines.Add(IntToStr(I) + '='+IntToStr(D[I].X) + ' ' + IntToStr(D[I].Y));
    end;
end;

//書き込み
procedure TForm2.Button2Click(Sender: TObject);
var
    I: Integer;
    D: array of TData;
    FileStream: TFileStream;
begin
    SetLength(D,10);

    for I:=0 to 9 do
    begin
      D[I].X := 32 + I;
      D[I].Y := 65 + I;
    end;

    FileStream := TFileStream.Create('FN.TXT',fmCreate);
    for I:=0 to 9 do
    begin
      FileStream.Write(D[I],SizeOf(TDATA));
    end;
    FileStream.Free;

end;

編集 削除
AS  2023-02-24 20:32:47  No: 150818  IP: 192.*.*.*

AAAAAさん、ありがとうございます。
データが残るようになりましたね。

問題は、追加ができるかなんです。
また、部分読み込みができる必要があります。
何十年ものデータを管理しなければなりませんので、
FileStream以外でもいいので、安心して使える方法を紹介してください。

よろしくお願いします。

編集 削除
AAAAA  2023-02-25 03:39:35  No: 150819  IP: 192.*.*.*

自作DBを作って そのDBを使ったDBアプリ(家計簿)を作ろうとしてるよね
市販のDB(BDEでも)使ったDBアプリうケーションにしたらどうだい?

ファイルの読み書きは1年単位にするとか一か月単位にするとか(ファイルを分ける)にすればファイルの操作なんて
関係なくなるけど

家計簿なら EXCEL のほうがいいよ

編集 削除
AS  2023-02-26 19:13:51  No: 150829  IP: 192.*.*.*

AAAAAさんへ

家計簿は子供のプログラムの勉強用です。
memo1を使って、かなりのころはできるようになりました。

私が何十年も使っているブロックリードは危険だといわれていたので、これを機会に新しい方法に変えようと思っているのです。
FileStreamでは無理なんですかね??


編集 削除
mam  2023-03-01 01:22:05  No: 150835  IP: 192.*.*.*

お子様のお勉強用なら、TStringGrid(jclとjvclをインストールしてTJvStringGridを使うほうがお勧めですが。並び替えもサポートしているので。)で表示してTStringListでcsvファイルに保存するのもお勧めかもです。
また、TClientDatasetだと、ファイルベースでフィルターも使えるのでお勉強にはいいかもですね。
いきなりStreamのお勉強はハードルが高いかもです。
外していたらすいません。

編集 削除
AT.W  2023-03-01 03:25:51  No: 150837  IP: 192.*.*.*

何十年というデータを扱うのであれば、データ量も大量になることが、当然想像つくが、
それを自前のデータファイル管理しようとか・・・

使い方の理解できないFileStreamで、どうにかしようとするより
AAAAAさんの仰るとおり、データベース化することを、おすすめする。

FireDACで扱うことができるSQLiteや、データベースコンポーネントつきAbsolute Database
https://www.componentace.com/bde_replacement_database_delphi_absolute_database.htm
なんかを使えばよろしかろう。

編集 削除
mam  2023-03-01 03:52:41  No: 150838  IP: 192.*.*.*

AAA様や、AT.W様のように(midas)データベースを使用するような方法です。
(別途インストールしないでDelphiが標準で搭載しているmidasを使用する)
但し、これではお勉強にならないかもです。
ほとんどコンポーネントとプロパティ設定だけで完成してしまうので。
Delphiってよくできていますよね。

TClientDataSetをフォームにドラッグ&ドロップ
TDataSourceとTDGBridをドラッグ&ドロップする

オブジェクトインスペクタで
DataSource1.DataSet:=ClientDataSet1
に設定する

オブジェクトインスペクタで
DGBrid1.DataSource:=DataSource1
に設定する

ClientDataSet1を右クリック⇒フィールドエディタ

フィールドの新規作成をクリックしてフィールドを追加する
  ID(id Integer Autoinc)、日付(date Date)、
  用途(usage String100)、金額(price currency)


オブジェクトインスペクタで
ClientDataSet1
のプロパティIndexesDefs[...]をクリックして「新規追加」ボタンを押し、
Fieldsにidを追加(name=ClientDataSetIndex1)する
ClientDataSetIndex1.Options.ixPrimary:=Trueに設定する
ClientDataSetIndex1.Options.ixUnique:=Trueに設定する

ClientDataSet1.IndexNameでidを選択する

ClientDataSet1.FileNameに'a.xml'などを入れる
(ClientDataSet1が閉じられるときに自動保存し、開かれる時に自動読み取りする)

//ClientDataSet1.OnNewRecordに以下を入れるとIDフィールドが自動的にインクリメントされる
procedure TForm1.ClientDataSet1NewRecord(DataSet: TDataSet);
var g:TAggregate;
    NewId:Integer;
begin
  ClientDataSet1.AggregatesActive:=False;
  ClientDataSet1.Aggregates.Clear;
  g:=ClientDataSet1.Aggregates.Add;
  g.Expression:='Max(id)';
  g.AggregateName:='MaxId';
  g.Active:=True;
  ClientDataSet1.AggregatesActive:=True;
  NewId:=ClientDataSet1.Aggregates[0].Value;
  Inc(NewId);
  ClientDataSet1.FieldByName('id').AsInteger:=NewId;
end;


ClientDataSet1を右クリックして
「データセットの作成」をクリックする

実行すれば、midasベースですが、データベースを別途インストールしなくても
簡易なmidasデータベースアプリの出来上がりです。
(Unit1.pasのuses に midasを追加することをお勧めします)

ClientDataSet1.Filter:='price>=100 and price<=200';
に好きにWhere句をいれて
ClientDataSet1.Filtered:=True;
にすれば、フィルター(SQLのwhere句で絞る)も出来ます。


//priceフィールドの合計はButton1.OnClickに以下で計算できます
procedure TForm1.Button1Click(Sender: TObject);
var g:TAggregate;
begin
  ClientDataSet1.AggregatesActive:=False;
  ClientDataSet1.Aggregates.Clear;
  g:=ClientDataSet1.Aggregates.Add;
  g.Expression:='Sum(Price)';
  g.AggregateName:='SumPrice';
  g.Active:=True;
  ShowMessage(Inttostr(ClientDataSet1.Aggregates[0].Value));
end;

編集 削除
AS  2023-03-01 18:33:31  No: 150841  IP: 192.*.*.*

mamさん、AT.Wさん、ありがとうございます。

正直、ブロックリードだけでプログラムは完成しているので、新しいfile操作の方法を教えてもらいたいのですが、Delphiにはないのでしょうか??
しばらく時間はかかると思いますが、教えていただいた方法も試してみます。

編集 削除
AAAAA  2023-03-02 06:43:56  No: 150849  IP: 192.*.*.*

家計簿って1日1行?

編集 削除
AS  2023-03-04 23:03:22  No: 150859  IP: 192.*.*.*

はい、1行でやっています。
本格的に作ると、1行ではダメな感じですが、プログラムの練習ですから。

編集 削除
HFUKUSHI  2023-03-06 06:24:20  No: 150867  IP: 192.*.*.*

> 新しいfile操作の方法を教えてもらいたい
教えてもらいましたよね?もういちどこの質問の最初の回答からひとつずつやり直してみてはいかがでしょう?
うまくいかないのは基本的にASさんの問題であって、Delphiの問題ではないです。
(おすすめはこの質問をいったん解決としたうえで、うまくいかなかったことを他の人にもわかるようにきちんと整理して別に質問をすることです)

編集 削除
AAAAA  2023-03-06 08:22:18  No: 150871  IP: 192.*.*.*

一応確認なんだけど、すでに出来上がっている家計簿のプログラムがあって
そこで使用している AssinFile とか Reset とか BlockRead を変えたいって話でいいんだよね?

編集 削除
AAAAA  2023-03-06 09:01:18  No: 150872  IP: 192.*.*.*

ためしてないけど 大体こんな感じなはず
procedure AssignFile(var F: TFILE; FILENAME: String);
begin
    F.FILENAME := FILENAME;
end;

procedure FileClose(var F: TFILE);
begin
    F.FileStream.Free;
    F.FileStream := nil;
end;

procedure Append(var F: TFILE);
begin
    if FileExists(F.Filename) = True then
    begin
      if Assigned(F.FileStream) = True then FileClose(F);     
      F.FileStream := TFileStream.Create(F.FILENAME,fmOpenWrite);
      F.FileStream.Position := F.FileStream.Size;
    end;
end;

procedure Rewrite(var F: TFILE; RecSize: Integer = 128);
begin
    if Assigned(F.FileStream) = True then FileClose(F);
    if FileExists(F.Filename) = True then DeleteFile(F.FILENAME);
    F.FileStream := TFileStream.Create(F.FILENAME,fmOpenWrite);
end;

function Eof(var F: TFILE): Boolean;
begin
    if F.FileStream.Position = F.FileStream.Size then RESULT := True else RESULT := False;  
end;

procedure Reset(var F: TFILE; RECSIZE: Integer = 128);
begin
    F.FileStream := TFileStream.Create(F.FILENAME,FILEMODE);
    F.RECSIZE := RECSIZE;
end;

function BlockRead(var F: TFILE; var Buffer; Count: Integer): LongInt;
begin
    RESULT := F.FileStream.Read(Buffer,F.RECSIZE * Count);
end;

procedure Seek(var F: TFILE; N: Integer);
begin
    F.FileStream.Position := N * F.RECSIZE;
end;

function FilePos(var F: TFILE): Int64;
begin
    RESULT := F.FileStream.Position;
end;

function FileSize(var F: TFILE): Int64;
begin
    RESULT := (F.FileStream.Size div F.RECSIZE);
end;

function BlockWrite(var F: TFILE; var Buffer; Count: Integer): LongInt;
begin
    RESULT := F.FileStream.Write(Buffer,F.RECSIZE * Count);
end;

編集 削除
AS  2023-03-21 08:35:50  No: 150893  IP: 192.*.*.*

AAAAAさん、ありがとうございます。

読ませていただきましたが、データはどの変数に入れるのでしょうか??

HFUKUSHIさんへ
①1~8日までのデータを一括で保存する
②作ったファイルに9日のデータを追加する
③6~9日のデータを読み込む
の3つのプログラムを紹介してください。
とお願いしているんですが?
よろしくお願いします。
分からないのならいいですので。

編集 削除
AAAAA  2023-03-21 09:21:59  No: 150894  IP: 192.*.*.*

TFILE = record
  FileStream: TFileStream
  Filename: String
  RecSize: Int64;
end

わすれてた

編集 削除
HFUKUSHI  2023-03-21 11:15:30  No: 150895  IP: 192.*.*.*

> の3つのプログラムを紹介してください。
> とお願いしているんですが?
ご自分で考えておつくりください。

> よろしくお願いします。
私はお断りします。他の優しい方は何かしら答えてくれるかもしれませんが。

> 分からないのならいいですので。
www

編集 削除
igy  2023-03-21 15:34:51  No: 150896  IP: 192.*.*.*

> ①1~8日までのデータを一括で保存する
> ②作ったファイルに9日のデータを追加する
> ③6~9日のデータを読み込む
> の3つのプログラムを紹介してください。
> とお願いしているんですが? 

は、これまでの投稿(AAAAA さんの投稿と、AS さんが試されたコード)で、
いくつか実現されているかと思うのですが、
現時点で、どこまで出来ていて、どこが出来ていない(判らない)のか、
改めて、提示するのは、いかがですか?

すでに、いくつか投稿があるのに、

> 新しいfile操作の方法を教えてもらいたいのですが、

と書かれると、HFUKUSHI さんの投稿にあるように、

> 教えてもらいましたよね?

と、他の人は、思うかもしれませんね。

編集 削除
AT.W  2023-03-22 04:27:29  No: 150897  IP: 192.*.*.*

> FileStream以外でもいいので、安心して使える方法を紹介してください。
安心して使える方法は、何一つありません。
理解できずに使えば、全て危険です。

TFileStreamは、使えます。
そもそも使い物にならないクラスが、標準で利用できるものでしょうか。
いったいどのような自信をもって発言されているのかわかりませんが、自分が扱えないからと言って、不良品の如く発言するのはやめていただきたい。

学習が目的と言いつつ、模範解答を得ようとしていませんか?
学習と言うなら、FileStreamの正しい使い方を学ぶことも当てはまるのでは?

学習とはなんたるか、まず、そこから考えていただきたいものである。

編集 削除
AAAAA  2023-03-22 11:56:06  No: 150898  IP: 192.*.*.*

procedure CloseFile(var F: TFILE);
begin
    F.FileStream.Free;
    F.FileStream := nil;
end;

から

function BlockWrite(var F: TFILE; var Buffer; Count: Integer): LongInt;
begin
    RESULT := F.FileStream.Write(Buffer,F.RECSIZE * Count);
end;
までをコメントにして

F: TFILE を F: FILE にしても動く
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

  TFILE = record
    FileStream: TFileStream;
    Filename: String;
    RecSize: Int64;
  end;

  TDATA = record
    Day: array[0..9] of AnsiChar;  //日付            //10byte
    Inc: Int64;                    //入金            //8byte
    Eat: Int64;                    //食費            //8byte
    Oth: Int64;                    //その他          //8byte
    Sum: Int64;                    //食費 + その他   //8byte
    Bal: Int64;                    //残金            //8byte 計 50byte
  end;

  TForm2 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form2: TForm2;

  //基本データ
  DATA:array[1..4] of TDATA=
    ((Day:'2023/02/01';InC:100000;Eat:0;Oth:0;Sum:0;Bal:100000),
     (Day:'2023/02/02';InC:0;Eat:1429;Oth:0;Sum:1429;Bal:98571),
     (Day:'2023/02/06';InC:0;Eat:3237;Oth:7240;Sum:10477;Bal:88094),
     (Day:'2023/02/08';InC:0;Eat:685;Oth:0;Sum:685;Bal:87409));

  //追加データ
  DATA2:array[1..1] of TDATA=
     ((Day:'2023/02/09';InC:0;Eat:479;Oth:0;Sum:479;Bal:86930));


implementation

{$R *.dfm}

procedure CloseFile(var F: TFILE);
begin
    F.FileStream.Free;
    F.FileStream := nil;
end;

procedure AssignFile(var F: TFILE; FILENAME: String);
begin
    F.FILENAME := FILENAME;
    F.FileStream := nil;
end;

procedure Rewrite(var F: TFILE; RecSize: Integer = 128);
begin
    if Assigned(F.FileStream) = True then CloseFile(F);
    if FileExists(F.Filename) = True then DeleteFile(F.FILENAME);
    F.FileStream := TFileStream.Create(F.FILENAME,fmCreate);
    F.RECSIZE := RECSIZE;
end;

procedure Reset(var F: TFILE; RecSize: Integer = 128);
begin
    if Assigned(F.FileStream) = True then CloseFile(F);
    F.FileStream := TFileStream.Create(F.FILENAME,FILEMODE);
    F.RECSIZE := RECSIZE;
end;

function Eof(var F: TFILE): Boolean;
begin
    if F.FileStream.Position >= F.FileStream.Size then RESULT := True else RESULT := False;
end;

function BlockRead(var F: TFILE; var Buffer; Count: Integer): LongInt;
begin
    RESULT := F.FileStream.Read(Buffer,F.RECSIZE * Count);
end;

procedure Seek(var F: TFILE; N: Integer);
begin
    F.FileStream.Position := N * F.RECSIZE;
end;

function FilePos(var F: TFILE): Int64;
begin
    RESULT := F.FileStream.Position;
end;

function FileSize(var F: TFILE): Int64;
begin
    RESULT := (F.FileStream.Size div F.RECSIZE);
end;

function BlockWrite(var F: TFILE; var Buffer; Count: Integer): LongInt;
begin
    RESULT := F.FileStream.Write(Buffer,F.RECSIZE * Count);
end;

//データ作成
procedure TForm2.Button1Click(Sender: TObject);
var
    F: TFILE;
    I: Integer;
begin
  AssignFile(F,'A.TXT');
    Rewrite(F,SizeOf(TDATA));
    for I := Low(DATA) to High(DATA) do
    begin
      BlockWrite (F,DATA[I],1);
    end;
    CloseFile(F);
end;

//全部表示
procedure TForm2.Button2Click(Sender: TObject);
var
    F: TFILE;
    DATA: TDATA;

    function XXX(Value: Int64): String;
    begin
      RESULT := '                ' + IntToStr(Value);
      RESULT := Copy(RESULT,Length(RESULT)-6,6);
    end;

begin
  AssignFile(F,'A.TXT');
    FILEMODE := fmOpenRead;
    Reset(F,SizeOf(TDATA));
    while Eof(F) = False do
    begin
      BlockRead(F,DATA,1);
      Memo1.Lines.Add(DATA.Day + ' ' + XXX(DATA.Inc) + ' ' + XXX(DATA.Eat) + ' ' + XXX(DATA.Oth) + ' ' + XXX(DATA.Sum) + ' ' + XXX(DATA.Bal));
    end;
    CloseFile(F);

end;

//追加
procedure TForm2.Button3Click(Sender: TObject);
var
    F: TFILE;
    I: Integer;
begin
  AssignFile(F,'A.TXT');
    FILEMODE := fmOpenWrite;
    Reset(F,SizeOf(TDATA));
    Seek(F,FileSize(F));
    for I := Low(DATA2) to High(DATA2) do
    begin
      BlockWrite (F,DATA2[I],1);
    end;
    CloseFile(F);
end;

//3-4
procedure TForm2.Button4Click(Sender: TObject);
var
    I: Integer;
    F: TFILE;
    DATA: TDATA;

    function XXX(Value: Int64): String;
    begin
      RESULT := '                ' + IntToStr(Value);
      RESULT := Copy(RESULT,Length(RESULT)-6,6);
    end;

begin
  AssignFile(F,'A.TXT');
    FILEMODE := fmOpenRead;
    Reset(F,SizeOf(TDATA));
    Seek(F,2);
    for I:= 1 to 2 do
    begin
      BlockRead(F,DATA,1);
      Memo1.Lines.Add(DATA.Day + ' ' + XXX(DATA.Inc) + ' ' + XXX(DATA.Eat) + ' ' + XXX(DATA.Oth) + ' ' + XXX(DATA.Sum) + ' ' + XXX(DATA.Bal));
    end;
    CloseFile(F);

end;

procedure TForm2.FormCreate(Sender: TObject);
begin
    Memo1.Font.Name := 'MS ゴシック';

end;

end.

編集 削除
AS  2023-03-24 20:35:52  No: 150899  IP: 192.*.*.*

AAAAAさん、ありがとうございました。

やはり、この方法以外にはありませんか。
20年以上前に教えてもらった方法です。
この方法以外に何かないかと質問していたのです。

あきらめがつきました。
解決の印はつけませんので、
また何かありましたらお願いします。

  AssignFile(F1, fileName);         // 入力ファイルを開く
  Reset(F1, SizeOf(Dtype));           // byte単位に変更する
  FileMode := 0;                      // ファイルモードを読み出し専用に設定する
  try
    Reset(F1, SizeOf(DType));
    seek(F1,N-haba);                 // ファイルは0から始まるから
    BlockRead(F1, S1, Haba, readDdNum);
  finally
    CloseFile(F1);
  end;


編集 削除
AAAAA  2023-03-24 21:45:54  No: 150900  IP: 192.*.*.*

いや・・・・・
FileStream 使用してるやん

FileStreamの使い方が理解できてなさそうだから AssignFile とかの形式にまねただけで

1日1行って事は365行しかないわけで StringList に読み込んじゃったほうが良い気がするけど

編集 削除
AS  2023-03-30 23:13:27  No: 150910  IP: 192.*.*.*

AAAAAさん、すみません。
研究してみます。

編集 削除
AS  2023-03-31 21:44:27  No: 150924  IP: 192.*.*.*

AAAAAさん、ありがとうございました。

部分呼び出しはできるようになっていますね。
ただ、追加ができないような。
こちらも研究してみますが、確認をお願いします。

編集 削除
AS  2023-03-31 22:06:07  No: 150925  IP: 192.*.*.*

AAAAAさん、完成しています。
ありがとうございました。

今後もよろしくお願いします。

編集 削除