| 
| 
 | Вопрос # 4 864/ вопрос решён / | 
 |  Здравствуйте, эксперты!У меня Delphi 7 и вот такая проблема. Имею TStream с данными. Причём данные произвольные не имеющие какой то структуры. Нужно найти в этих данных другие данные и узнать позицию их в потоке. Пробовал считывать все данные из потока в PChar а затем с помощью функции AnsiStrPos произвести поиск, но вот беда, в потоке есть нулевые символы которые PChar "считает" концом строки. Если есть возможность дайте быструю функцию поиска данных ибо через цикл у меня как то медленно всё работает. Спасбо. Пришлите пожалуйста ответ на amber8706@mail.ru или ссылку на него.
 
|  |   Вопрос задал: amber (статус: 1-ый класс)Вопрос отправлен: 26 декабря 2010, 16:26
 Состояние вопроса: решён, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 15; последнее сообщение — 21 января 2011, 13:21; участников в обсуждении: 5. 
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 16:31 [#1]:Давай-ка по-конкретнее, что нужно искать. В чём хранятся данные (шаблон) для поиска? Всё делается гораздо проще, чем ты думаешь. Не надо ничего никуда копировать, можно (нужно!) искать прямо в стриме.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | amber (статус: 1-ый класс), 26 декабря 2010, 16:54 [#2]:есть IdHTTPServer, браузер отсылает ему форму с прикрепленным фалом(ми). Данные формы и сами файлы находятся в параметре ARequestInfo.PostStream события OnCommandGet. Я пытался считать все данные из потока в PChar и с помощью AnsiStrPos разбить поток на элементы: заголовок запроса\данные, т.е. отделить одно от другого и привести в более "опрятный" вид, создав коллекцию из этих элементов. Так вот в чём проблема: если в присылаемых данных нет нулевых символов функция AnsiStrPos и всё с ней связанное работает нормально. Разделение данных  создание коллекции происходит без проблем, НО если в данных встречается символ с кодом 0 функция AnsiStrPos и сё с ней связанное не работает! Может я изобретаю велосипед и данную проблему уже решили? |  
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 17:05 [#3]:Мне таких подробностей не надо. Ты на мой вопрос не ответил.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | amber (статус: 1-ый класс), 26 декабря 2010, 17:45 [#4]:Вот пример содержимого патока (TStream): 
 -----------------------------7da31c3510562
 Content-Disposition: form-data; name="path"
 
 C:\
 -----------------------------7da31c3510562
 Content-Disposition: form-data; name="PutFile"; filename="primer.txt"
 Content-Type: text/plain
 
 ПРИМЕР!!
 -----------------------------7da31c3510562
 Content-Disposition: form-data; name="submit"
 
 Закачать
 -----------------------------7da31c3510562--
 
 Нужно отделить "Content-Disposition:" от данных, т.е. на выходе хотелось бы видеть следующее:
 
 Массив строк (или TStrings) вида:
 
 Content-Disposition: form-data; name="path"
 
 Content-Disposition: form-data; name="PutFile"; filename="primer.txt"
 Content-Type: text/plain
 
 Content-Disposition: form-data; name="submit"
 
 Массив данных, вида:
 
 C:\
 
 ПРИМЕР!!
 
 Закачать
 
 Разумеется данные могут быть двоичными, но строки всегда имеют текстовый вид, кроме того строка "-----------------------------7da31c3510562" может быть какой угодно, но всегда имеет вид: "----ххх"
 
 Сам поток может содержать сколько угодно данных, разделанных строкой вида: "----ххх", но начинается он всегда с строки "----ххх", а заканчивается всегда строкой вида: "----ххх--"
 |  
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 18:06 [#5]:А искать-то что надо? Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 18:09 [#6]:Для поиска нужно только одно - то, что искать. В любом буфере, будь то массив, строка, указатель на кусок памяти и т.д. Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 18:11 [#7]:Вот, например, функция поиска 4-байтного целого в стриме: 
 unit General;
 
interface
 
uses
  Messages, Classes;
 
type
  TProgressCallback = procedure(const Progress: Integer) of object;
  TSuccessCallback = procedure(const Address: Int64) of object;
 
const
  WM_RANDOM_VALUE =             WM_USER + 100;
  TargetWindowClassName =       'TTargetMainForm';
  TargetWindowTitle =           'Приложение - цель';
  MainWindowClassName =         'TMainForm';
  MainWindowTitle =             'Управляющее приложение';
 
var
  FindNextAddress: Cardinal = 0;
 
// Поиск адреса первого вхождения 4-байтного целого в потоке
// Возвращает кол-во вхождений.
// вызывает cbProgress() при увеличении прогресса на 1%
// вызывает cbSuccess() при нахождении очередного вхождения
function FindValueInStream(const Value: Cardinal;
                           Stream: TStream;
                           cbProgress: TProgressCallback;
                           cbSuccess: TSuccessCallback): Cardinal;
 
implementation
 
function FindValueInStream(const Value: Cardinal;
                           Stream: TStream;
                           cbProgress: TProgressCallback;
                           cbSuccess: TSuccessCallback): Cardinal;
var
  MayBe: Cardinal;
  B,
  LeftByte: Byte;  // мл. байт
  Progress, OldProgress: Integer;
begin
  Result:= 0;
  if not Assigned(cbSuccess)
    then Exit;
 
  OldProgress:= 0;
 
  if Stream.Position <> 0
    then Stream.Position:= 0;
 
  LeftByte:= Value and $FF;
  while Stream.Position < Stream.Size do
    begin
      if Stream.Read(B, 1) <> 1
        then Exit;
 
      if B <> LeftByte
        then Continue
        else begin
               if Stream.Read(MayBe, 3) <> 3
                 then Exit; // читаю 3 остальных байта
               MayBe:= (MayBe shl 8) + B; // Соединяю с младшим байтом
 
               if Value = MayBe
                 then begin
                        Inc(Result);
                        cbSuccess(Stream.Position - 4)
                      end
                 else Stream.Seek(-3, soFromCurrent);
             end;
 
      // Вызов события по прогрессу
      if Assigned(cbProgress)
        then begin
               Progress:= Round(100 * Stream.Position / Stream.Size);
               if Progress <> OldProgress
                 then begin
                        OldProgress:= Progress;
                        cbProgress(Progress);
                      end;
             end;
    end;
end;
 
end.Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | amber (статус: 1-ый класс), 26 декабря 2010, 19:35 [#8]:Я ж написал, что нужно отделить "Content-Disposition" от данных. Вышеприведённое содержимое потока было примером. Через Ваш код это сделать то можно, но для больших данных он не годится, поскольку работать будет медленно. Алгоритм должен быть примерно таким: 
 Считываем строку-разделитель (в примере она выглядит как "-----------------------------7da31c3510562"
 
 Считываем заголовки "Content-Disposition" каждого блока данных, разделанных ранее полученной строкой.
 
 Считываем данные каждого блока .
 
 Вся сложность заключается в БЫСТРОМ поиске в потоке строки-разделителя. Я использовал для её поиска AnsiStrPos, но как я сказал ранее, эта функция не дружит с нулевыми символами.
 
 P.S.
 Представляете сколько будет "Думать" приведенная Вами функция если размер потока, скажем 1Гб, а нужное число находится в его конце? Но смысл я вижу Вам стал понятен.
 |  
|   | min@y™ (статус: Доктор наук), 26 декабря 2010, 20:03 [#9]: Цитата (amber): Представляете сколько будет "Думать" приведенная Вами функция если размер потока, скажем 1Гб, а нужное число находится в его конце? Да, но это частный случай. Можно сделать немного по-другому. Читать блоками по, например, 64 кб, искать там начало, запоминать индекс и дальше выдирать из стрима блок нужного размера и сравнивать. Всё будет быстро и просто.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | bugmenot (статус: 3-ий класс), 26 декабря 2010, 23:06 [#10]:функция SearchBuf, кстати, Pos тоже binary-safe 
 и вообще это стандартный multipart/form-data
 виконання програми розпочинається з того самого мiсця, де призупинилося.
 
 |  
|   | amber (статус: 1-ый класс), 27 декабря 2010, 12:58 [#11]:Спасибо за SearchBuf! Всё работает быстро и с большими объёмами данных (до нескольких сотен мегабайт). с гигабайтными потоками  правда проблема. При попытке считать их в переменную пишет, что не хватает памяти (хотя на компьютере у меня 8Гб оперативки из них Windows видит 4Гб (ОС 32 битная)). Попробую использовать метод, описанный min@y™, считывать в память по несколько килобайт и обрабатывать их (правда это будет немного геморойно и скорее всего дольше. Проще наверно запретить пользователю отправлять файлы больше определённого размера), но всё равно всем спасибо! |  
|   | Вадим К (статус: Академик), 27 декабря 2010, 13:58 [#12]: Цитата (amber):  (хотя на компьютере у меня 8Гб оперативки из них Windows видит 4Гб (ОС 32 битная)) Нужно ставить 64битную ось. Хотя это может не помочь - ещё процессор и материнская плата должна видеть.
 на 32битной системе выделить больше 2 гигов памяти одним куском без специальных приспособлений нельзя.
 Но даже если все приспособления заюзать, больше 3 гигов нераздельно не выделить.
 Но спрашивается, зачем обрабатывать гигабайтные потоки? В чем же там таком ищется. Если это http ответы обрабатываются, то есть смысл смотреть только начало стрима.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | eclipse (статус: Посетитель), 28 декабря 2010, 23:12 [#13]:Короче... 32 или 64 по боку! Я вкурсе чё ты там хочешь рубануть... тупо делай s:= TStringList.creaTE... а дальше делай свё по теме. |  
|   | eclipse (статус: Посетитель), 28 декабря 2010, 23:19 [#14]:Да короче даже дело не в оперативки... как ты прогу юзаешь... тупо опиши. |  21 января 2011, 13:20: Статус вопроса изменён на решённый (изменил автор вопроса — amber) 
|   | amber (статус: 1-ый класс), 21 января 2011, 13:21 [#15]:Спасибо всем, всё получилось! |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |