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

Вниз

Как преместить данные в буфер не с начала?   Найти похожие ветки 

 
MegaVolt ©   (2004-04-05 12:40) [0]

функция Read класса ТFileStream определена так TFileStream.Read(var Buffer; Count: Integer): Longint;
Хотя на самом деле Buffer это скорее указатель и зачем так сделано мне не совсем понятно  :(
Я пишу наследника от TFileStream и перекрываю Read своей функцией с тем же определением.
У себя в функции я заполняю Buffer значениями самостоятельно некоторыми порциями меньшими чем сам Buffer. Получается что мне нужно скопировать некоторые данные в середину Buffer. Как это можно сделать?
Я делал так:

var
 m:integer; //Содержит указатель на новое место в Buffer
 Cach: array[0..1023]of byte;
.............
 m:=integer(pointer(Buffer))+BufPos;
 move(Cach[0],m,SizeOf(Cach));

почему то не работает. Где я ошибся?

Заранее благодарен :)


 
PVOzerski ©   (2004-04-05 12:51) [1]

При таком использовании move содержимое массива cash будет записано не туда, куда указывает m, а туда, где эта переменная m находится, в итоге будет и она потеряна, и всё, что дальше в памяти на 1022 байта.
move(Cach[0],pointer(m)^,SizeOf(Cach));


 
MBo ©   (2004-04-05 12:54) [2]

ИЗ потока - read
В поток  - write ;)
В хелпе еще зачем-то про Position и Seek написано.

>и зачем так сделано мне не совсем понятно  
Собственно, в этом непременно нужно разобраться, для того чтобы продолжать программировать на Паскале/Дельфи.


 
MegaVolt ©   (2004-04-05 13:04) [3]

PVOzerski:
Выдаёт AccessViolation во время записи по тому адресу который вычислен. Даже если смещение равно 0 :(

MBo: как работать с потоком я знаю. Но если из файла вычитывать по одному байту резко падает скорость :( Поэтому я решил написать класс наследник от TFileStream который реально читает из файла по 32К а я с ним работаю как с обычным TFileStream. Если знаешь как это сделать проще напиши :)


 
MBo ©   (2004-04-05 13:14) [4]

>Если знаешь как это сделать проще напиши
Я не понял задачи пока


 
Fay ©   (2004-04-05 13:18) [5]

Блин! Вы чё всне издеваетесь!?!? Сегодня уже 5-е число!
У одних TStringList.SaveToFile У других TFileStream.Read...
А CreateFile/ReadFile/WriteFile/CloseHandle и т.д. уже отменили?
>>  Если знаешь как это сделать проще напиши :)
Читать файл по 32К можно так. Под виндой - только так 8)
const
 BUF_SZ = 32768;
var
 h : THandle;
 n : Cardinal;
 b : array[0..BUF_SZ-1] of Byte;
