【问题标题】:Delphi TStreamReader - How to read in a shareable mode?Delphi TStreamReader - 如何以共享模式阅读?
【发布时间】:2018-12-17 17:03:34
【问题描述】:

我在 Delphi Tokyo 中编写了一个例程,它接收多个文件(例如 CSV)并将它们合并在一起,让用户可以选择忽略除第一个文件之外的所有文件的第一行(因为 CSV 文件通常有标题行/column name 行,合并文件时,我只想要一份标题)。我遇到的问题是,即使我只读取各种输入文件,如果文件在另一个进程(特别是 Excel)中打开,我的应用程序会给出错误:“无法打开文件。进程无法访问文件,因为它正被另一个进程使用。”

我正在使用 TStreamReader。我如何告诉 TStreamReader 它应该以只读方式打开文件......并且即使文件在其他地方打开也继续?

代码如下:

procedure glib_MergeTextFiles(const InFileNames: array of string; const OutFileName: string;
          HasHeader: Boolean = True;
          KeepHeader: Boolean = True);
var
  I: Integer;
  InStream: TStreamReader;
  OutStream: TStreamWriter;
  Line: string;
  IsFirstLine: Boolean;
begin
  // Create our output stream
  OutStream := TStreamWriter.Create(OutFileName, False, TEncoding.UTF8);
  try
    for I := 0 to high(InFileNames) do
    begin
      InStream := TStreamReader.Create(InFileNames[I], TEncoding.UTF8);
      IsFirstLine := True;
      try
        while not InStream.EndOfStream do
        begin
          Line := InStream.ReadLine;

          if IsFirstLine then { First Line }
          begin
            if HasHeader = False then
            begin
              OutStream.WriteLine(Line);
            end
            else
            begin
              // Is First Line, Has Header
              if I = 0 then  {is first file}
                OutStream.WriteLine(Line);
            end;
          end
          else
          begin
            OutStream.WriteLine(Line);
          end;

          IsFirstLine := False;
        end;

      finally
        InStream.Free;
      end;

    end;
  finally
    OutStream.Free;
  end;
end;

【问题讨论】:

  • 这就是它的作用。 TStreamReader 使用 fmOpenRead 创建其 TFileStream。
  • @Sertac - 我会有这样的想法。收到您的评论后,我设置了另一个测试。新文件(所以没有其他应用程序使用它们)等...我打开了 test.csv 文件 EXCEL,然后运行合并 file1.csv 和 test.csv 的例程。我收到 EFOpenError 消息“无法打开文件 test.csv。文件...被另一个进程使用”.. 错误发生在“InStream := TStreamReader.Create(InFiles[i], TEncoding.UTF8);
  • 看起来您可以将流传递给流阅读器构造函数。所以这应该是可能的。
  • 线索就在名字里,它是一个流阅读器。给它一个阅读流。

标签: delphi


【解决方案1】:

问题在于共享模式。默认情况下,流阅读器创建一个只读文件流,但不指定共享模式,因此它以独占方式打开文件。但是,要打开已在其他地方打开的文件进行读取,该文件必须先前已使用FILE_SHARE_READ 标志打开以共享读取访问权限:

FILE_SHARE_READ
0x00000001

启用对文件或设备的后续打开操作以请求读取访问权限。

否则,如果其他进程请求读取访问权限,则无法打开文件或设备。

如果未指定此标志,但已打开文件或设备进行读取访问,则函数失败。

您可以将自己的文件流传递给流阅读器,以您喜欢的模式打开:

var
  I: Integer;
  FileStream: TFileStream;
  InStream: TStreamReader;
  ..
begin
...
  FileStream := TFileStream.Create(InFileNames[I], fmOpenRead or fmShareDenyNone);
  try
    InStream := TStreamReader.Create(FileStream, TEncoding.UTF8);
    try
      ..

同样,这需要 Excel 在打开文件时执行相同的操作,但通过我的简单测试,它看起来确实如此。

【讨论】:

  • 爱它。谢谢
猜你喜欢
  • 2013-05-10
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 2020-10-05
相关资源
最近更新 更多