2013-01-18 52 views
1

我有很多文件(大約160 000),我需要有關於單個文件在文件(全文)中的位置的信息。所以我使用的字典是這樣的:TDictionary保存到文件

WordDict : TDictionary<string, TDictionary<string, TIntegerDynArray>>; 

現在我知道,WORD1是FILE1,FILE3和FILE100和位置中的每個文件< 1,3,5>,< 2,8,35>等 我可以填充它,我可以使用它 - 它非常快。但我不知道如何有效地存儲字典文件。

編輯:有效 - 我的意思是迅速和文件

+0

你有什麼意思是「有效」或「有效」?小文件?整個文件的快速加載?快速搜索沒有加載文件的單詞? 目前看起來,大多數跨海大陸的方式是使用TMemIniFile。 –

+0

使用JSON發射器轉儲它,並使用JSON解析器加載它 –

+0

'TIntegerDynArray' - 更好地使用'TArray '因爲你總是使用泛型。請參閱http://stackoverflow.com/questions/11029353 http://stackoverflow.com/questions/14383093 –

回答

8

您可以用Delphi的流系統寫一個專有的流格式的大小小。如果大小很重要(與速度相反),則可以壓縮該流。這裏是一些代碼:

type 
    TFilePos = TArray<Integer>; 
    TFileDict = TDictionary<string, TFilePos>; 
    TWordDict = class (TDictionary<string, TFileDict>) 
    private 
    procedure LoadFromStream(stream: TStream); 
    procedure SaveToStream(stream: TStream); 
    public 
    procedure LoadFromZip(const AFileName: string); 
    procedure LoadFromFile(const AFileName: string); 
    procedure SaveToZip(const AFileName: string); 
    procedure SaveToFile(const AFileName: string); 
    end; 

procedure TWordDict.LoadFromZip(const AFileName: string); 
var 
    stream: TStream; 
    localHeader: TZipHeader; 
    zipFile: TZipFile; 
begin 
    zipFile := TZipFile.Create; 
    try 
    zipFIle.Open(AFIleName, zmRead); 
    zipFile.Read('worddict', stream, localHeader); 
    try 
     LoadFromStream(stream); 
    finally 
     stream.Free; 
    end; 
    zipFile.Close; 
    finally 
    zipFile.Free; 
    end; 
end; 

procedure TWordDict.SaveToZip(const AFileName: string); 
var 
    stream: TStream; 
    zipFile: TZipFile; 
begin 
    stream := TMemoryStream.Create; 
    try 
    SaveToStream(stream); 
    stream.Position := 0; 
    zipFile := TZipFile.Create; 
    try 
     zipFile.Open(AFileName, zmWrite); 
     zipFile.Add(stream, 'worddict'); 
     zipFile.Close; 
    finally 
     zipFile.Free; 
    end; 
    finally 
    stream.Free; 
    end; 
end; 

procedure TWordDict.SaveToStream(stream: TStream); 
var 
    posi: System.Generics.Collections.TPair<string, TFilePos>; 
    i: Integer; 
    pair: System.Generics.Collections.TPair<string, TFileDict>; 
    writer: TWriter; 
begin 
    writer := TWriter.Create(stream, 4096); 
    try 
    writer.WriteListBegin; 
    for pair in Self do 
    begin 
     writer.WriteString(pair.Key); 
     writer.WriteListBegin; 
     for posi in pair.Value do 
     begin 
     writer.WriteString(posi.Key); 
     writer.WriteInteger(Length(posi.Value)); 
     for i in posi.Value do 
     begin 
      writer.WriteInteger(i); 
     end; 
     end; 
     writer.WriteListEnd; 
    end; 
    writer.WriteListEnd; 
    finally 
    writer.Free; 
    end; 
end; 

procedure TWordDict.LoadFromStream(stream: TStream); 
var 
    sFiles: TFileDict; 
    aPosi: TFilePos; 
    size: Integer; 
    i: Integer; 
    sWord: string; 
    reader: TReader; 
    sFile: string; 
begin 
    Clear; 
    reader := TReader.Create(stream, 1024); 
    try 
    reader.ReadListBegin; 
    while not reader.EndOfList do 
    begin 
     sWord := reader.ReadString; 
     sFiles := TFileDict.Create; 
     reader.ReadListBegin; 
     while not reader.EndOfList do 
     begin 
     sFile := reader.ReadString; 
     size := reader.ReadInteger; 
     SetLength(aPosi, size); 
     for I := 0 to size - 1 do 
     begin 
      aPosi[I] := reader.ReadInteger; 
     end; 
     sFiles.Add(sFile, Copy(aPosi)); 
     end; 
     reader.ReadListEnd; 
     Add(sWord, sFiles); 
    end; 
    reader.ReadListEnd; 
    finally 
    reader.Free; 
    end; 
end; 

procedure TWordDict.LoadFromFile(const AFileName: string); 
var 
    stream: TStream; 
begin 
    stream := TFileStream.Create(AFileName, fmOpenRead); 
    try 
    LoadFromStream(stream); 
    finally 
    stream.Free; 
    end; 
end; 

procedure TWordDict.SaveToFile(const AFileName: string); 
var 
    stream: TStream; 
begin 
    stream := TFileStream.Create(AFileName, fmCreate); 
    try 
    SaveToStream(stream); 
    finally 
    stream.Free; 
    end; 
end; 
+0

非常感謝,完美的作品 – user1990191