読み取り専用で開く

解決


ふー  2008-04-12 04:59:31  No: 30468

ファイル操作について質問させてください。

普通ファイルを他のアプリケーションが使用していると、
Delphiからは開けませんよね。
ところが、一部のテキストエディタなどは読み取り専用とすることで
ファイルを開くことができます(MicrosoftOffice等)。
あれはどうやっているのでしょうか?


ほんとに?  2008-04-12 06:07:43  No: 30469

LoadFromFileなら開けると思うけど。
内部的には、LoadFromFileは以下のように「読み取り専用 + 他からの書き込みを禁止」で開いている。

var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;


ふー  2008-04-14 22:34:55  No: 30470

回答ありがとうございます。
TextFileとAssignfileで読み込んでいたので、読み込めなかったのだろうと思います。

ところでFilestreamを使用して60万行ほどあるテキストを読み込みたいのですが、
ファイルを開いてから一行ずつ読み込む方法がわからないんです。
いままではReadlnで読み込んでいたのですが、
Filestreamで同じことをするにはどうしたらいいのでしょうか?
どうやらRead関数を使う場合一行あたりの長さがわかっていないといけないようなので、
不定である今回の場合は使えないようだということがわかっています。

ご教授いただければと思います。


真っ平御免  2008-04-15 01:26:21  No: 30471

>ご教授いただければと思います。
"ご教授"などということは、真っ平御免こうむりたい。
"教えてほしい"ということなら、以下の通り。

ファイルからの一行単位の読み込みは効率が悪いので、バッファサイズ単位で読み込む。

procedure TForm1.Button1Click(Sender: TObject);
const
  BUF_SIZE = $4000-1;
var
  NumRead: DWORD;
  PosRead: INT64;
  pT, pH, Buf: PChar;
begin
 with TOpenDialog.Create(nil) do try
  if not Execute then exit;

  GetMem(Buf, BUF_SIZE+1);
  PosRead := 0;
  try
   with TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) do try
    repeat
     NumRead := Read(Buf^, BUF_SIZE);
     Buf[NumRead] := #0;
     pH := Buf;
     pT := pH;
     while pT-Buf < BUF_SIZE do begin
      while not(pT^ in [#0,#10,#13]) do inc(pT);
      if pT^ <> #0 then begin
       pT^ := #0;
       Memo1.Lines.Add(pH);   // 切り出した一行の処理
       inc(pT, 2);            // CRLFを読み飛ばし
       pH := pT;
      end else begin
       pT := pH;
       break;
      end;
     end;
     inc(PosRead, pT - Buf);
     Position := PosRead;
    until NumRead < BUF_SIZE;
    Memo1.Lines.Add(pH);      // 最終行切り出し処理
   finally
    Free;
   end;
  finally
   FreeMem(Buf);
  end;
 finally
  Free;
 end;
end;


ふー  2008-04-15 03:38:37  No: 30472

ありがとうございました。
無事に解決することができました。


ふー  2008-04-16 06:46:58  No: 30473

すいません。
再度お教え願います。

真っ平御免さんの方法を使わせていただきました。
読み込みは無事に成功したのですが、やはり読み込み速度が上がりません。
どうも
>while not(pT^ in [#0,#10,#13]) do inc(pT);
で一文字ずつ読んでいるのが原因だと思われるのですが・・・
ReadlnやObject.Linesなどのように一行を高速に読むことはできないのでしょうか?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加