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

> Внимание!

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

> Ada BlockRead
TarasBer
сообщение 31.05.2011 11:40
Сообщение #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 - 31.05.2011 12:16


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


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

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

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


Код такой:

procedure Load_From_File(V: out Vector; File_Name: String) is
use Ada.Streams;
use Ada.Streams.Stream_IO;

File : constant Controlled_Stream_IO := New_Stream_IO(In_File, File_Name);
El_Count : constant integer := integer(Size(File.F)) * 8 / Element'Size;

subtype byte is Interfaces.Unsigned_8;

subtype Test_SA is Stream_Element_Array
(1 .. Stream_Element_Offset(El_Count * Element'Size));
type Test_BA is array
(1 .. Stream_Element_Offset(El_Count * Element'Size)) of aliased byte;

Is_Workaround_Possible: constant Boolean := (Test_SA'Size = Test_BA'Size) and (Test_SA'Alignment = Test_BA'Alignment);

begin
V.Set_Length(0);
V.Set_Length(El_Count);
if Is_Workaround_Possible then
declare
Buffer : Test_SA;
for Buffer'Address use V.Elements.all'Address;
Last : Stream_Element_Offset; pragma Unreferenced(Last);
begin
Read(File.S.all, Buffer, Last);
end;
else
Element_Array'Read(File.S, V.Elements.all (V.First .. V.Last));
end if;
end;


Вылетает.

Если же Is_Workaround_Possible сделать в лоб false, то всё нормально.
________________________________
Правка:
Всё, я заменил Element'Size на Element'Size/8 и всё заработало не только на мелких файлах.
Ну и формулу
integer(Size(File.F)) * 8 / Element'Size;
поменял на
integer(Size(File.F)) / (Element'Size / 8);
(чтобы на больших файлах не было лишнего переполнения)

Всё-таки иногда забываю, что размер возвращается в битах, а не байтах.

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


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

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


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

 



- Текстовая версия 5.09.2025 12:34
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"