2012-08-14 80 views
0

我已經寫了一個Delphi函數,用於將.dat文件中的數據加載到字符串列表中。然後它解碼字符串列表並分配給一個字符串變量。該字符串的內容使用'#'符號作爲分隔符。如何循環使用分隔字符串並將字符串內容分配給本地delphi變量?

我該如何獲得這個字符串的內容,然後將其內容分配給局部變量?

// Function loads data from a dat file and assigns to a String List. 
function TfrmMain.LoadFromFile; 
var 
    index, Count : integer; 
    profileFile, DecodedString : string; 
begin 
    // Open a file and assign to a local variable. 
    OpenDialog1.Execute; 
    profileFile := OpenDialog1.FileName; 
    if profileFile = '' then 
    exit; 
    profileList := TStringList.Create; 
    profileList.LoadFromFile(profileFile); 
    for index := 0 to profileList.Count - 1 do 
    begin 
    Line := ''; 
    Line := profileList[Index]; 
    end; 
end; 

其被解碼的VAR「行」之後包含的東西看起來是這樣的:

例如:

Line '23#80#10#2#1#...255#'. 

並不是所有的隔板之間的值是相同的長度和每次調用函數LoadFromFile時,「Line」的值都會有所不同(例如,有時一個值可能只有一個數字,接下來的兩個或三個等等,所以我不能依賴字符串或數組的Copy函數)。我試圖找出循環「線」的內容,將其分配給稱爲「緩衝區」的局部變量,然後如果它遇到了「#」,然後將緩衝區的值分配給一個局部變量,重新初始化緩衝區爲'';然後移動到「Line」中的下一個值,每次重複忽略「#」的下一個參數的處理。

我覺得我一直在研究這個問題太久了,我似乎無法取得任何進展,需要休息一下。如果有人願意看看,我會歡迎任何有關如何實現這一目標的建議。

非常感謝

KD

+0

是文件單行還是多行#限制行? – 2012-08-14 15:34:30

+0

它似乎你沒有免費profileList。這是內存泄漏。如果你需要在解析每行之前將文件拆分爲行,那麼你應該使用try-finally來釋放該對象。查看@UweRaabe的答案 - 並使用創建和釋放profileList的相同模式。外殼「profileList」表明你來自Java的土地或類似的東西。這裏沒有垃圾收集是Delphi。如果你創造了一些東西 - 你有責任釋放它。儘管有引用計數的接口,就像我在答案中提到的IJclStringList。他們將被編譯器釋放。 – 2012-08-14 15:35:54

+0

如果文件沒有多行,但是隻有一行,那麼你應該將它讀入字符串變量而不是字符串列表。 – 2012-08-14 15:36:36

回答

5

你需要一個第二的TStringList:

lineLst := TStringList.Create; 
    try 
    lineLst.Delimiter := '#'; 
    lineLst.DelimitedText := Line; 
    ... 
    finally 
    lineLst.Free; 
    end; 

根據您的Delphi版本,你可以在設置的情況下將lineLst.StrictDelimiter := true行包含空格。

+0

「取決於你的Delphi版本」 - 這就是我討厭這種方法。只是在情感上不喜歡:-) – 2012-08-14 15:02:22

+0

感謝您的答覆 - 我應該說的版本是XE2。 – kvnDalley 2012-08-14 15:20:41

+3

@ Arioch'The,Delphi版本只在需要StrictDelimiter時才重要,只有在行數據中有空格時才需要。沒有這些空間也被視爲分隔符。 – 2012-08-14 17:29:47

0

你沒有標記你的Delphi版本,所以我不知道它是否適用。 這是版本特定的。請做!

在我個人的偏好順序:

1:下載絕地CodeLib - http://jcl.sf.net。然後使用TJclStringList。它有非常好的拆分方法。之後,你只需要遍歷。

函數Split(const AText,ASeparator:string; AClearBeforeAdd:Boolean = True):IJclStringList;