begin
 h := CreateFile(PChar(MyFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 ReadFile(h, b, BUF_SZ, n, nil);
 if n > 0 then
 repeat
   .....
   ReadFile(h, b, BUF_SZ, n, nil);
 until n = 0;  
 CloseHandle(h);
end;


 
MegaVolt ©   (2004-04-05 13:19) [6]

Задача очень проста:
Стандартный TFileStream читает данные с максимальной скоростью если куски вычитываемых данных равны 32К почему так я не знаю :( Если вычитывать данные побайтно скорость резко падает. Можно конечно читать 32К а из него потом побайтно но как то неудобно. Поэтому я решил этот механизм запихнуть в класс и снаружи иметь всё тот же FileStream но который реально читает по 32К.
Для этого нужно заменить Read а так же Position и Seek родительского класса. Так вот я столкнулся с проблемой: в функцию Read указатель на буфер передаётся почему то как Integer. И я не могу копировать данные в буфер не с начала. А нужно копировать с некоторой позиции. Как это сделать???


 
Verg ©   (2004-04-05 13:21) [7]


> Так вот я столкнулся с проблемой: в функцию Read указатель
> на буфер передаётся почему то как Integer.


Че-гоо?!
Где такое снится?


 
MegaVolt ©   (2004-04-05 13:25) [8]

Verg: вот цитата из D5:

TFileStream.Read(var Buffer; Count: Integer): Longint;


 
Fay ©   (2004-04-05 13:28) [9]

8))


 
MBo ©   (2004-04-05 13:29) [10]

var Buffer; Объявление закончено.
Нетипизированный параметр, при использовании вместо него ставится любая переменная, элемент массива, если указатель - то обычно РАЗЫМЕНОВАННЫЙ .


 
Verg ©   (2004-04-05 13:29) [11]


> MegaVolt ©   (05.04.04 13:25) [8]
> Verg: вот цитата из D5:
>
> TFileStream.Read(var Buffer; Count: Integer): Longint;


Ну и? Что мы видим?

Два параметра:
1. Buffer - нетипизированная ссылка. Т.е. ссылка на что угодно
2. Count  - число типа integer;


 
Digitman ©   (2004-04-05 13:29) [12]


> MegaVolt ©   (05.04.04 13:25) [8]


запятую и точку с запятой различаешь ? после Buffer ? о чем, по-твоему говорит точка с запятой в этом месте ?


 
MegaVolt ©   (2004-04-05 13:30) [13]

Согласен тормознул :(
Но вопрос остался как в этот Buffer скопировать данные не с начала а с некоторой позиции?


 
pasha_golub ©   (2004-04-05 13:31) [14]

Nut?


 
Fay ©   (2004-04-05 13:31) [15]

Позиции чего???? В середину буфера, что-ли?


 
MegaVolt ©   (2004-04-05 13:32) [16]

Ага в середину с N-ой позиции


 
Verg ©   (2004-04-05 13:33) [17]

вот смотри:
procedure Proc(var B);

чтобы получить адрес того, на что ссылается B нужно сказать @B

продолжать?


 
Fay ©   (2004-04-05 13:34) [18]

Read(PByte(Integer(@Buf)+N)^, M);


 
han_malign ©   (2004-04-05 13:35) [19]

- самое простое (начиная с TP 5.0, если не раньше)
function TFileStream.Read(var Buffer; Count: Integer): Longint;
var Cach: array[0..1023]of byte absolute Buffer;
begin
  ...Cach[i]...


 
MegaVolt ©   (2004-04-05 13:38) [20]

Ага продолжай. Дальше по идее нужно адрес инкрементировать но как :( Просто добавить не даёт :(


 
MBo ©   (2004-04-05 13:39) [21]

>- самое простое (начиная с TP 5.0, если не раньше)
Ну уж нет - самое простое -
Stream.Read(Cach[50],DataSize)


 
Fay ©   (2004-04-05 13:39) [22]

Чё, прямо Inc(N) не даёт сделать?! Ай, нехорошо!


 
Fay ©   (2004-04-05 13:40) [23]

2MBo
Что упростилось от han_malign ?


 
MegaVolt ©   (2004-04-05 13:42) [24]

Заработало. :):) Действительно перевести в integer а потом сложить и обратно :):) Всем большущее спасибо :):):)


 
Verg ©   (2004-04-05 13:45) [25]


> MegaVolt ©   (05.04.04 13:38) [20]


Ага. Значит мы должны увеличит на сколько-то указатель (адрес) на то, на что ссылается B, но мы не знаем на что оно ссылается. Поэтому мы должны определить для себя - пусть будет это некоторый массив символов или просто байт.

procedure proc(var B);
var
 pB : pchar;
begin
 pB := @B;
 C какого байта по порядку тебе нужно прочитать? С N-ого?

 Read(pB[N], Count);

 или Read((pB+N)^, Count);
 инкрементируем - Inc(pB, N);
.................


 
MegaVolt ©   (2004-04-05 14:13) [26]

Или так :)

Может за одно объяснишь почему можно исспользовать PChar для определения массивов байт т.к. если в массиве вдруг встретится 0 то PChar по идее должен понять это как окончание переменной. Почему мы это игнорируем?


 
Fay ©   (2004-04-05 14:18) [27]

Ничего он не должен. Это указатель.


 
Verg ©   (2004-04-05 14:19) [28]


> PChar


- это тип такой. Указатель, на котором в делфи официально разрешена арифметика и индексирование.
Он сам по себе ничего "не понимает".

Можете пинать меня ногами, но преобразования указателей к integer и наоборот - порочная практика, привычка к которой вам обязательно когда-нибудь стрельнет и очень больно.


 
Fay ©   (2004-04-05 14:20) [29]

С какого перепугу?


 
MegaVolt ©   (2004-04-05 14:21) [30]

Указатель на длинную строку оканчивающуюсю нулём. А мы вдруг стали считать что это указатель на массив байт. И работать исспользую функции заточенные под PChar но с байтами. Почему же вдруг 0 перестал быть концом длинной строки?


 
Verg ©   (2004-04-05 14:22) [31]


> Почему же вдруг 0 перестал быть концом длинной строки?


Потому, что мы с ним работаем не как со строкой символов, заканчивающихся нулем.


 
Fay ©   (2004-04-05 14:22) [32]

2MegaVolt ©
Просто поверьте. Так легче поймёте.


 
MegaVolt ©   (2004-04-05 14:32) [33]

Я верю и во многих местах встречал просто не совсем понимал почему такое возможно. Т.е. в одном случае 0 это конец переменной а в другом вдруг уже не конец. Получается что мы исспользуем функции которые этот 0 не анализируют? А как узнать анализирует ли функция 0 или нет? Вот например  AnsiStrPos скорее всего уже нельзя будет исспользовать для поиска в массиве байт потому что он остановится на первом попавшемся нуле.
И почему принято исспользовать PChar а не array of byte? Ведь почти то же самое?


 
Fay ©   (2004-04-05 14:41) [34]

Блин! "Конец переменной"! Чё за порнуха?! Использовать можно хоть PApplication (хочешь - заведи себе такой). Но компилятир делфовый умеет (тупо для удобства)  делать всякие штуки :

1) PChar(String) - совсем не то же , что PChar(@String)
2) String := PChar : в строке будет то же, что в лежит по адресу PChar^ вплоть до #0.
3) прочее 8)

А AnsiStrPos "думает", что ты ещё не совсем с катущек слетел (не подведи её!) и оганичивается тем, что до #0.
ЯСНО?!


 
Verg ©   (2004-04-05 14:46) [35]


> Я верю и во многих местах встречал просто не совсем понимал
> почему такое возможно. Т.е. в одном случае 0 это конец переменной
> а в другом вдруг уже не конец.


Выражение "конец переменной" - это ты забудь.
Есть масса функций, которые интерпретируют область памяти, на которую указывает переменная типа pchar как массив символов, который заканчивается #0. Сама же переменная ничем не заканчивается - у нее есть размер. Т.к. это указатель, то и размер ее = sizeof(pointer).
Так же делфи интерпретирует присваивания переменной строчного типа (string) переменной типа pchar как копирование той самой области памяти вплоть до первого же #0 в ту строку с автоматическим определением ее размера.


 
MegaVolt ©   (2004-04-05 15:42) [36]

Спасибо :)


 
Fay ©   (2004-04-05 15:43) [37]

Одумался окаянный 8)



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

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

Наверх




Память: 0.56 MB
Время: 0.023 c
6-1077962919
Kolyan
2004-02-28 13:08
2004.04.25
TelnetServer


8-1073718580
Albelg
2004-01-10 10:09
2004.04.25
Аудио файл


1-1081412020
Closer
2004-04-08 12:13
2004.04.25
Отображение графа


3-1080786388
Артем К.
2004-04-01 06:26
2004.04.25
Казус в создании MDI-приложения с использование баз данных!


3-1080807471
ilya
2004-04-01 12:17
2004.04.25
Active Directory