IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

> Ada BlockRead
сообщение
Сообщение #1


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Мне очень не нравится скорость побайтового чтения - 3МБ файл читается больше секунды, когда дельфовый аналог на BlockRead считывает его моментально.
Всё, что приходит в голову - открыть файл для типа byte, узнать размер, потом открыть файл для массива данного размера и считать за раз.

Byte_IO.Open(SF, Byte_IO.In_File, "test.txt");
declare
S: Byte_IO.Count := Byte_IO.Size(SF);
type Arr is array (1..S) of byte;
type AArr is access Arr;
package Arr_IO is new Ada.Direct_IO(Arr);
F: Arr_IO.File_Type;
A: AArr;
begin
A := new Arr;
Byte_IO.Close(SF);
Arr_IO.Open(F, Arr_IO.In_File, "test.txt");
Arr_IO.Read(F, A.all);
Arr_IO.Close(F);
end;


Но это выдаёт
raised STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW
(даже после того, как я вместо заведения массива на стеке завёл указатель)
Да и мало ли размер файла изменится между первым и вторым открытиями.
И вообще много дёргать винт это плохо.

Последний вариант - через ВинАПИ, но мне неохота туда лезть.

ПС Настраиваемые пакеты во внутреннем блоке - это сильно. Реально круто, я про язык.

Сообщение отредактировано: TarasBer -


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Так вот, нету ли стандартного контролируемого потока?
Нет. Ни файлов, ни потоков контролируемых нет и не будет. Придется писать закрытие в конце работы с потоком. А работать с ним очень просто:

with Interfaces;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_IO;

with Ada.Direct_IO;

procedure Main is

subtype Byte is Interfaces.Unsigned_8;
type Byte_Buffer is array(Integer range <>) of aliased Byte;
type PByte_Buffer is access Byte_Buffer;

subtype sz_Test_A is Byte_Buffer(1 .. 19);
subtype sz_Test_B is Ada.Streams.Stream_Element_Array(1 .. 19);
Is_Workaround_Possible: constant Boolean :=
sz_Test_A'Size = sz_Test_B'Size and sz_Test_A'Alignment = sz_Test_B'Alignment;

procedure BlockRead(File : in Ada.Streams.Stream_IO.File_Type;
Buffer : out Byte_Buffer;
Was_Read: out Natural) is

use Ada.Streams, Ada.Streams.Stream_IO;
SE_Buffer : Stream_Element_Array (1 .. buffer'Length);
for SE_Buffer'Address use Buffer'Address;
pragma Import (Ada, SE_Buffer);
Last_Read : Stream_Element_Offset;

begin
if Is_Workaround_Possible then
-- Быстрый путь
Read (Stream (file).all, SE_Buffer, Last_Read);
Was_Read := Natural (Last_Read);
else
-- Медленный путь
if End_Of_File(file) then
Was_Read := 0;
else
Was_Read :=
Integer'Min (Buffer'Length, Integer (Size (File) - Index (File) + 1));
Byte_Buffer'Read (Stream (File),
Buffer (Buffer'First .. Buffer'First + Was_Read - 1));
end if;
end if;
end BlockRead;

File_Name : String := "F:\Programs\Ada\forum\debug\aga.txt";

SFIn : Ada.Streams.Stream_IO.File_Type;
Buffer : PByte_Buffer;
Buf_Size : Integer;
Bytes_Read : Integer;

begin
-- Открыл
Ada.Streams.Stream_IO.Open(SFIn, Ada.Streams.Stream_IO.In_File, File_Name);
-- Получил размер
Buf_Size := Integer (Ada.Streams.Stream_IO.Size (SFIn));
-- Выделил память
Buffer := new Byte_Buffer (1 .. Buf_Size);

-- Прочел (это - процедура Gautier)
BlockRead (SFIn, Buffer.all, Bytes_Read);

-- Проверил, все ли нормально
if Buf_Size /= Bytes_Read then
Ada.Text_IO.Put_Line ("Something goes wrong ...");
end if;
-- Закрыл
Ada.Streams.Stream_IO.Close(SFIn);
end Main;

Не дожидаясь вопроса, сразу объясню, что такое Is_Workaround_Possible. У компиляторов GNAT и ObjectAda есть некоторые проблемы со скоростью выполнения Read и Write в потоках. Так вот, если Stream_Element это и есть байт, и оба тестовых массива одинаково упакованы и одинаково выровнены - то можно значительно ускорить операции чтения/записи, работая напрямую с массивом Stream_Element-ов, наложенным на буфер (строка for SE_Buffer'Address use Buffer'Address этим занимается). Если же нет возможности работать с таким массивом - что ж поделаешь - приходится читать медленно в буфер, это действительно медленно: автор замерял, говорит о 50-кратном замедлении в среднем. Если надо, кстати, есть и BlockWrite для стримов...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.05.2024 22:12
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name