Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

чтение массива double с помощью TFileStream [D7]


Страницы:   1 2 3 4 5

Alexander123 ©   (2012-01-17 18:11:00) 

Имеется текстовый файл с числами. Пытаюсь считать их вот таким способом:

var
fs: TFileStream;
A: array [0..9] of double;
begin
if opendialog1.Execute then
begin
fs:=TFileStream.Create(opendialog1.FileName, fmOpenRead);
fs.Read(A[0], sizeof(A));
...

При дальнейшей работе получаются значения которых не было в файле. Как решить проблему? Или обязательно считывать данные как byte и потом уже переводить в double?


Alexander123   (2012-01-18 09:49:00) [61]

Всем спасибо за ответы.
Оказалось, что я сам себе проблему придумал)) readln, оказывается, работает достаточно быстро. Значительное замедление программы у меня происходило после добавления считанных точек на график. Я думал, что если данные уже считались в память и произошло их преобразование в дабл, то существенных тормозов не должно быть. Делал это следующим образом:

procedure TForm1.Button1Click(Sender: TObject);
var
f: textfile;
x,y: double;
begin
if opendialog1.Execute then
begin
assignfile(f, opendialog1.FileName);
reset(f);
while not eof(f) do
begin
readln(f,x,y);
series1.AddXY(x,y);
end;
end;
closefile(f);
end;

Если файл размером несколько Мб, то график строится очень медленно, но если убрать строчку addxy(), то само считывание происходит моментально.

Погуглил и нашел некоторые рекомендации по этому поводу
http://www.delphigroups.info/2/7/359178.html
пример программы как лучше добавлять точки, смысл этого в том, чтобы избегать использование addXY():

Var X,Y : Array of Double; // TChartValues
t : Integer;
Num : Integer;
begin
{ 1M points }
Num:= 1000000;
{ allocate our custom arrays }
SetLength(X,Num);
SetLength(Y,Num);
{ fill data in our custom arrays }
X[0]:=0;
Y[0]:=Random(10000);
for t:=1 to Num-1 do
begin
X[t]:=t;
Y[t]:=Y[t-1]+Random(101)-50;
end;
{ set our X array }
With Series1.XValues do
begin
Value:=TChartValues(X);
Count:=Num;
Modified:=True;
end;
{ set our Y array }
With Series1.YValues do
begin
Value:=TChartValues(Y);
Count:=Num;
Modified:=True;
end;
{ Show data }
Series1.Repaint;


PS: TChartValues(X) у меня не работает, похоже надо TChart обновить


Германн   (2012-01-18 02:32:00) [62]


> Ega23 ©   (18.01.12 02:13) [23]
>
>
> > а потом уже N раз работать с файлом типа File of Double
>
>
> Нафига файловые операции туда-сюда дёргать?

Спроси у своего отца, Олег. Достаточно ли физику один раз считать файл с данными, чтобы "нормально" обработать результаты некоего "физэксперимента"?


Ega23   (2012-01-18 02:13:00) [63]


> а потом уже N раз работать с файлом типа File of Double


Нафига файловые операции туда-сюда дёргать? Зачитал разом в память, а там уже работай сколько влезет.


Ega23   (2012-01-18 02:11:00) [64]


> Самуилыч   (18.01.12 00:58) [19]


Зачем так сложно?


procedure TForm12.Button1Click(Sender: TObject);
var
 arr: array of Double;
 i, cnt: Integer;
 fs: TFileStream;
begin
 cnt := StrToInt(Edit1.Text);
 SetLength(arr, cnt);
 for i := 0 to cnt - 1 do
   arr[i] := (i + 1)/10;
 fs := TFileStream.Create('c:\temp\1.dat', fmCreate);
 try
   fs.WriteBuffer(cnt, SizeOf(Integer));
   if cnt > 0 then
     fs.WriteBuffer(arr[0], cnt * SizeOf(Double));
 finally
   fs.Free;
 end;
end;

procedure TForm12.Button2Click(Sender: TObject);
var
 arr: array of Double;
 i, cnt: Integer;
 fs: TFileStream;
begin
 fs := TFileStream.Create('c:\temp\1.dat', fmOpenRead or fmShareDenyNone);
 try
   fs.ReadBuffer(cnt, SizeOf(Integer));
   if cnt = 0 then Exit;
   SetLength(arr, cnt);
   fs.ReadBuffer(arr[0], cnt * SizeOf(Double));
   Memo1.Clear;
   for i := 0 to cnt - 1 do
     Memo1.Lines.Add(FloatToStr(arr[i]));

 finally
   fs.Free;
 end;
end;


Германн   (2012-01-18 01:21:00) [65]


> Alexander123 ©   (17.01.12 19:25) [11]
>
>
> > Так их и надо писать изначально не в виде текста, а в
> виде
> > набора double
>
> это уже другая программа их записывает в таком виде
> может сам файл возможно как-то конвертировать?
>

