![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите новичку. Как массивы символов складывать.... [D6, WinXP]
Senti © (2005-08-07 13:58:00)Задача такая.
Мне приходят данные, которые записываются в 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:51:00) [1]Наконец я со всем разобрался!
СПАСИБО ВСЕМ ЗА ПОМОЩЬ !!!
Senti (2005-08-07 14:49:00) [2]Alexander Panov > Спасибо за развернутый ответ... Когда писал предыдущий пост, вы уже ответили.
Alexander Panov (2005-08-07 14:48:00) [3]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:00) [4]Большое спасибо. Т.е. получается s[1] ссылка на сами данные ? А почему именно [1] ? :)
Mx (2005-08-07 14:45:00) [5]
> 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)^. Меня поправят, если это не одно и тоже.
Senti (2005-08-07 14:38:00) [6]Просите за не вежество....
Senti (2005-08-07 14:36:00) [7]А если не сложно поясните почему при записи в 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 размер буфера) ???? так или нет ?
begin...end (2005-08-07 14:31:00) [8]> Senti © (07.08.05 14:27) [7]
> Move(M, Pointer(Cardinal(@Buf) + P)^, Count) намного
> быстрее чем работа со строкой.
В приведённом мной коде нет работы со строкой.
Senti (2005-08-07 14:30:00) [9]Да я знаю что можно использовать MemoryStream, но это замедляет работу программы и получения данных. При использование буфера в виде строки или массива символов скорость возрастает в разы. Тестировал вчера и с MemoryStream, с последующей записью в FileStream и запись с буфера (string) в FileStream.
При аналогичном коде с MemoryStream время на получение одних и тех же данных возрастало в 1,5 раза.
Senti (2005-08-07 14:27:00) [10]>begin...end, да спасибо... Можно и так решить проблему. Но какие операции быстрее всего совершаются
Move(M, Pointer(Cardinal(@Buf) + P)^, Count) намного быстрее чем работа со строкой.
Alexander Panov (2005-08-07 14:24:00) [11]Для таких задач, если не ограничены условия, можно использовать 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:23:00) [12]Спасибо, понял... Я использую 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 ?
begin...end (2005-08-07 14:19:00) [13]> 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.
begin...end (2005-08-07 14:07:00) [14]Приходят данные, каждый раз блоками по 8192 байта. Их нужно записывать в буфер, максимальный размер которого -- 200 КБ, т.е. в буфер может поместиться ровно 200 * 1024 / 8192 = 25 таких блоков данных. Так? Если да, то, может быть, сделать буфер фиксированного размера (200 КБ), и записывать приходящие данные в нужное место буфера?
Mx (2005-08-07 14:07:00) [15]Заведи статический буфер на 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;
Senti (2005-08-07 14:01:00) [16]
m : Array [1..8192] of char;
ts : string;
begin
ts:=m; SetLength(ts,Count);
s := s + ts;
end;
Я просто перепутал переменные, когда писал :)