powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lazarus: построчное чтение данных из памяти
25 сообщений из 49, страница 1 из 2
Lazarus: построчное чтение данных из памяти
    #39856405
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мужики,
понадобилось читать и писать вывод запускаемой внешней программы (примерно как в этом примере ) в наследник 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-
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856409
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

Так в примере же есть поблочное чтение. Остаётся только найти окончание строки и скопировать её. Если читаешь на виндах, то вывод необходимо сначала перекодировать OemToAnsi.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856417
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyТак в примере же есть поблочное чтение.
в примере все телодвижения начинаются лишь после того, как запись в память закончена, а мне бы понять, как из постоянно пополняемого MemoryStream читать и парсить строки. Пока не догоняю...
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856422
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

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


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


Потом строку получишь приведением типа: string(accBuf);
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856425
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Моя процедура выделения строки. Для дельфей.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
//
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;
//

...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856436
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

спасибо, смотрю...
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856750
stanilar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Memory Mapped File

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

В свое время накатал исходник по расширению менеджера памяти для датасета. Собирался к лазарю прикрутить... Но вот времени не было сделать, а теперь уже бывший дельфиец...
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856975
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть же TStringReader
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39856992
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stanilarрасширению менеджера памяти для датасетане поясните о чем речь?
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857011
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

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

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

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


если номер строчки неважен, то можно считать любой из символов #13 или #10 разделителем и если аддитивный буфер непустой считать его новой строкой
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857034
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)у вас ещё и под разные платформы, так что стоит сразу заложиться на все возможные разделители #13, #10, #10#13


sLineBreak же.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857040
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vizit0r,

даже мелкомягкие иногда просто #13 или #10 скидывают, и такие сбои нужно обрабатывать корректно
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857052
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)стоит сразу заложиться на все возможные разделители #13, #10, #10#13
В моём варианте, как раз, поддерживается #10, #13, #13#10.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857060
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

спасибо за пинок в нужном направлении. Правда, для простоты я реализовал через строки, а не через указатели (скорость выполнения дял меня не критична, в моих задачах не планируется длинный вывод). Выглядит примерно так (пояснения в тексте для себя-склеротика и нубов, которые будут читать код после меня. "Лишние" переменные остались после отладки, в итоговом коде почищу)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
procedure TForm1.btnGoClick(Sender: TObject);
{$IFDEF MSWINDOWS}
type
  WinCpString = type AnsiString(CP_ACP);//uses LConvEncoding
{$ENDIF}
const
  BUF_SIZE = 1024*2; // Размер буфера для чтения выходных данных блоками
var
  {$IFDEF MSWINDOWS}
  Buffer: WinCpString = '';
  {$ELSE}
  Buffer: string = '';
  {$ENDIF}

  DebugStr: String = '';//отладочная строка
  BufferStr: String = '';//буфер-накопитель
  BytesRead: LongInt = 0;//кол-во считанных из буфера байт
  LineEndingPos: Integer = 0;//позиция начала перевода строки
  StrPartLineEndingAhead //часть строки до LineEnding
  , StrPartLineEndingBehind //часть строки после LineEnding
                :String;
  StrCounter: Integer = 0;//счетчик выводимых memoOutput строк
begin
  memoOutput.Clear;

  {$IFDEF MSWINDOWS}
  // В Windows команду dir нельзя использовать напрямую, потому что она является встроенной
  // командой оболочки. Поэтому нужны cmd.exe и дополнительные параметры
  AProcess.Executable := 'c:\windows\system32\cmd.exe';
  AProcess.Parameters.Add('/c');
  AProcess.Parameters.Add('dir /s c:\Windows\System32\drivers');
  {$ENDIF}
  {$IFDEF UNIX}
  AProcess.Executable := '/bin/ls';
  AProcess.Parameters.Add('--recursive');
  AProcess.Parameters.Add('--all');
  AProcess.Parameters.Add('-l');
  {$ENDIF}

  AProcess.Options := [poUsePipes, poStderrToOutPut, poNoConsole];

  //Запуск процесса (выполнение команды dir/ls)
  AProcess.Execute;

  StrPartLineEndingAhead:= '';
  StrPartLineEndingBehind:= '';
  repeat
    memoOutput.Lines.BeginUpdate;
    try
      SetLength(Buffer,BUF_SIZE);//задаем минимальный размер Buffer (как правило размер Pipes в ОС не превышает 2kB)
      BytesRead := AProcess.Output.Read(Buffer[1],Length(Buffer));//читаем в Buffer и получаем кол-во считанных байт BytesRead;
      if BytesRead > 0
      then
        begin
          SetLength(Buffer,BytesRead);
          DebugStr:= CP1251ToUTF8(Buffer);//uses LConvEncoding

          {LineEnding - алиас для sLineBreak:
          Win = #13#10
          Unix = #10
          Mac OS до v.9 = #13}

          //получаем позицию LineEnding в строке
          LineEndingPos:= UTF8Pos(LineEnding,CP1251ToUTF8(Buffer)); //uses LazUTF8

          if LineEndingPos > 0
          then
            repeat
              if LineEndingPos = 1 //LineEnding в начале строки
              then
                begin
                  StrPartLineEndingAhead:= UTF8Copy(DebugStr,1, UTF8Length(LineEnding));//по сути присвоим пустую строку ''
                  Inc(StrCounter);
                  memoOutput.Lines.Add(Format('%d.',[StrCounter]));//добавляем в memoOutput пустую строку
                end
              else //LineEnding не в начале строки
                begin
                  StrPartLineEndingAhead:= UTF8Copy(DebugStr,1, LineEndingPos - 1);//захватываем часть строки до LineEndingPos;
                  BufferStr:= BufferStr + StrPartLineEndingAhead;// добавляем к строке-буферу захваченный до LineEnding текст
                  Inc(StrCounter);
                  memoOutput.Lines.Add(Format('%d. %s',[StrCounter, BufferStr]));//пишем буфер-накопитель в memoOutput
                  BufferStr:= '';//и "обнуляем" его для следующей итерации
                end;

              //захватываем оставшуюся часть строки после LineEndingPos без символов LineEnding
              StrPartLineEndingBehind:= UTF8Copy(DebugStr,LineEndingPos + UTF8Length(LineEnding), UTF8Length(DebugStr));

              DebugStr:= StrPartLineEndingBehind;
              LineEndingPos:= UTF8Pos(LineEnding,DebugStr);
            until LineEndingPos = 0
          else //LineEnding в DebugStr отсутствует 
            begin
             BufferStr:= BufferStr + DebugStr;
             Inc(StrCounter);
             memoOutput.Lines.Add(Format('%d. %s',[StrCounter, BufferStr]));//пишем строку-буфер в memoOutput
            end;
        end;
    finally
      memoOutput.Lines.EndUpdate;
      memoOutput.SelStart := UTF8Length(memoOutput.Text);
    end;
    Sleep(10);
    Application.ProcessMessages;
  until BytesRead = 0;
end;      


Возможно, есть ошибки в коде. Если найду, поправлю.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857113
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

Хапнешь горя, когда дефотные строки перестанут быть байтовыми.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857123
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати, не помешает наверное ещё и по таймауту забирать то, что ещё не завершено #10, #13, #13#10.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857195
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyХапнешь горя, когда дефолтные строки перестанут быть байтовыми.
можно подробнее, о каких строках речь и какими они станут? НЕ ОДНОбайтовыми, ты имеешь ввиду?

Мимопроходящийкстати, не помешает наверное ещё и по таймауту забирать то, что ещё не завершено #10, #13, #13#10
не совсем догнал - где?
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857243
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Докможно подробнее, о каких строках речь и какими они станут? НЕ ОДНОбайтовыми, ты имеешь ввиду?
О дефолтном String, он будет юникодовым в ближайшей перспективе.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857276
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.09.2019 15:09, Kazantsev Alexey пишет:
> О дефолтном String, он будет юникодовым в ближайшей перспективе.

в Лазаре utf8.
а Док на нём и сидит.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857279
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.09.2019 14:25, Док пишет:

МП>> кстати, не помешает наверное ещё и по таймауту забирать то, что ещё не завершено #10, #13, #13#10
> не совсем догнал - где?

если я правильно понял твою задачу, ты тащишь данные, которые процесс вываливает в консоль по "трубе".
может так случиться, что ты получил из "трубы" последовательность, которая не заканчивается #10, #13, #13#10
а процесс, который ты отслеживаешь, ничего больше не шлёт (пока).
в этом случае ты этого кусочка можешь ждать ооооооочень долго...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857283
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий,

Строковый тип определяется не лазарем, а в фпц он скоро будет юникодовым по дефолту.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857296
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, уже и лазарь готовится к utf-16.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857301
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
The goal of FPC project is [/b]to create a Delphi compatible UnicodeString (UTF-16) based solution[/b], but it is not ready yet. It may take some time to be ready.

This UTF-8 solution of LCL in its current form can be considered temporary. In the future, when FPC supports UnicodeString fully in RTL and FCL, Lazarus project will provide a solution for LCL that uses it. At the same time the goal is to preserve UTF-8 support although it may require changes to string types or something. Nobody know the details yet. We will tell when we know...

In essence LCL will probably have 2 versions, one for UTF-8 and one for UTF-16.

Так что, использование конкретизированного строкового типа не просто доброе пожелание, это маст хэв.
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857309
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дважды дибилы!
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Lazarus: построчное чтение данных из памяти
    #39857325
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящийможет так случиться, что ты получил из "трубы" последовательность, которая не заканчивается #10, #13, #13#10
так я в коде вроде бы учел этот момент. Нет?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
          if LineEndingPos > 0
          then
            repeat
            <skiped>
            until LineEndingPos = 0
          else //LineEnding в DebugStr отсутствует 
            begin


Не уверен, но repeat..until в операторные скобки заключать же не надо?

зы. вообще, я пишу для себя кроссплатформенную утилитку с использованием gbak/gfix/gstat/isql - покатаю код еще там...

Kazantsev AlexeyТак что, использование конкретизированного строкового типа не просто доброе пожелание, это маст хэв.
если я правильно тебя понял, все упирается в то, какого типа строка в фпц на момент сборки кода.

Ну дык я же везде повтыкал UTF8-аналоги функций работы со строками, которые корректно работают как с UTF8, так и с ansi. Наверняка, в момент перехода на utf16 окончательно обновятся и аналогичные UTF16-функции, которые (весьма вероятно) будут корректно работать со всеми ansi/utf8/utf16 строками. Вся беда в том, что
автор...Nobody know the details yet. We will tell when we know...

Или я не так тебя понял и опять чего-то не догоняю?

ps. надеюсь #13 и #10 при любой погоде остануться однобайтными
. Иначе придется, как в Дельфях, из CodePointSize/UTF8CodepointSize городить огород.
...
Рейтинг: 0 / 0
25 сообщений из 49, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lazarus: построчное чтение данных из памяти
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]