Delphi:如何捕获TStreamWriter磁盘已满错误?

Delphi:如何捕获TStreamWriter磁盘已满错误?,delphi,error-handling,filestream,writer,Delphi,Error Handling,Filestream,Writer,我想知道,为什么这段代码没有像它应该捕获的那样捕获“磁盘已满”错误 这一点很重要,因为如果用户没有注意到保存失败,他们的数据可能会丢失 我不明白这个 procedure TForm2.按钮1单击(发送方:TObject); 变量 作者:TStreamWriter; n:整数; 开始 Writer:=TStreamWriter.Create('MyUTF8Text.txt',false,TEncoding.UTF8); 最后试试 试试看// 对于n:=1到1000 do 开始 WriteLine(

我想知道,为什么这段代码没有像它应该捕获的那样捕获“磁盘已满”错误

这一点很重要,因为如果用户没有注意到保存失败,他们的数据可能会丢失

我不明白这个

procedure TForm2.按钮1单击(发送方:TObject);
变量
作者:TStreamWriter;
n:整数;
开始
Writer:=TStreamWriter.Create('MyUTF8Text.txt',false,TEncoding.UTF8);
最后试试
试试看//
对于n:=1到1000 do
开始
WriteLine('测试文本写入UTF-8文件');
结束;
除了
关于E:Exception-do
开始
ShowMessage('异常类名:'+E.ClassName);
ShowMessage('异常消息:'+E.Message);
结束;
完除了
最后
Writer.Free();
结束//最后
结束;
“顺便说一句,‘编写器可能未初始化’警告,真的严重吗?”

编辑:出现此警告,因为TStreamWriter.Create是在尝试后创建的。 谢谢你的建议,在(!)尝试之前,我已将该行代码更正到正确的位置。

尝试以下操作:

procedure WriteStream;
var
  Writer: TStreamWriter;
  fs: TFileStream;
  s: String;
  n, bytesWritten : integer;
begin
  bytesWritten := 0;
  fs := TFileStream.Create('MyUTF8Text.txt', fmCreate);
  try
    //avoid warning by initiaizing before try
    Writer := TStreamWriter.Create(fs);
    try //Finally
      try //Except
        for n := 1 to 10 do
        begin
          s := 'Testing text writing to the UTF-8 file.'  + '#13#10';
          //keep count of bytes written
          bytesWritten := bytesWritten + TEncoding.UTF8.GetByteCount(s);
          Writer.Write(s);
        end;
        Writer.Flush;
        Writer.Close;
        //Check stream size to make sure all bytes written
        if bytesWritten <> Writer.BaseStream.Size then
          raise Exception.Create(String.Format('Expected %d bytes, wrote %d', [Writer.BaseStream.Size, bytesWritten]));
      except
        on E: Exception do
        begin
          Showmessage('Exception Class name: ' + E.ClassName);
          Showmessage('Exception Message: ' + E.Message);
        end;
      end; // except
    finally
      Writer.Free; // Will only free if it has been constructed
    end; //finally
  finally
    fs.Free;
  end;
end;
procedure WriteStream;
变量
作者:TStreamWriter;
fs:TFileStream;
s:字符串;
n、 字节数:整数;
开始
字节写入:=0;
fs:=TFileStream.Create('MyUTF8Text.txt',fmCreate);
尝试
//在尝试之前初始化以避免警告
Writer:=TStreamWriter.Create(fs);
最后试试
试试看//
对于n:=1到10 do
开始
s:=“正在测试写入UTF-8文件的文本。”+“#13#10”;
//保持写入的字节数
BytesWrited:=BytesWrited+TEncoding.UTF8.GetByteCount(s);
作者:写;
结束;
作者:同花顺;
作者:关闭;
//检查流大小以确保写入所有字节
如果是bytesWriter.BaseStream.Size,则
引发异常.Create(String.Format('Expected%d字节,writed%d',[Writer.BaseStream.Size,byteswrited]);
除了
关于E:Exception-do
开始
Showmessage('异常类名:'+E.ClassName);
Showmessage('异常消息:'+E.Message);
结束;
完除了
最后
Writer.Free;//只有在建造完成后才能免费使用
结束//最后
最后
财政司司长:免费;
结束;
结束;

如果TStreamWriter的构造函数引发异常,则不会初始化写入程序。是的,这很严重。惯用的方法是在
try
try…finally块之前创建对象,当嵌入try…except块时,try…finally块毫无意义。你想从另一个角度看。。。就像Ken指出的,你想在try块开始之前创建一个对象,Ken说得很对
Writer
是非托管类型的局部变量,因此未初始化。看,它最初是一个随机指针。如果
TStreamWriter.Create(…)
引发异常(这种情况不太可能发生),析构函数将自动运行并处理半创建的流编写器。由于该异常,
Writer
将不会被分配一个指向对象的指针(没有新对象!),因为执行将移动到
除了
,然后移动到
,最后移动到
,这样您就可以在随机ptr
Writer
上执行
Writer.Free
。那太糟糕了。始终使用成语
X:=TX.Create;尝试{use X}最后X.Free;结束
。无论如何,引发异常的是
TStreamWriter.Create
?小的挑剔-
TEncoding.UTF8.GetByteCount
可以是
Writer.Encoding.GetByteCoint
。这样,如果您决定更改使用的
TEncoding
,您只需更新1行代码(构造函数)而不是2行代码。请注意,此解决方案不会捕获磁盘已满问题(即如果TFilestream.Create失败)…
“#13#10”
可能应该是
#13#10
。答案不需要
+
操作符.Thansk。Tav,你的代码工作正常,谢谢!不过,我希望解决办法会更简单。类似于将备忘录文本保存到UTF-8文件,如下所示:var myEncoding:TEncoding;开始myEncoding:=TEncoding.UTF8;尝试Memo1.Lines.SaveToFile('myUTF8file.txt',myEncoding);除了E:Exception do begin Showmessage('Exception类名:'+E.ClassName);//这将给出:“EWriteError”Showmessage('异常消息:'+E.Message);//这将导致:“流写入错误”磁盘未满-112“空间不足”错误。。。结束;完除了结束;是的,Tav的代码提供了一个解决方案,但主要问题仍然存在:如何捕获磁盘已满错误?或者流I/O处理与传统的文件管理完全不同?