Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.03 c
1-1123251915
Андрей Молчанов
2005-08-05 18:25
2005.08.28
Node.CustomSort


1-1123164603
Андрей Молчанов
2005-08-04 18:10
2005.08.28
Shell в TTreeView


3-1121431796
erika
2005-07-15 16:49
2005.08.28
формирование запроса IB


4-1121089291
grigory
2005-07-11 17:41
2005.08.28
Проблема с остановкой хука!!


11-1105724735
Bil Bal Dur
2005-01-14 20:45
2005.08.28
PDirList и ListView





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский