Lazarus: построчное чтение данных из памяти

Док
Дата: 02.09.2019 17:32:26
Мужики,
понадобилось читать и писать вывод запускаемой внешней программы (примерно как в этом примере) в наследник TStrings построчно, а не прочтенными блоками. Причем чтение должно осуществляться из пополняемого в это время контейнера/памяти (а не как в выше приведенном примере, после окончания отработки внешней программы).

Подскажите, плз, в каком направлении двигаться? Может ссылки на материал, который можно почитать?
=================
Док.

Win7 Ultim x64/Deb 10 (MATE; gtk3) amd64:
FB 3.0.4.33054, Lazarus 2.1(r.61313); FPC 3.3.1 (r.42151), IBX by -Rik-
Kazantsev Alexey
Дата: 02.09.2019 17:46:58
Док,

Так в примере же есть поблочное чтение. Остаётся только найти окончание строки и скопировать её. Если читаешь на виндах, то вывод необходимо сначала перекодировать OemToAnsi.
Док
Дата: 02.09.2019 18:38:28
Kazantsev Alexey
Так в примере же есть поблочное чтение.

в примере все телодвижения начинаются лишь после того, как запись в память закончена, а мне бы понять, как из постоянно пополняемого MemoryStream читать и парсить строки. Пока не догоняю...
Kazantsev Alexey
Дата: 02.09.2019 18:50:28
Док,

Вот там чтение блока:
BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);

Блок прочитал, ищи конец строки. Не нашёл, складывай данные в накопительный буффер. Нашёл - клади часть данных до маркера новой строки в накопительный буффер и конвертируй накопительный буффер в строку. Накопительный буффер сделай строковым:
type
 OEMString = type AnsiString(CP_OEMCP);
var
 accBfr : OEMString;

Потом строку получишь приведением типа: string(accBuf);
Kazantsev Alexey
Дата: 02.09.2019 18:57:30
+ Моя процедура выделения строки. Для дельфей.
//
Procedure TBuilder.ParseDccOutput(Const ABuffer; ACount : Integer);
Var

 CPos       : MarshaledAString; // PAnsiChar;
 Index      : Integer;
 StartIndex : Integer;

 //
 Procedure _AccBuffer(AIndex : Integer);
 Var

  IncSize : Integer;
  OldSize : Integer;

 Begin

  IncSize := AIndex - StartIndex;

  If IncSize > 0 Then
   Begin

    OldSize := Length(FBuffer);
    SetLength(FBuffer, OldSize + IncSize);

    CopyMem(PByte(@ABuffer) + StartIndex, PByte(FBuffer) + OldSize, IncSize);

   End;

  StartIndex := AIndex + 1;

 End;
 //

 //
 Procedure _ProcessLine;
 Begin

  _AccBuffer(Index);

  Try

   ProcessDccLine(String(FBuffer)); // Твоя обработка готовой строки

  Finally

   FBuffer := ''; // тот самый накопительный буфер

  End;

 End;
 //

Begin

 CPos       := @ABuffer;
 Index      := 0;
 StartIndex := 0;

 For Index := 0 To ACount - 1 Do
  Begin

   Case CPos[Index] Of

    #10 : Begin

           If FLastChar = 13 Then
            Inc(StartIndex)
           Else
            _ProcessLine;

          End;

    #13 : _ProcessLine;

   End;

   FLastChar := Ord(CPos[Index]); // FLastChar : Byte;

  End;

 _AccBuffer(ACount);

End;
//
Док
Дата: 02.09.2019 20:36:18
Kazantsev Alexey,

спасибо, смотрю...
stanilar
Дата: 03.09.2019 16:42:34
Memory Mapped File

Вроде как даже рекомендованный способ совместного доступа к одному файлу. Или он базируется на нем.

В свое время накатал исходник по расширению менеджера памяти для датасета. Собирался к лазарю прикрутить... Но вот времени не было сделать, а теперь уже бывший дельфиец...
Василий 2
Дата: 04.09.2019 10:14:20
Есть же TStringReader
vavan
Дата: 04.09.2019 10:36:12
stanilar
расширению менеджера памяти для датасета
не поясните о чем речь?
kealon(Ruslan)
Дата: 04.09.2019 11:08:06
Док,

обычно автомат делают

несмотря на всю теорию, на практике в простейших случаях как этот, это обычно набор Case в которых происходит установка текущего состояния

у вас ещё и под разные платформы, так что стоит сразу заложиться на все возможные разделители #13, #10, #10#13


если номер строчки неважен, то можно считать любой из символов #13 или #10 разделителем и если аддитивный буфер непустой считать его новой строкой