Страница 1 из 2

Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 04.12.2019 14:11:53
Нердик
Привет Сообществу. Первые шаги, так что не обессутьте. Использую читапаскаль Lazarus скриптовый язык, встроенный в ПО. Написал первый скрипт, но получилось оч медленное выполнение, надо убыстрять. Задача, открыть  бинарный файл размером до 15гб, а  затем по читает данные из железа и сравниваем с откртым файлом. В скриптовом движке есть функция работы с файлом, но вот буфер и для работы с файлом и для чтения железа - один. Приходится читать файл, копировать в свой буфер - медленно!!!
Почитал http://www.freepascal.ru/forum/viewtopic.php?f=1&t=8320&sid=e75139d60d4f6940c94a120503e07e0c.
Решил использовать в самом скрипте TFileStream для чтения в свой массив-буфер средствами самого паскаля.
Код: Выделить всё
const
PageSize = 512;
ErGrSize = 512*1024{PageSize *page_count;};
var
Res: Boolean; //Результат выполнения функции. Принимает значение 1 в случае успешного выполнения и 0 в случае ошибки
myFileName: String; //Имя файла, выбираемое в файловом диалоге
FS: TFileStream;
iFileSize: Int64; // Размер открываемого дампа
page_count, i, g: Integer;
MyBuffer: array OF Byte;

begin

        Res := GetOpenFileName('Выбери меня!', myFileName, 'Dumps', 'Дампы (*.user)|*.user| Все файлы|*.*', 'user');

        SetLength(MyBuffer, ErGrSize); //объявляем PageBuffer (PageSize*page_count)
       
        setarraylength(PageBuffer, ErGrSize);

      
        //setarraylength(MyBuffer, ErGrSize);


                if (Res) then
                        begin
                     
                        AddMessage('Open file %s', [myFileName]);
                         FS := TFileStream.Create(myFileName, fmOpenRead or fmShareDenyWrite);
                        try                             
                                iFileSize := FS.Size;
                           
                                AddMessage('File size %d byte', [iFileSize]);
                               

                                for g:= 0 to (iFileSize div ErGrSize)-1  do     //filesize : 524288

                                                begin
                                           
                                                FS.Seek(g*ErGrSize, soFromBeginning);
                                                FS.Read(MyBuffer[0], ErGrSize);

......
                                             

В движке есть редактор с проверками на ошибки. Так вот - на строку FS.Read(MyBuffer[0], ErGrSize); -  Type mismatch

Что я делаю не так?

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 12:19:07
iskander
А если попробовать так?
Код: Выделить всё
  FS.Read(Pointer(MyBuffer)^, ErGrSize)
  //или
  FS.Read(PByte(MyBuffer)^, ErGrSize)

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 14:09:06
Vadim
Нердик писал(а):Что я делаю не так?

Я не знаю, чем недоволен Ваш редактор (строку с ошибкой Вы привели явно не полностью, а зря... ;-) ), но вот логическая ошибка у Вас там видна даже без мелкоскопа. :D Вот смотрите, Вы в одну ячейку своего массива MyBuffer (MyBuffer[0]), которая у Вас задана размером в 1 байт, пытаетесь засунуть данные размером 512*1024. Ну вот сами представьте, что Вам в рот пытаются засунуть очень вкусный бутерброд размером с авианесущий крейсер "Адмирал Кузнецов". Каковы, после этого, будут Ваши впечатления? :D

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 14:29:12
iskander
Vadim писал(а):Вы в одну ячейку своего массива MyBuffer (MyBuffer[0]), которая у Вас задана размером в 1 байт, пытаетесь засунуть данные размером 512*1024.

Метод function TFileStream.Read(var Buffer; Count: LongInt): LongInt; принимает нетипизированный параметр.

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 16:09:54
Vadim
iskander писал(а):принимает нетипизированный параметр.

Т.е., любого типа. В приёмный параметр можно вставлять переменную любого типа - Char, Integer и вообще всё что угодно. Но я ведь говорил не об этом... ;-)

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 16:31:24
iskander
А о чем?

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 16:56:39
Vadim
iskander писал(а):А о чем?

Vadim писал(а):пытаетесь засунуть данные размером

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 17:14:54
iskander
Дык
Код: Выделить всё
......
MyBuffer: array OF Byte; // Обьявляем массив MyBuffer.

