すいません、少し調べてみましたが、分からずに困っています。
Appendは、ファイルの最後に追加しますが、それの逆のセオリーはどうするのでしょうか?
自分でも考えたのですが、無駄が多い気がするのと、自信がなくって。^^;
Appendの逆の関数がないみたいですが、もしあったら、バカみたいですし。
ファイルを開く。
1番上に書くのを新規で書き込み。
開いたファイルの内容を、ループして書き込み。
//ファイルを開く
FStrBuf := TStringList.Create;
FStrBuf.LoadFromFile(FileName);
//新規の作成用
Rewrite( fp );
FStrBuf.count-1をループして、追加保存。
ファイル保存の関数を作りたいと思っているので、FileSave('ファイル名','追加する文')としたいので、Memoとかは使いたくないのですが。^^;
セオリーがあれば、ご教授お願い致します。
TStringList を使って
・LoadFromFile メソッドでファイルを読み込み
・Insert メソッドで、挿入
・SaveToFile メソッドでファイル保存
でどうですか?
お目汚しかもしれませんが、一応できたものを公開。
ファイルセーブといえば、成功不成功の戻り値と思って、functionにしたけど、procedureでも問題ないですね。
ファイルの存在チェックを先にやることにしたので、意味がなくなりました。
開けたけど、書き込みない場合は、エラーになるか。x
こちらの方が、私の用途に合っているのと、tryとかがよく分からなかったので。
お尻から何番目、、、という形も考えたのですが、使い勝手が悪いので、やめました。
//===================================================================
//ファイルの保存(自作
//FN,Line : ファイル名、追加書き込み、Inc:挿入場所、-ならお尻に。
//Result:意味がないですね。
//===================================================================
function TForm1.FileSave2(FN,Line:String;Inc:Integer) : Boolean;
var
FStrBuf : TStringList;
F : TextFile;
begin
//ファイルチェック
if not FileExists( FN ) then
begin
//空ファイルを作成
AssignFile(F, FN);
Rewrite(F);
CloseFile(F);
end;
//ファイルを開く
FStrBuf := TStringList.Create;
FStrBuf.LoadFromFile(FN);
//マイナスの場合は、お尻に
If Inc < 0 then
Inc := FStrBuf.Count;
//ラインの挿入
FStrBuf.Insert(Inc, Line);
//ファイルに保存
FStrBuf.SaveToFile(FN);
//解放
FStrBuf.Free;
end;
問題はないと思いますが、「へったくそだなー、もっと簡単になるよ。」という場合は、訂正して頂けると幸いです。
変数の名前の付け方は、ちょっと独特かもしれませんが、独学なのでご容赦くだされ。
もう少し開いておこうかと思います。
とりあえず、igyさんサンクスです。
LoadFromFile の直前にFileExists判定入れるだけでいいのは?
FStrBuf := TStringList.Create;
if FileExists( FN ) then
FStrBuf.LoadFromFile(FN);
//ファイルチェック
ここのがAssignFile〜CloseFileが不要になる。
こんな感じでどうでしょう。
少し長いです。冗長かも。
大きいファイルを扱う場合や、メモリ使用量が気になる場合には効果があるかと思います。
(**
* ファイルの先頭に行を追記する。
* FileName: String 対象ファイルの名前
* Line: String 追記する文字列。最後の改行はこの関数で必ず付ける
* IsBackup: Boolean バックアップしたファイルを消すならfalse
*)
function FileSave(const FileName, Line: String; IsBackup: Boolean): Boolean;
var
isExistFile: Boolean;
BackupFileName: String;
hReadFile: Cardinal;
hWriteFile: Cardinal;
Buf: String;
Len: Cardinal;
begin
Result := False;
BackupFileName := ChangeFileExt(FileName, '.BAK');
isExistFile := FileExists(FileName);
if FileExists(BackupFileName) then
begin
if DeleteFile(BackupFileName) = false then
begin
Exit;
end;
end;
hReadFile := INVALID_HANDLE_VALUE;
if isExistFile then
begin
//元のファイルを*.BAKに変更
if RenameFile(FileName, BackupFileName) = false then
begin
Exit;
end;
//バックアップしたファイルを開く
hReadFile := CreateFile(PCHAR(BackupFileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hReadFile = INVALID_HANDLE_VALUE then
begin
if isExistFile then
begin
RenameFile(BackupFileName, FileName);
end;
Exit;
end;
end;
//ファイルを開く
hWriteFile := CreateFile(PCHAR(FileName), GENERIC_WRITE, 0, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
if hWriteFile = INVALID_HANDLE_VALUE then
begin
CloseHandle(hReadFile);
if isExistFile then
begin
RenameFile(BackupFileName, FileName);
end;
Exit;
end;
//追記分
Buf := Line + #13#10;
WriteFile(hWriteFile, PCHAR(Buf)^, Length(Buf), Len, nil);
//残りをコピー
SetLength(Buf, 1025);
if hReadFile <> INVALID_HANDLE_VALUE then
begin
while True do
begin
ReadFile(hReadFile, PCHAR(Buf)^, 1024, Len, nil);
if Len = 0 Then Break;
WriteFile(hWriteFile, PCHAR(Buf)^, Len, Len, nil);
end;
CloseHandle(hReadFile);
end;
//閉じる
CloseHandle(hWriteFile);
//バックアップがいらないなら消す
if Not IsBackup then
begin
DeleteFile(BackupFileName);
end;
Result := True;
end;
みなさま、私の様な素人に毛が生えたものに、コメントありがとうございました♪
さらにちょっと手を加えて、追加書き込みしかできなかったので、上書きもできるようにしました。
一応フォルダの存在チェックもするように。
function TForm1.FileSave2(FN,Line,New:String;Inc:Integer) : Boolean;
//パスを絶対パスに
Path := ExpandFileName(FN);
//上書きなら削除
if New = 'On' then DeleteFile(Path);
//フォルダチェック
if not DirectoryExists( ExtractFileDir( Path ) ) then
MkDir( ExtractFileDir( Path ) );
引数に、Newのon/offを指定して、絶対パスに変換、onなら削除。
フォルダがなかったら、作成です。
削除にがどのタイミングで、次にいくのか分からなかったのですが、1Gのテキストで、onにしても大丈夫だった(たぶん、完全に削除されてから、次の処理に)まぁ、大丈夫なのかなー?と。
本来ならロック処理や別ファイル名にしての方がいいのでしょうが、私レベルではそれ程問題はないだろう、・・・面倒なので、やめました。
PHP育ちなもので、ファイルの読み書きのような、セオリーの書き込みがあるものを、考えるのは少し苦手です。
つい、人のを参考・・・、考えてから丸パクリにしてしまうので。^^;
igy様、自分なら・・・様、にしの様、ありがとうございました。
とくに、にしの様のサンプルは大変貴重です。(苦笑
じっくり見てから、使う場面があれば、使わせていたこうかと思います。
やはり、大きなファイルを読み書きする時は、一行ずつの方が、メモリーを食わなさそうですね。
ありがとうございます。
ツイート | ![]() |