Можно. Но вопрос - нужно ли? Если обработка данных конкретного эксперимента - разовая задача, то не нужно. Всё равно сначала нужно будет потратить время на считывание текстового файла текстовыми способами. А потом ещё потратить время на запись чисто двоичного файла. А потом его заново читать ещё придётся.
А вот если эти данные предназначены для многократного считывания, то есть смысл один раз сей файл преобразовать, а потом уже N раз работать с файлом типа File of Double или просто File.
Имхо2. Не уверен что чтение с помощью класса TFileStream в данном случае будет быстрее старого, доброго BlockRead.


Германн   (2012-01-18 01:12:00) [66]


> Самуилыч   (18.01.12 00:58) [19]

Имхо, лучше всегда записывать с разделителями. Может это и чуть более медленный вариант (не экспериментировал), а может и чуть менее медленный. Как этот Compile Magic поймёшь. :)
Но зато при просмотре в блокноте проблем не будет. Что немаловажно автору для проверки его алгоритма.


Самуилыч   (2012-01-18 00:58:00) [67]

> Alexander123 ©   (17.01.12 18:11)  

Лучше всего сразу писать числа не как текст, а именно как числа, тогда они и пушутся быстрее, и читаются тоже быстрее (потому что не просходит преобразования чисел в строки и обратно):

var
 A: array [N..M] of double;
 F: file of double;
 i: integer;
begin
 AssignFile(F, 'имя  файла');
 Rewrite(F);
 for i := N to M do
   Write(F, A[i]);
 CloseFile(F);
end;


var
 A: array [N..M] of double;
 F: file of double;
 i: integer;
begin
 AssignFile(F, 'имя  файла');
 Reset(F);
 for i := N to M do
   Read(F, A[i]);
 CloseFile(F);
end;

Но если текстовый файл уже есть, то читать его можно так:

var
 A: array [N..M] of double;
 F: TextFile;
 i: integer;
begin
 AssignFile(F, 'имя  файла');
 Reset(F);
 for i := N to M do
   Read(F, A[i]); // Если числа разделены пробелами
   // ReadLn(A[i]); // Если каждое число с новой строки
 CloseFile(F);
end;


sniknik   (2012-01-18 00:17:00) [68]

> 11 45678 5554 555545 77766 {bla bla ....{очень много}... bla}#13#10
???
Ega23 ©   (17.01.12 19:19) [9]
> Так их и надо писать изначально не в виде текста, а в виде набора double


Dennis I. Komarov   (2012-01-17 23:11:00) [69]


> sniknik ©   (17.01.12 23:02) [16]

так все и рассказали в [0] (как обычно :))
11 45678 5554 555545 77766 {bla bla ....{очень много}... bla}#13#10
B64[тут еще комент или Bitmap]
................
776876 77776 767878 76988


sniknik   (2012-01-17 23:02:00) [70]

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


Anatoly Podgoretsky   (2012-01-17 21:36:00) [71]


> > Используй тип Текстовый файл.
>
>
> Для компьютера все файлы суть двоичные. Текстовость файла
> это проблема интерпретации. Следовательно, при правильной
> интерпретации массив доубле можно прочесть при помощт тфилестреам.
>

Поддержка текстовых файлов встроена в компилятор, ничего самому интерпритировать не требуется.

Read(F, A[I])


Dimka Maslov   (2012-01-17 19:30:00) [72]


> может сам файл возможно как-то конвертировать?


Написать прогу, которая читает текст и записывает в другой файл двоичные данные?


Ega23   (2012-01-17 19:29:00) [73]

Не, если файл чётко структурирован, то ускорить, пожалуй, можно.
Например, число (строго 5 символов до разделителя, разделитель строго запятая, строго 8 символов после разделителя), дЖва пробела, число, ..., 10-е число, перевод строки (строго #13#10).
Тогда можно ускорить. Но на копейки.


Ega23   (2012-01-17 19:29:00) [74]


> может сам файл возможно как-то конвертировать?


Тогда это будет уже 3-я программа. :)


Alexander123   (2012-01-17 19:25:00) [75]


> Так их и надо писать изначально не в виде текста, а в виде
> набора double

это уже другая программа их записывает в таком виде
может сам файл возможно как-то конвертировать?


Dimka Maslov   (2012-01-17 19:23:00) [76]


> реально приходится работать с файлами, состоящими, например,
>  из миллиона точек


Тогда - либо действительно изначально создаём файл в виде набора double, либо читаем побайтно, преобразуя строки в числа. Впрочем read/readln так и поступают. Тут уже не убыстрится.


Ega23   (2012-01-17 19:19:00) [77]


> реально приходится работать с файлами, состоящими, например,
>  из миллиона точек


Так их и надо писать изначально не в виде текста, а в виде набора double


Alexander123   (2012-01-17 19:17:00) [78]


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


число 10 я тут от балды поставил) с маленькими файлами проще проверять правильность работы
реально приходится работать с файлами, состоящими, например, из миллиона точек
и вот тут уже важна и скорость работы


Dimka Maslov   (2012-01-17 19:08:00) [79]


> пытаюсь ускорить работу


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


Alexander123   (2012-01-17 19:02:00) [80]


> Если файл действительно текстовый, то проще Read или Readln
> ничего не придумано.

файл действительно текстовый
но проблема в том, что с большими файлами read и readln работает довольно медленно
пытаюсь ускорить работу


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо