Страницы

Поиск по вопросам

пятница, 1 марта 2019 г.

Можно ли данные в дереве TDictionary писать в файл, как массив?

Вопрос, непосредственно связанный с моим предыдущим Импорт данных секвенирования и обработка SAM-файлов в TDictionary
Ранее, когда мы держали данные для обработки в массиве записей, мы просто создавали типовой файл и сбрасывали данные (а затем архивировали в ZIP, хорошо сжималось):
type data = record <...> end; var f: file of data; d: array of data;
Теперь, если мы будем использовать структуру
type DataType = record name,qual, info, seq:string; data:array[1..30] of double; paired, structured:boolean; ref:integer; end;
TData3 = TDictionary; TData1 = class(TDictionary); end;
Можно ли использовать тот же подход, что и раньше, т.е. сбрасывать данные в типовой файл? Или необходимо использовать FileStream?


Ответ

Можно конвертировать в массив, но, подозреваю, что не нужно. Особенно, если вы планируете делать это лишь для записи. Гораздо проще работать с потоками. Могу привести пример, как это реализовано у нас в базовом классе:
TVCFFile = class (TDictionary) // private <...> procedure SaveToStream(stream: TStream); protected <...> public <...> procedure SaveToZip(const AFileName: string); override; procedure SaveToFile(const AFileName: string); override; end;
procedure TVCFFile.SaveToStream(stream: TStream); var posi: System.Generics.Collections.TPair; pair:System.Generics.Collections.TPair; third:System.Generics.Collections.TPair; i: Integer; writer: TWriter; begin writer := TWriter.Create(stream, 4096); try writer.WriteListBegin; for third in Self do begin writer.WriteString(third.Key); writer.WriteListBegin; for pair in third.Value do begin writer.WriteInteger(pair.Key); writer.WriteListBegin; for posi in pair.Value do begin writer.WriteString(posi.Key); writer.WriteDouble(posi.Value.qual); writer.WriteString(posi.Value.alt); writer.WriteString(posi.Value.filter); writer.WriteString(posi.Value.info); end; writer.WriteListEnd; end; writer.WriteListEnd; end; writer.WriteListEnd; finally writer.Free; end; end;
procedure TVCFFile.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, 'bigdata.tvb'); zipFile.Close; finally zipFile.Free; end; finally stream.Free; end; end;
procedure TVCFFile.SaveToFile(const AFileName: string); var stream: TStream; begin stream := TFileStream.Create(AFileName, fmCreate); try SaveToStream(stream); finally stream.Free; end; end;
Можно просто записать в файл, можно сразу в ZIP-файл, скорость записи и считывания достаточно велика (для загрузки есть аналогичные методы, строите их от обратного). Плюс, понадобятся методы для загрузки из SAM, записи в него же, возможно, понадобится поддержка BED, VCF и прочее, а, может, вы всё это сделаете в других классах.

Комментариев нет:

Отправить комментарий