Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.28;
Скачать: CL | DM;

Вниз

Помогите новичку. Как массивы символов складывать....   Найти похожие ветки 

 
Senti ©   (2005-08-07 13:58) [0]

Задача такая.
Мне приходят данные, которые записываются в Array [1..8192] of Char
Необходимо эти данные каждый раз добавлять в буфер, пока буфер не достигнет значения 200 кб, затем записывать на диск.
Все казалось бы просто. Но вот совсем глупый вопрос... Как новые данные добавлять в конец буфера и какой тип буфера должен быть Array of char ?

Я решил задачу, но это решение из рук вон плохое. Привожу выдержку из кода.
(s  - глобальная переменная string, я использовал ее как буфер, Count - величина полученных данных : integer)

m : Array [1..8192] of char;
ts : string;
begin
s:=m; SetLength(s,Count);
ts := ts + s;
end;


Вот решение, далеко не лучше и не быстрое. Слишком много операций производиться лишних. Задача стоит как можно быстрей сохранять данные в буфер.

Простите за ламерский вопрос....


 
Senti ©   (2005-08-07 14:01) [1]

m : Array [1..8192] of char;
ts : string;
begin
ts:=m; SetLength(ts,Count);
s := s + ts;
end;


Я просто перепутал переменные, когда писал :)


 
begin...end ©   (2005-08-07 14:07) [2]

Приходят данные, каждый раз блоками по 8192 байта. Их нужно записывать в буфер, максимальный размер которого -- 200 КБ, т.е. в буфер может поместиться ровно 200 * 1024 / 8192 = 25 таких блоков данных. Так? Если да, то, может быть, сделать буфер фиксированного размера (200 КБ), и записывать приходящие данные в нужное место буфера?


 
Mx ©   (2005-08-07 14:07) [3]

Заведи статический буфер на 200Кб, запоминай в какую позицию "сувать" новые данные, перемещай их Move"ом. Примерно так:

const
 MyBytesSize = 8192;

type
 TMyBytes = array[1..MyBytesSize] of Char;

var
 Buf: array[0..204799] of Char;
 P: Cardinal = 0;

procedure WriteMyBytes(M: TMyBytes);
begin
 Move(M, Pointer(Cardinal(@Buf) + P)^, MyBytesSize);
 Inc(P, MyBytesSize);
end;


 
begin...end ©   (2005-08-07 14:19) [4]

> Senti

type
 TDataBlock = array [1..8192] of Char;

var
 Buffer: array [1..25] of TDataBlock;
 I: Integer;
begin
 I := 1;
 while нужно_получать_данные do
 begin
   Запись_очередного_блока_данных_в_элемент_Buffer[I];
   // Если I = 25 (т.е. заполнен уже весь буфер)...
   if I = 25 then
   begin
     Запись_всего_массива_Buffer_на_диск;
     // Сбрасываем I, чтобы следующий блок данных
     // записывать в начало буфера
     I := 1
   end
   // ...иначе просто увеличиваем I для подготовки
   // записи в следующий элемент массива Buffer
   else
     Inc(I)
 end
end.


 
Senti ©   (2005-08-07 14:23) [5]

Спасибо, понял... Я использую count, т.к. размер полученных данных может быть и меньше 8192. Каждый раз они считаются при получении.
А проверить на размер наверно можно так
if P + Count > 204799 then
begin
 fs.write(....) // запись на диск;
 Buf:=nil;
 P:=0;
 Move(M, Pointer(Cardinal(@Buf) + P)^, Count);
 Inc(P, Count);
end;


Кстати не быстрей использовать не Array of Char, а Array of byte ?


 
Alexander Panov ©   (2005-08-07 14:24) [6]

Для таких задач, если не ограничены условия, можно использовать TStream(TMemorySTream). Довольно удобно.
Применрно так:

const
 MaxLen=1024*200;
var
 MS: TMemorySTream;
 FS: TFileStream;
...

 MS := TMemoryStream.CReate;
...
procedure GetBufer;
var
 m: array[0..8191] of Char;
 Counter: Integer;
 Len: Integer;
