Delphi: как динамически «разбить» строку на подстроки в соответствии с (динамической) маской - PullRequest
3 голосов
/ 08 апреля 2011

Это моя ситуация: у меня есть текстовый файл, содержащий много строк одинаковой длины, представляющих записи, которые должны быть загружены в таблицу БД SQL, поэтому мне придется генерировать код SQL из этих строк.
У меня есть таблица в этой БД (назовем ее «таблицей форматирования»), которая сообщает мне, как форматируются строки и где их загружать (каждая запись в этой таблице содержит имя целевой таблицы, имя поля, позицию и длину данных ссылаются на строки из текстового файла).

Я уже решил эту проблему таким образом, что я думаю, что это хорошо известно каждому программисту Delphi, использующему функцию Copy(string, pos, length) и перебирающему каждое поле на основе информации из "таблицы форматирования".
Это работает хорошо, но медленно, особенно когда мы говорим об исходных текстовых файлах с миллионом или более строк, каждая из которых представляет несколько десятков или даже сотен полей данных.

Сейчас я пытаюсь «увидеть» исходные строки таким образом, чтобы они выглядели уже разделенными, избегая функции Copy(), которая непрерывно создает новые строки, копируя содержимое из исходной строки, выделяя и освобождая память и тд. Я бы сказал, что «у меня есть вся строка, давайте посмотрим на нее так, чтобы она представляла каждую его« часть »(поле) за один шаг, не создавая из нее подстроки».

Что могло бы решить мою проблему, так это определить способ динамической структуры, такой как динамическая запись или динамический массив (не то, что Delphy называет динамическим массивом, а скорее чем-то вроде «динамического статического массива») для «наложения» на Строка для того, чтобы «посмотреть» с этой точки зрения ... Я не знаю, достаточно ли я понятен в этом объяснении ... Однако Delphi (насколько я знаю) не реализует такого рода динамические структуры.

Это кусок (статического) кода, который делает то, что я хочу, кроме отсутствия динамизма.

procedure TForm1.FormCreate(Sender: TObject);
type
  PDecodeStr = ^TDecodeStr;
  TDecodeStr = record
    s1: Array[0..3] of AnsiChar;
    s2: Array[0..9] of AnsiChar;
    s3: Array[0..4] of AnsiChar;
    s4: Array[0..7] of AnsiChar;
    s5: Array[0..2] of AnsiChar;
  end;
var
  cWholeStr: AnsiString;
begin
  cWholeStr := '123456789012345678901234567890';
  Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s1);
  Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s2);
  Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s3);
  Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s4);
  Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s5);
end;

Есть идеи, как решить эту проблему?

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 08 апреля 2011

Вы не можете избежать создания дополнительных строк.Ваш пример в конце вашего вопроса создает строки.

Memo1.Lines.Add(PDecodeStr(PAnsiString(cWholeStr)).s1)

Ваш вызов TStrings.Add() в этом коде создает неявную динамическую строку из передаваемого вами параметра, а затем эта строка передается в Add().

Решение с Copy, вероятно, является подходящим решением, поскольку я не вижу простого способа избежать копирования памяти, если вы хотите что-то сделать с разделенными строками.

1 голос
/ 08 апреля 2011

Я думаю, что в Delphi нет более эффективного способа, чем использовать Copy.

Но другое решение состоит в том, чтобы загрузить все строки непосредственно во временную таблицу с одним столбцом и после этого выполнить SQL-запрос. Общее время зависит от множества параметров, поэтому лучший способ это проверить !!

...