我在Delphi Tokyo编写了一个例程,它接受多个文件(例如CSV)并将它们合并在一起,让用户可以忽略除第一行之外的所有文件的第一行(因为CSV文件通常有标题行/列名)在合并文件时,我只想要一个标题的副本).我遇到的问题是,即使我只读取各种输入文件,如果文件在另一个进程中打开(特别是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;
Run Code Online (Sandbox Code Playgroud)
问题在于共享模式.默认情况下,流阅读器会创建一个文件流以供只读,但不指定共享模式,因此它会打开文件以进行独占访问.但是,要在已在其他位置打开文件时打开文件进行读取,必须先使用该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
..
Run Code Online (Sandbox Code Playgroud)
同样,这需要Excel在打开文件时执行相同操作,但是通过我的简单测试,它看起来就像它一样.
| 归档时间: |
|
| 查看次数: |
525 次 |
| 最近记录: |