【问题标题】:How to save a TFilestream to hard drive with Lazarus如何使用 Lazarus 将 TFilestream 保存到硬盘
【发布时间】:2016-09-28 02:20:16
【问题描述】:

我在更改某些值后保存 xml 文件时遇到问题。 我使用 Lazarus 1.6 作为 FPC 版本 3.0.0 的 IDE 这是我在这篇文章中使用的 xml 文件的结构:

<?xml version="1.0" encoding="UTF-8"?>
 <wbpickeys>
  <picture>
    <name>C:\IMG_1.JPG</name>
    <imagedate>p-06/04/2014 16:22:10</imagedate>
    <favorit>n</favorit>
    <remark>aaa</remark>
    <drive>DRIVE_FIXED</drive>
  </picture>
</wbpickeys>

我使用以下 uses 子句(可能并非所有这些都是必需的,但我认为至少重要的一次是可用的):

uses
Windows, ShellAPI, FileUtil, Graphics, Menus, ComCtrls, ExtCtrls, ExtDlgs, Classes, SysUtils, LResources, Forms, Controls, StdCtrls, Dialogs, CheckLst, Buttons, inifiles,
laz2_DOM, laz2_XMLRead, laz2_XMLWrite, laz2_XMLCfg, laz2_XMLUtils, laz_XMLStreaming;

在程序启动时,我将此 xml 文件加载到 Tfilestream (g_stream: TfileStream) 中。这样做的原因是在程序运行期间具有独占访问权限。 为此,我使用以下打开函数:

function open_xml:Boolean;
begin
    if g_stream <> nil then FreeAndNil(g_stream);
    try
            //with load from (TFile)-Stream the xml file can be opened with Share Exclusive
            //when loading only from file there is no possibility to open it exclusive
            g_stream:= TFileStream.Create('wbpickeys.xml',fmShareExclusive);
            //Read the XML file into an XML Document
        readxmlfile(g_wbpickeys,g_stream);
            result:= true;
    except
        on E:EFOpenError do
        begin
             beep();
                MessageDlg
        (
          //br is defined as a constance for line feed
        '*** A T T E N T I O N ***' + br + br +
          'When trying to open the file for the keywords' + br +  '"wbpickeys.xml"' + br +
          'the following error occurs:' + br +
          E.Message + br +
          'Please check if the file is available' + br +
          'or deleted or moved or what else',mtError,[mbOK],0
        );
        result:= false;
        end;
    end;
end;

比我改变一个子节点的文本值:

procedure TForm1.BChangeNodeClick(Sender: TObject);
var
  pictures          : TDOMNodeList;
  pic, tempnode     : TDOMNode;
  i                 : integer;
begin
  // Get all nodes with name "picture"
  pictures:= g_wbpickeys.GetElementsByTagName('picture');
  // For all Member nodes
  for i:= 0 to pictures.Count - 1 do
  begin
    pic:= pictures[i];
    tempnode:= pic.FindNode('remark');
    // if content is 'bbb' change it
    if(tempnode.TextContent = 'bbb') then
    begin
      tempnode.TextContent:= 'aaa';
      //than I try to save the xmldocument to the hard drive    
      writeXMLFile(g_wbpickeys,'wbpickeys.xml');
    end;
end;

这是我的问题: 新文本已设置,我可以在备忘录中看到结果。但该值仅在运行时加载 xml 的内存中发生更改,但并未物理更改到硬盘驱动器上的文件。 我几乎浏览了整个网络,但找不到将流保存到硬盘驱动器上相应文件的解决方案。

如果我使用这个 “writeXMLFile(g_wbpickeys, ‘wbpickeys.xml’);” 我在文件 lazutf8classes.pas 第 143 行中收到 EFCreateError “无法创建文件 wbpickeys.xml”。

问题是我不想创建一个 xml 文件——我想更改一个现有的。

比我寻找将流保存到磁盘上的文件的可能性。不幸的是,我没有找到任何东西。

当然我犯了一个错误,但我看不到它。谁能告诉我?

【问题讨论】:

  • 创建另一个文件流并复制到该流

标签: xml save filestream xmldocument lazarus


【解决方案1】:

当您将修改后的文档写回磁盘时,您必须替换整个文件,您不能将操作限制为仅修改后的节点。因此,您必须先删除旧的 xml 文件(或者更好:重命名它,以防在写入过程中出现问题),然后使用 WriteXMLFile 写入文档。或者写入一个新的临时文件名,以保持原始文件一直锁定;然后销毁读取流(结束独占访问),删除原始文件并将新文件重命名为旧文件。

【讨论】:

  • 哇——听起来真的很复杂。 Bevor 我使用了 Delphi,而且要容易得多。但是好的,非常感谢您的回复!
  • 复杂?我无法想象如何简化这一点。而且我无法想象 Delphi 在原则上如何做到这一点。
  • 我不是真正的专家,但我猜想使用 delphi 和 writeXML 函数不会创建 xml,但此函数会更改现有文件。可能是在后台执行的功能相同 - 删除现有的并编写一个新的。但这比这更有效,无需让用户考虑。无论如何 - 我听从了你的建议,它奏效了。非常感谢安德烈亚斯
猜你喜欢
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多