begin
         //При запуске скрипта открывается файловый диалог, в котором необходимо выбрать дамп
        Res := GetOpenFileName('Выбери меня!', myFileName, 'Dumps', 'Дампы (*.user)|*.user| Все файлы|*.*', 'user');

        SetLength(MyBuffer, ErGrSize);
       ........

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 17:31:34
Нердик
Друзья, спасибо за ответы. Я решил, что исходя из сказанного http://www.freepascal.ru/forum/viewtopic.php?f=1&t=8320 [0] в MyBuffer , будет офсетом буфера.

ИСходно на строку  идет ошибка [Error] (44:34): Type mismatch
Прошу пардон, похоже надо обьявить Pointer or PByte. Или нет.
На это 
FS.Read(PByte(MyBuffer)^, ErGrSize)  - ошибка [Error] (45:15): Unknown identifier 'PByte'

Добавлено спустя 22 минуты 37 секунд:
Обьявил - теперь и на строку с PByte - [Error] (45:20): Type mismatch

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 18:27:21
iskander
Ну, значит на арапа не получилось, нужна какая-нибудь дока по вашему движку.

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 19:14:04
Vadim
iskander писал(а):Дык

:D
Ну, это только у Вас "дык", а у ТС совсем даже никакой не "дык", а всё печально. У него ведь совсем другой код. Вы просто свои мысли за его выдаёте, так нельзя... ;-)

Добавлено спустя 15 минут 59 секунд:
Нердик писал(а):FS.Read(PByte(MyBuffer)^, ErGrSize) - ошибка [Error] (45:15): Unknown identifier 'PByte'

Добавлено спустя 22 минуты 37 секунд:
Обьявил - теперь и на строку с PByte - [Error] (45:20): Type mismatch

Это всё потому, что Вы нормальным русским языком не объяснили, где именно Вы программируете. ;-) В FreePascal PByte - это встроенный тип данных. Если у Вас его нет - Вы используете что-то другое. Начав с "олбанского" языка, Вы сделали помощь в Вашей проблеме невозможной.

Настаиваю, что у Вас ошибка исключительно логическая, ошибка разработчика. Необходимо сначала продумать логику Ваших действий и только потом садиться программировать.

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 19:47:04
iskander
Vadim писал(а):не "дык", а всё печально

"Всё печально" это всё же по другому поводу, а здесь наоборот, стимул к познанию непознанного. :)

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 05.12.2019 19:51:06
Vadim
iskander писал(а):стимул к познанию непознанного.

Ещё бы познать о чём шла речь в непознаном, чтобы можно было, хоть примерно, опознать... :D

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 09.12.2019 14:46:38
Alex2013
1 Насколько я помню по умолчанию в скрипте нельзя использовать классы и указатели.
(Механизм для использования некого подобия подключения внешних классов есть, но уж больно он неудобный )
2 Я обращения к файлам делал с помощь подключения внешних функцией.
Например так :
Код: Выделить всё
// Читать текст из файла
Function R_LoadText(FN:String):String;
var
  ST:TStringList;
begin
ST:=TStringList.Create;
Result:='';
try
if FileExists(FN) then begin
  St.LoadFromFile(FN);
  Result:= ST.Text;
end;
finally
  st.Free;
end;
end;
.....
//---------------------------------------------------------//
// Настройка библиотеки функций доступных в скипте
procedure TRF1.PSScript1Compile(Sender: TPSScript);
begin
{----------------------------------------------}
With Sender do
begin
//Доступ к текстовым файлам
AddFunction(@R_LoadText ,'Function R_LoadText(FN:String):String;');
...
end
end;

Зы
Если в скриптах нужна динамическая память то нужно писать что-то вроде своего менеджера памяти с заменой указателей чем то попроще. Единственное что работает почти нормально это строки ( размеры которых может быть примерно до 4 гигабайт ) . :idea:
Но вообще скрипты обычно применяют для динамической подгрузки небольших и "чисто счетных функций " причем там где скорость их выполнения не очень важна . То есть даже использование внешних функции уже чуток перебор ( классический скрипт это чистая математика с несколькими внешними переменными )

Re: Паскаль скрипт TfileStream type mismatch

СообщениеДобавлено: 10.12.2019 01:14:03
Нердик
Спасибо друзья.Не думал что последуют еще ответы, не заглядывал, а тут такое.
Alex2013 - спасибо за ваш ответ. К сожалению я еще не так глубоко освоил предмет, понять трудновато. Может тестировочный код просто подсунуть чтобы проверить что движок "разрешит" использовать? какую конструкцию попробовать?
Vadim писал(а):Это всё потому, что Вы нормальным русским языком не объяснили, где именно Вы программируете. ;-) В FreePascal PByte - это встроенный тип данных. Если у Вас его нет - Вы используете что-то другое. Начав с "олбанского" языка, Вы сделали помощь в Вашей проблеме невозможной.

