Форум: "Начинающим";
Текущий архив: 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