Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];

Вниз

чтение массива double с помощью TFileStream   Найти похожие ветки 

 
Alexander123 ©   (2012-01-17 18:11) [0]

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

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?


 
Германн ©   (2012-01-17 18:29) [1]


> Имеется текстовый файл с числами

Текст нужно читать как текст, а не как числа.


 
Anatoly Podgoretsky ©   (2012-01-17 18:32) [2]

> Alexander123  (17.01.2012 18:11:00)  [0]

Используй тип Текстовый файл.


 
Alexander123 ©   (2012-01-17 18:52) [3]


> Германн ©   (17.01.12 18:29) [1]

т.е. надо считать данные из файла как массив byte, потом найти в нем символы, соответствующие цифрам (чтобы избавится от пробелов) и далее переводить в double? есть ли более простой способ?


 
Dimka Maslov ©   (2012-01-17 18:52) [4]


> Используй тип Текстовый файл.


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


 
Германн ©   (2012-01-17 18:56) [5]


> есть ли более простой способ?
>

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


 
Alexander123 ©   (2012-01-17 19:02) [6]


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

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


 
Dimka Maslov ©   (2012-01-17 19:08) [7]


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


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


 
Alexander123 ©   (2012-01-17 19:17) [8]


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


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


 
Ega23 ©   (2012-01-17 19:19) [9]


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


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


 
Dimka Maslov ©   (2012-01-17 19:23) [10]


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


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


 
Alexander123 ©   (2012-01-17 19:25) [11]


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

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


 
Ega23 ©   (2012-01-17 19:29) [12]

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


 
Ega23 ©   (2012-01-17 19:29) [13]


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


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


 
Dimka Maslov ©   (2012-01-17 19:30) [14]


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


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


 
Anatoly Podgoretsky ©   (2012-01-17 21:36) [15]


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

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

Read(F, A[I])


 
sniknik ©   (2012-01-17 23:02) [16]

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


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


> 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-18 00:17) [18]

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


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

> 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;


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


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

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


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


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

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


 
Ega23 ©   (2012-01-18 02:11) [22]


> Самуилыч   (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;


 
Ega23 ©   (2012-01-18 02:13) [23]


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


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


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


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

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


 
Alexander123 ©   (2012-01-18 09:49) [25]

Всем спасибо за ответы.
Оказалось, что я сам себе проблему придумал)) 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 обновить


 
Dimka Maslov ©   (2012-01-18 10:40) [26]


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


Наверняка у TChart есть метод типа BeginUpdate, который блокирует перерисовку и прочие лишние вещи при массовой модификации данных.


 
sniknik ©   (2012-01-18 10:50) [27]

> смысл этого в том, чтобы избегать использование addXY():
поищи другой смысл... ну например чтобы добавлять не точки, рекордсет к примеру.


 
Inovet ©   (2012-01-18 11:06) [28]

> [25] Alexander123 ©   (18.01.12 09:49)

Эта, текст форматировать желательно, а то ведь глаза ломаются, не за что зацепиться. Например так:

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;

Сразу видно - чего-то не хватает. И у читающих больше желания просмотреть и вникнуть.


 
bumbum   (2012-01-18 11:35) [29]

И я предложу свой вариант:

var
s: TStringList;
begin
s:= TStringList.Create;
if opendialog1.Execute then
s.LoadFromFile(opendialog1.FileName);


 
Ega23 ©   (2012-01-18 11:40) [30]


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


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


 
Самуилыч   (2012-01-18 11:51) [31]

> Ega23 ©   (18.01.12 02:11) [22]
> Зачем так сложно?

AssignFile, Reset, Read, CloseFile - ЭТО сложно?
Хм... или LOL ?


 
Ega23 ©   (2012-01-18 11:57) [32]


> AssignFile, Reset, Read, CloseFile - ЭТО сложно?


На асме сразу пиши, там, в целом, тоже ничего сложного нет.


 
Dennis I. Komarov ©   (2012-01-18 11:58) [33]


> sniknik ©   (18.01.12 00:17) [18]

само собой, но [11] же...


 
sniknik ©   (2012-01-18 12:32) [34]

> но [11] же...
и что? рекорсед это такой же набор данных как массив например. все воспринимают его как "= база", но это неправильно. читать не в массив, а в рекордсет и все дела. проблема?


 
sniknik ©   (2012-01-18 12:34) [35]

> читать не в массив
+
а если и сохранять как рекордсет, то и с чтением меньше мороки.


 
Самуилыч   (2012-01-18 16:34) [36]


> Ega23 ©   (18.01.12 11:57) [32]

Дружище, фии... ведь это уже демагогия... некрасиво же. Ай-яй-яй.


 
Ega23 ©   (2012-01-18 16:53) [37]


>  ведь это уже демагогия... некрасиво же. Ай-яй-яй.


Ты предлагаешь сравнить варианты с последовательным чтением каждого double, или чтения целиком?


 
Dennis I. Komarov ©   (2012-01-18 17:53) [38]


> sniknik ©   (18.01.12 12:32) [34]

У меня?
У меня нет такого файла, и я даже не знаю его структуры. Откуда могут у меня появится проблемы. :)


 
Самуилыч   (2012-01-18 19:43) [39]


> Ega23 ©   (18.01.12 16:53) [37]

Во-первых, я предлагаю не использовать "доводы" типа [32].

Во-вторых, AssignFile-Reset-Read-CloseFile - это не сложный, а, наверное, наоборот, самый простой способ чтения файла на Паскале.

В-третьих, при любом способе (сразу весь или кусками) будет буферизация, поэтому разница не должна быть большой. И в [25] автор написал, что даже при чтении кусками тормоза совсем в другом - так что способ чтения здесь тем более по барабану.


 
Ega23 ©   (2012-01-18 20:08) [40]


> Во-вторых, AssignFile-Reset-Read-CloseFile - это не сложный,
>  а, наверное, наоборот, самый простой способ чтения файла
> на Паскале.


1. Речь не о Паскале, а о Delphi 7. И  FileStream тут будет гораздо более удобней. И проще. В связи с этим


> Во-первых, я предлагаю не использовать "доводы" типа [32].


вкупе с [31] воспринимается смешно.


> В-третьих, при любом способе (сразу весь или кусками) будет
> буферизация, поэтому разница не должна быть большой


А ты возьми и проверь. На 10 миллионов значений. FileStream - 93 ms. Assign-Read-Close: 16708 ms
Разница не очень большая, всего в 180 раз. Буферизация, тем более... :)



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

Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.004 c
2-1326879729
i2e
2012-01-18 13:42
2012.05.20
Проверить TDrawGrid на установленные опции


15-1326277214
OW
2012-01-11 14:20
2012.05.20
по Oracle и PL/SQL Developer. Как его научить автоформатировать?


15-1326482274
Riply
2012-01-13 23:17
2012.05.20
Фриланс на исходниках.


4-1257109119
Maksim V.
2009-11-01 23:58
2012.05.20
Запретить DrawFocusRect. при отрисовке строк Listbox


2-1326880929
gvozdkoff
2012-01-18 14:02
2012.05.20
чтение из файла и проблема при его перезаписи





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский