首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi XE6中数据call服务器方法调用后的文件删除

Delphi XE6中数据call服务器方法调用后的文件删除
EN

Stack Overflow用户
提问于 2016-06-09 13:56:48
回答 2查看 444关注 0票数 3

我有一个用Delphi XE6编写的Datasnap客户端服务器应用程序。我正在调用一个服务器方法,该方法使用TFileStream创建临时文件,从我的http post中以TStream格式填充它,并将其返回给我的客户端。这一切都在必要时起作用。但是,在方法的末尾,我调用deleteFile方法从服务器中删除临时文件,但它从未被删除。我做错了什么?

代码语言:javascript
复制
var
  r,f: String;
  SS: TStringStream;
  Uid: TGuid;
begin
   CreateGuid(Uid);
   f:= ChangeFileExt(GuidToString(Uid),'.rpt');
   result:= TFileStream.Create(f, fmCreate or fmOpenWrite);

  r := getRunReportJSON(ARunReportObj);
  SS := TStringStream.Create(r, TEncoding.ASCII);
  try
    try      
      ServerContainer1.idHttp1.Post(gUrl, SS, result);
      Result.Position:= 0;
    except
    end;
  finally
    SS.Free;
    if FileExists(f) then
      DeleteFile(f)
  end;
end;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-09 16:45:19

正如David所说,在TFileStream被首先销毁之前,您不能删除该文件,这样它就可以关闭该文件的句柄。如果希望在服务器使用完文件后自动删除该文件,则可以:

  1. 直接使用Win32 CreateFile()函数打开文件,以便指定FILE_FLAG_DELETE_ON_CLOSE标志,然后用THandleStream类包装得到的句柄。 类型TMyHandleStream =类(THandleStream)公共析构函数破坏;重写;结束;析构函数TMyHandleStream.Destroy;begin继承;CloseHandle(句柄);end;var h: THandle;r,f: String;SS: TStringStream;Uid: TGuid;begin CreateGuid(Uid);f := 'C:\some文件夹\‘+ GuidToString(Uid) +’..rpt‘;H := Windows.CreateFile(PChar(f),GENERIC_READ或GENERIC_WRITE,FILE_SHARE_READ,nil,CREATE_ALWAYS,FILE_FLAG_DELETE_ON_CLOSE,0);如果h= INVALID_HANDLE_VALUE,RaiseLastOSError;结果:= TMyHandleStream.Create(h);尝试r := getRunReportJSON(ARunReportObj);Result.Position := 0;除Result.Free外;提高;结束;结束;
  2. TFileStream派生一个新类并重写其析构函数以删除该文件: 类型TMyFileStream =类(TFileStream)公共析构函数破坏;覆盖;结束;析构函数TMyFileStream.Destroy;开始继承;DeleteFile(Self.FileName);结束;

变量r,f: String;SS : TStringStream;Uid: TGuid;begin CreateGuid(Uid);f :=‘C:\CreateGuid’+ GuidToString(Uid) +‘..rpt’;结果:= TMyFileStream.Create(f,fmCreate或fmOpenReadWrite);尝试r := getRunReportJSON(ARunReportObj);SS := TStringStream.Create(r,TEncoding.ASCII);Result.Position := 0;除Result.Free外;提高;结束;结束;

  1. 使用TFileStreamEx类,如这个论坛的答案所示: 类型TFileStreamEx = class(THandleStream)公共构造函数创建( const FileName: string;Mode: Word;标志: DWORD = FILE_ATTRIBUTE_NORMAL);析构函数破坏;重写;结束;构造函数TFileStreamEx.Create(const FileName: string;Mode: Word;标志: DWORD = FILE_ATTRIBUTE_NORMAL);const AccessMode: array0 0.2 of LongWord =( GENERIC_READ,GENERIC_WRITE,GENERIC_READ或GENERIC_WRITE);ShareMode: array0.4 of LongWord =( 0,0,FILE_SHARE_READ,FILE_SHARE_WRITE,FILE_SHARE_READ或FILE_SHARE_WRITE);如果FILE_SHARE_READ= fmCreate然后开始继承创建( CreateFile( PChar(FileName),GENERIC_READ或GENERIC_WRITE,0,0,nil,CREATE_ALWAYS,标志0) );如果句柄= INVALID_HANDLE,则引发EFCreateError.CreateFmt(SFCreateError,FileName);end PChar开始继承创建( CreateFile( PChar(FileName),AccessModeMode和3,ShareMode(Mode和$F0) shr 4,0,OPEN_EXISTING,标志,0 );如果句柄= INVALID_HANDLE,则提升EFOpenError.CreateFmt(SFOpenError,FileName);结束;结束;析构函数TFileStreamEx.Destroy;如果句柄<>开始,那么CloseHandle(句柄);结束;

变量r,f: String;SS: TStringStream;Uid: TGuid;begin CreateGuid(Uid);f :=‘C:\ :=’‘+ GuidToString(Uid) +’..rpt‘;结果:= TFileStreamEx.Create(f,fmCreate或fmOpenReadWrite,FILE_FLAG_DELETE_ON_CLOSE);尝试r := getRunReportJSON(ARunReportObj);SS:= TStringStream.Create(r,TEncoding.ASCII);尝试ServerContainer1.IdHTTP1.Post(gUrl,SS,Result);最后是SS.Free;结束;Result.Position := 0;除Result.Free;提高;结束;

票数 5
EN

Stack Overflow用户

发布于 2016-06-09 14:50:23

在销毁了文件流对象之前,不能删除您创建的文件流。文件流对象包装文件句柄,当文件句柄存在时,它后面的文件对象不能被删除。

在删除文件流对象之前,需要销毁它。

您的代码有一些非常奇怪的异常处理。它在功能的中间不加歧视地吞食例外。你真想这么残忍吗?在try/try块之外,任何异常都会导致文件流对象泄漏。

在删除该文件之前,测试该文件是否存在并没有多大意义。如果您成功地创建了文件流,那么您可以确信该文件是存在的。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37728036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档