Настаиваю, что у Вас ошибка исключительно логическая, ошибка разработчика. Необходимо сначала продумать логику Ваших действий и только потом садиться программировать.

Вадим, в этом деле я новичок, и нектотрые вещи мне еще, возможно, не совсем понятны, вы уточните, в чем вы видите "олбанский". В ПО встроен скриптовый язык. Автор упоминает Pascal Script Lazarus, и руководство Remobjects pascal script.
Вот скрипт, с которого я начинал, он построен на ФУНКЦИЯХ описанных к использованию в движке. Как я упоминал исполнение получается очень медленным, в основном из-за копирования присвоением в цикле. По этому, я хочу исключить копирование из буфера в буфер, для начала. Решил делать это средствами самого паскаля. Естественно,я что то не учитываю, я и прошу помощи, что не так.

Код: Выделить всё
const
PageSize = 512;
ErGrSize = 512*1024{PageSize *page_count;};
var
Res: Boolean; //Результат выполнения функции. Принимает значение 1 в случае успешного выполнения и 0 в случае ошибки
myFileName: String; //Имя файла, выбираемое в файловом диалоге
iFileSize: Int64; // Размер открываемого дампа
page_count, i, g: Integer;
MyBuffer: array {[0..ErGrSize]} OF byte; // Обьявляем массив MyBuffer.

begin
         //При запуске скрипта открывается файловый диалог, в котором необходимо выбрать дамп
        Res := GetOpenFileName('Выбери меня!', myFileName, 'Dumps', 'Дампы (*.user)|*.user| Все файлы|*.*', 'user');

        //SetLength(PageBuffer, ErGrSize); //объявляем PageBuffer (PageSize*page_count)
        // Устанавливаем размер буфера
        setarraylength(PageBuffer, ErGrSize);

        // Устанавливаем размер буфера
        setarraylength(MyBuffer, ErGrSize);


                if (Res) then //если файл выбран, то продолжаем выполнять скрипт, если нет, то переход на завершение
                        begin
                        //В лог выдаем сообщения об открытии файла
                        AddMessage('Open file %s', [myFileName]);
                        Res := iFileStreamCreate(myFileName, fmOpenRead or fmShareDenyWrite);
                        // Проверка
                                if not(Res) then Exit;

                                iFileSize := iFileStream.Size;
                                //В лог выдаем сообщение
                                AddMessage('File size %d byte', [iFileSize]);
                                // Последовательно, группа за группой считываем в буфер и сравниваем файл с дампом.

                                for g:= 0 to (iFileSize div ErGrSize)-1  do     //filesize : 524288

                                                begin
                                                // считали группу из файла
                                                iFileStreamSeek(g*ErGrSize, soFromBeginning);
                                                iFileStreamRead(0, ErGrSize);

                                                //AddMessage('Прочитали файл', []);
                                                // и выводим в лог
                                                //ArrayToLog(PageBuffer, 512);


                                                //AddMessage('Копируем в MyBuff', []);
                                                //Просто копируем из буфера в массив.
                                                for i:= 0 to ErGrSize-1 do
                                                MyBuffer [i] := PageBuffer [i];

                                                // и выводим в лог, проверяем
                                                //ArrayToLog(MyBuffer, 512);


                                                // Считать 1024 страниц начиная с g*1024
                                                //AddMessage('Читаю EMMC группу', []);
                                                ReadPage(g*1024, 1024); ////Какой раздел будет читаться зависит от того, какой файл был выбран для сохранения
                                                //ReadPage всегда читается только по 512 байт независимо от размера обьявленного PageBuffer



                                                //AddMessage('Тест PageBuffer', []);
                                                // и выводим в лог
                                                //ArrayToLog(PageBuffer, 512);
                                                // выводим сообщение в лог
                                                //AddMessage('Тест MyBuffer', []);
                                                // и выводим в лог
                                                //ArrayToLog(MyBuffer, 512);


                                                //AddMessage('Сравниваю буферы', []);
                                                for i:= 0 to (ErGrSize-1)  do
                                                        begin
                                                                if PageBuffer[i] <> MyBuffer[i] then break; //сравниваем в цикле блок данных, при первом несовпадении цикл прерывается
                                                        end;
                                                        if i = ErGrSize then  //если i = x, то все байты в массивах совпадают
                                                                        //AddMessage('переходим к проверке следующей группы №%d', [g])
                                                                        else AddMessage(' требуется перезапись группы, i = %d', [i]);
                                                end;
iFileStreamFree;
AddMessage('Проверка заврешена', [])
Time;
                        end
     end.