begin
//Здесь заполняется m
//и запоминается длина данных
//
 if MS.Size+Couner>=MaxLen then
 begin
   Len := MaxLen-MS.Size;
   MS.Write(m[0],Len);
   FS := TFileStream.Create("ИмяФайла",fmOpenReadWrite);
   try
     MS.Position := 0;
     FS.CopyFrom(MS,MS.Size);
   finally
     FS.Free;
   end;
   MS.Size := 0;
   MS.Write(m[0],Counter-Len);  
 end
 else MS.Write(m[0],Counter);
end;


 
Senti ©   (2005-08-07 14:27) [7]

>begin...end, да спасибо... Можно и так решить проблему. Но какие операции быстрее всего совершаются

Move(M, Pointer(Cardinal(@Buf) + P)^, Count) намного быстрее чем работа со строкой.


 
Senti ©   (2005-08-07 14:30) [8]

Да я знаю что можно использовать MemoryStream, но это замедляет работу программы и получения данных. При использование буфера в виде строки или массива символов скорость возрастает в разы. Тестировал вчера и с MemoryStream, с последующей записью в FileStream и запись с буфера (string) в FileStream.
При аналогичном коде с MemoryStream время на получение одних и тех же данных возрастало в 1,5 раза.


 
begin...end ©   (2005-08-07 14:31) [9]

> Senti ©   (07.08.05 14:27) [7]

> Move(M, Pointer(Cardinal(@Buf) + P)^, Count) намного
> быстрее чем работа со строкой.

В приведённом мной коде нет работы со строкой.


 
Senti ©   (2005-08-07 14:36) [10]

А если не сложно поясните почему при записи в FileStream
используют вот такой синтаксис:
Есть строка с данными s : string;
а запись идет так fs.Write(s[1], Length(s));

Почему именно s[1] ?

и как можно записать буфер из array of char напрямую, без преобразования в строку ?
fs.Write(m[1], P) (Где M Array [1..204799] of char, и P размер буфера) ???? так или нет ?


 
Senti ©   (2005-08-07 14:38) [11]

Просите за не вежество....


 
Mx ©   (2005-08-07 14:45) [12]


> Senti ©   (07.08.05 14:36) [10]
> и как можно записать буфер из array of char напрямую, без
> преобразования в строку ?
> Где M Array [1..204799] of char, и P размер буфера

fs.Write(M, P)


> а запись идет так fs.Write(s[1], Length(s));

Потому как сама строка - указатель, если просто S, то запишется указатель, а иначе данные на которые он указывает. Я лично пишу Pointer(S)^. Меня поправят, если это не одно и тоже.


 
Alexander Panov ©   (2005-08-07 14:48) [13]

Senti ©   (07.08.05 14:36) [10]
А если не сложно поясните почему при записи в FileStream
используют вот такой синтаксис:
Есть строка с данными s : string;
а запись идет так fs.Write(s[1], Length(s));

Почему именно s[1] ?


Потому что в параметрах многих процедур и функции необходим указатель на начало буфера.
s[1] указывает на певый символ в строкею

Senti ©   (07.08.05 14:36) [10]
и как можно записать буфер из array of char напрямую, без преобразования в строку ?

fs.Write(m[1], P) (Где M Array [1..204799] of char, и P размер буфера) ???? так или нет ?


Именно так.

если бы первый индекс массива был 0, то нужно было бы написать fs.Write(m[0], P)


 
Senti ©   (2005-08-07 14:48) [14]

Большое спасибо. Т.е. получается s[1] ссылка на сами данные ? А почему именно [1] ? :)


 
Senti ©   (2005-08-07 14:49) [15]

Alexander Panov > Спасибо за развернутый ответ... Когда писал предыдущий пост, вы уже ответили.


 
Senti ©   (2005-08-07 14:51) [16]

Наконец я со всем разобрался!

СПАСИБО ВСЕМ ЗА ПОМОЩЬ !!!



Страницы: 1 вся ветка

Текущий архив: 2005.08.28;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.049 c
1-1123513665
Valentin
2005-08-08 19:07
2005.08.28
*.exe в *.exe


1-1123212087
Этом
2005-08-05 07:21
2005.08.28
Какие символы можно использовать в именах файлов ?


14-1122782501
guestPascal
2005-07-31 08:01
2005.08.28
Украли Базу


1-1123491917
Alx2
2005-08-08 13:05
2005.08.28
D6 не хочет компилировать следущий код:


5-1094974226
FHT
2004-09-12 11:30
2005.08.28
Работа при срабатывании OnCustomDrawItem в своем компаненте