uses JclStringLists; 
... 
var s: string; js: IJclStringList. 
begin 
... 
    js := TJclStringList.Create().Split(input, '#', True); 
    for s in js do begin 
     ..... 
    end; 
... 
end; 

2:德爾福現在有點少功能的StringSplit例程。 http://docwiki.embarcadero.com/Libraries/en/System.StrUtils.SplitString 它有一個misfeature,字符串數組類型可能不分配兼容本身。你好,1949年帕斯卡規則...

uses StrUtils; 
... 
var s: string; 
    a_s: TStringDynArray; 
(* aka array-of-string aka TArray<string>. But you have to remember this term exactly*) 
begin 
... 
    a_s := SplitString(input, '#'); 
    for s in a_s do begin 
     ..... 
    end; 
... 
end; 

3:使用TStringList。它的主要問題是,它被設計爲空格或新行是內置分隔符。在較新的德爾福可以壓制。總的來說,代碼應該適合你的確切的Delphi版本。你可以很容易的谷歌的東西,如「使用TStringlist分割字符串」,並獲得一個例子的負載(如@ Uwe的一個)。

但是你可能會忘記壓抑在這裏或那裏。而且你可能在舊的Delphi上,那裏無法完成。你可能會錯誤地應用不同的Delphi版本的例子。並且......它只是無聊:-)雖然你可以自己創建函數來爲你生成這些預調整的字符串列表,並仔細檢查它的Delphi版本:-)但是,那麼你將不得不在使用後小心地釋放該對象。

+0

對不起,我應該說Delphi XE2。感謝您的回覆。 – kvnDalley 2012-08-14 15:19:50

+0

我認爲最好不要「說」,而是添加delphi-xe2標籤。別客氣。 – 2012-08-14 15:29:03

+0

「輸入」是字符串。你應該閱讀整個文件,但我相信你可以谷歌如何做到這一點。將文件加載到字符串列表中是錯誤的,因爲你告訴過你不需要在不同的行上進行分割。這將是脆弱的,然後需要更慢。 – 2012-08-14 15:32:57

1

你可以做這樣的事情:

program Project1; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    System.SysUtils, StrUtils; 

var 
    S : string; 
    D : string; 

begin 
    S := '23#80#10#2#1#...255#'; 

    for D in SplitString(S,'#') do //SplitString is in the StrUtils unit 
    writeln(D); 

    readln; 
end. 
0

我使用的功能我已經寫了叫Fetch。我認爲,前一段時間,我從印地庫偷的想法:

function Fetch(var VString: string; ASeperator: string = ','): string; 
var LPos: integer; 
begin 
    LPos := AnsiPos(ASeperator, VString); 
    if LPos > 0 then 
    begin 
    result := Trim(Copy(VString, 1, LPos - 1)); 
    VString := Copy(VString, LPos + 1, MAXINT); 
    end 
    else 
    begin 
    result := VString; 
    VString := ''; 
    end; 
end; 

然後我會這樣稱呼它:

var 
    value: string; 
    line: string; 
    profileFile: string; 
    profileList: TStringList; 
    index: integer; 
begin 
    if OpenDialog1.Execute then 
    begin 
    profileFile := OpenDialog1.FileName; 
    if (profileFile = '') or not FileExists(profileFile) then 
     exit; 

    profileList := TStringList.Create; 
    try 
     profileList.LoadFromFile(profileFile); 

     for index := 0 to profileList.Count - 1 do 
     begin 
     line := profileList[index]; 
     Fetch(line, ''''); //discard "Line '" 
     value := Fetch(line, '#') 
     while (value <> '') and (value[1] <> '''') do //bail when we get to the quote at the end 
     begin 
      ProcessTheNumber(value); //do whatever you need to do with the number 
      value := Fetch(line, '#'); 
     end; 
     end; 
    finally 
     profileList.Free; 
    end; 
    end; 
end; 

注:這是輸入到瀏覽器中,所以我的天堂」檢查它的工作。

相關問題