簡體   English   中英

Delphi:Indy TIdTCPClient讀取XML

[英]Delphi: Indy TIdTCPClient Reading XML

我正在打開與TidTCPClient到服務器的套接字連接。 服務器開始向我發送不同XML數據的提示音。 但是ReadLn不能幫助我,因為我不知道xml在哪里開始和停止。 因此,我決定使用Capture。 這是正確的。 但是,正如我從文檔捕獲中讀取的那樣,它也稱為ReadLn,表示它逐行讀取。 30到40行XML有時需要1到2秒才能讀取。 所以我需要更快地閱讀。 我可以使用ReadStream或其他有區別的東西嗎?

我現在使用的代碼:

procedure TfrmMain.ThreadRun(Sender: TIdThreadComponent);
var
  FData: TStringList;
  FMemory: TStringStream;
begin
  if Client.Connected = False then Exit;
  FData := TStringList.Create;
  Client.IOHandler.Capture(FData, '', False);
  FMemory := TStringStream.Create('',TEncoding.UTF8);
  FMemory.WriteString(FData.Text);
  CoInitialize(Nil);
  QInsert.ParamByName('XMLData').LoadFromStream(FMemory,ftBlob);
  QInsert.Execute;
  CoUninitialize;
  FMemory.Free;
  FData.Free;
end;

如您所見,我正在將XML數據插入到本地表中,並且此過程非常快,具體取決於XML的大小,需要15ms到60ms,但是獲取數據確實很痛苦。

Capture()循環調用ReadLn() ,直到讀取了指定的終止符行(在您的示例中為空白行)。

您需要知道每個XML文檔的結尾以及下一個文檔的起點。 如果每個文檔之間沒有明顯的標記(只要每個XML文檔在該空白行之前以換行符結尾並且在XML內不包含任何空白行,則可以使用空白行),那么您剩下的唯一內容選項是讀取第一個文檔的開始標簽,繼續閱讀直到找到相應的結束標簽,然后閱讀下一個文檔的開始標簽並等待其結束標簽,依此類推。

在這種情況下,最好使用支持推送模型的XML解析器進行處理。 您只需從套接字讀取原始字節並將它們按原樣推送到解析器中,並讓它在遇到每個頂級文檔元素的開始和結束時告訴您。 您可以在這兩個事件之間緩沖解析器提供給您的任何數據,使用開始事件來清除/准備緩沖區,並使用結束事件來將緩沖區最終確定/刷新到數據庫。

如果您不願意/不能使用預先存在的XML庫,則必須編寫自己的解析器。

更新:您顯示的示例Capture()ADelim參數設置為'' ,這僅在XML文檔由LF LFCR LF CR LF序列分隔時才有效。 在這種情況下,可以將該定界符用作ReadLn()ATerminator參數,並使其一次讀取1個整個文檔,而不用完全使用Capture()

procedure TfrmMain.ThreadBeforeRun(Sender: TIdThreadComponent);
begin
  CoInitialize(Nil);
end;

procedure TfrmMain.ThreadAfterRun(Sender: TIdThreadComponent);
begin
  CoUninitialize;
end;

procedure TfrmMain.ThreadRun(Sender: TIdThreadComponent);
var
  Xml: String;
  FMemory: TStringStream;
begin
  // read until a 'CR LF CR LF' sequence is reached...
  Xml := TrimRight(Client.IOHandler.ReadLn(CR+LF+CR+LF, IndyTextEncoding_UTF8));
  // alternatively:
  // Xml := Client.IOHandler.WaitFor(CR+LF+CR+LF, True, False, IndyTextEncoding_UTF8);

  FMemory := TStringStream.Create(Xml, TEncoding.UTF8);
  try
    QInsert.ParamByName('XMLData').LoadFromStream(FMemory, ftBlob);
  finally
    FMemory.Free;
  end;

  QInsert.Execute;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM