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

Вниз

FileRead(Write)   Найти похожие ветки 

 
SMAC   (2006-02-27 18:20) [0]

Ув. мастера!

Мои данные представляют из себя таблицу и хранятся в текстовом ASCII файле. Например:

0,1 123 544 600
0,2 124 544 650
...
1,1 127 545 800
...

Файл довольно большой (неск. мегабайт). Хочу загрузить в свою программу как массив (а потом обработать). Быстро.
Если же читаю файл с данными построчно и разделяю на фрагменты, а потом еще и перевожу из строк в числа - получается очень медленно.
Похожим извращением я занимался тогда, когда примерно таким же способом загружал текстовый файл в TMemo несколько лет назад. А оказалось, что есть такая штука как LoadFromFile и всё встало на свои места. Есть ли аналогичные методы и для моего случая?

Интересует также и запись в файл (потом, после обработки).

Заранее спасибо.


 
Eraser ©   (2006-02-27 18:25) [1]


> SMAC   (27.02.06 18:20)


>  Есть ли аналогичные методы и для моего случая?

Если примерно до 10 МБ размер, то TStringList.LoadFromFile, иначе - TFileStream, по скорости будет не намного быстрее чем ReadLn.


 
SMAC   (2006-02-27 18:48) [2]

Имеется в виду загрузить содержимое файла в абстрактный TStringList и потом обрабатывать построчно? А почему ограничение в 10 Мб?
Что касается скорости - этот способ наиболее быстрый? Ну, в сравнеии с ReadLn или TStream?

По TFileStream нашел ещё http://delphimaster.net/view/2-1140545982/. Похожая беда.


 
Eraser ©   (2006-02-27 18:57) [3]


> SMAC   (27.02.06 18:48) [2]


> Имеется в виду загрузить содержимое файла в абстрактный
> TStringList и потом обрабатывать построчно?

Да, только TStringList не абстрактный.

> А почему ограничение в 10 Мб?

эт примерная цифра... чтобы памяти много не отъедала программа.

> По TFileStream

это другой подход, похожий на Readln, т.е. данные считываются не все сразу, а построчно... TFileStream в таких случаях лучше применять при значительных размерах файлов.
А вообще всё от конкретной ситуации зависит.


 
Desdechado ©   (2006-02-27 19:08) [4]

какой смысл хранить таблицу в тексте, если ее можно хранить в БД?


 
Virgo_Style ©   (2006-02-27 19:39) [5]

Desdechado ©   (27.02.06 19:08) [4]

это могут быть чьи-то логи.

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

Кажется, удалось ускорить процесс, выбрасывая "тупые" фрагменты вроде

p:=pos(" ",S);
S1:=copy(S,1,p);
delete(S,1,p+1);

p:=pos(" ",S);
S2:=copy(S,1,p);
delete(S,1,p+1);


и заменяя их на разбиение строки в один проход, причем с минимумом выделений памяти под строку, т.е. нельзя делать
while S[i]<>" " do begin
 S1:=S1+S[i];
 inc(i);
end
,
а можно
j:=1;
SetLength(S1,100);
while S[i]<>" " do begin
 S1[j]:=S[i];
 inc(i);
 inc(j);
end;


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


 
SMAC   (2006-02-28 09:51) [6]

Для Desdechado.
Я пользуюсь результатами расчетов довольно древней специализированной программы, а у нее либо никак, либо только так можно наладить интерфейс.
А вот сохранять можно попробовать и в ВД и в нетипизированном файле. Кстати говоря - проверено горьким многолетним опытом - чем больше будет файл с данными и чем проще будет в нем представление отдельных значений - тем меньше вероятность потерять данные. Как у Архимедовского рычага - проигрываем в скорости - выигрываем в расстоянии.

Для Virgo_Style.
Попробую и так. Вообще-то когда-то очень давно что-то читал (зрительная память самая крепкая), что ускорить работу можно путем использования указателей и буферов. Кто что скажет?

Всем спасибо.


 
Сергей М. ©   (2006-02-28 10:19) [7]


> ускорить работу можно путем использования указателей и буферов


Смотря что подразумевать под "работой" ..


> сохранять можно попробовать и в ВД и в нетипизированном
> файле


Судя по приведенному фрагменту внутр.структуры файла длины всех строк, записанных в него, одинаковы, а поля в каждой из строковых записей фиксированы по смещениям отн-но начала строки

Следовательно, к строковым записям и полям в них можно обращаться с произвольным (а не последовательным) доступом, использовав обычный FileStream либо написав своего наследника TDataSet для навигации по файлу как по табличному НД.


 
Mikhail V ©   (2006-02-28 10:32) [8]

Отображение в память не ускорит дело?


 
SMAC   (2006-02-28 12:31) [9]

А подробнее?


 
SMAC   (2006-02-28 12:44) [10]


> Судя по приведенному фрагменту внутр.структуры файла длины
> всех строк, записанных в него, одинаковы, а поля в каждой
> из строковых записей фиксированы по смещениям отн-но начала
> строки

Это только в том куске, который я привел, а так может быть произвольной:

0,1 123 544 600
0,2 124 544 650
...
10,1 1027 545 400
...

И даже (в других файлах) через степень "E":
скажем, 1,245683E+3

Во всяком случае перевожу всегда с помощью
function StrToFloat(const S: string): Extended;

Исходный массив: array of string;
Конечный массив: array of Extended;

Это если подробнее.


 
Mikhail V ©   (2006-02-28 13:00) [11]

См. File Mapping


 
SMAC   (2006-02-28 13:09) [12]


> См. File Mapping


Где? По F1 нет ничего.


 
Mikhail V ©   (2006-02-28 13:10) [13]

Win32 Developer"s References


 
SMAC   (2006-02-28 13:18) [14]

Можно линк?
Желательно на FREE и лучше всего RU.


 
Mikhail V ©   (2006-02-28 13:30) [15]

Win32 Developer"s References - входит в поставку Delphi


 
Сергей М. ©   (2006-02-28 13:53) [16]


> Это только в том куске, который я привел, а так может быть
> произвольной


Какого ж ххх ты об этом не говоришь сразу ? Телепатов тут нет.

И это резко осложняет "дело" ..


 
SMAC   (2006-02-28 13:53) [17]

Уже сходил по
"Пуск->Программы->Borland Delphi 5->Help->MS SDK Help Files".

Читаю по диагонали. Нового мало.

Как слить файл в буфер? Код можно?


 
SMAC   (2006-02-28 14:02) [18]

Для Сергей М.
Я же тоже не телепат.
На 100% правильно поставленный вопрос - это уже практически ответ на него. Во всяком случае чтобы такой вопрос задать нужно уже практически всё по этому вопросу знать.


 
Сергей М. ©   (2006-02-28 14:26) [19]


> SMAC   (28.02.06 14:02) [18]
> На 100% правильно поставленный вопрос - это уже практически
> ответ на него


Нет тех самых 100% в правильности твоего вопроса.
Хотя бы потому что ты изначально умалчиваешь, как часто требуется проделывать всю эту петрушку. Из-за этого и "телепаты" всплывают.
Если это разовый импорт, то и программу писать, возможно, нет повода ..


 
Mikhail V ©   (2006-02-28 14:57) [20]


function MapFileData(const FileName: string; var Buffer: Pointer): DWORD;
var
 hFile: THandle;
 hMap: THandle;
begin
 hFile := FileOpen(FileName, fmOpenReadWrite or fmShareExclusive);
 if hFile <> INVALID_HANDLE_VALUE then
 begin
   Result := GetFileSize(hFile, nil);
   hMap := CreateFileMapping(hFile, nil, PAGE_READWRITE, 0, Result, nil);
   if hMap <> 0 then
   begin
     Buffer := MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
     CloseHandle(hMap);
   end;
   CloseHandle(hFile);
 end;
end;


 
SMAC   (2006-02-28 14:57) [21]

Импорт данных необходимо делать всякий раз как нужно сделать расчет в другой программе. Файлом выходных данных этой программы пользуюсь не только я. Моя цель, не переписывая этой программы (на самом деле это не одна программа а пакет однотипных), обработать эти данные и переписать в уже мой выходной файл.
Ну вот и как считать это разовой задачей? Файлов данных десятки только уже предварительно отфильтрованных (кстати с помощью моей программы), а с учетом того, что на каждый "одобренный" еще с десяток промежуточных - и счет уже на сотни.
Короче, не на один раз если это опять таки важно.


 
SMAC   (2006-02-28 14:58) [22]

Спасибо, Mikhail V.
Буду пробовать.


 
Сергей М. ©   (2006-02-28 14:59) [23]


> Короче, не на один раз если это опять таки важно


Значит , тебе прямая дорога в СУБД ..


 
SMAC   (2006-02-28 15:33) [24]

Для Сергей М.Мне нужна дорога "из" а не "в".
Формат исходного файла - не БД, а обычный (см. пост [0]) текстовый файл.

Для Mikhail V.
Разбираюсь с указателями. Обидно, что в который уже раз.


 
Сергей М. ©   (2006-02-28 15:55) [25]


> Формат исходного файла - не БД, а обычный


Вот я и предлагаю импорт данных из исх.файла в любую из подходящих БД


 
SMAC   (2006-02-28 15:55) [26]

Написал для проверки следующее:
procedure TForm1.Button1Click(Sender: TObject);
var
p1 : array of integer;
i : integer;
p : Pointer;
dw : DWORD;
begin
dw := Form1.MapFileData("c:\temp\data\data.txt", p);
p1 := p;
Memo1.Text := IntToStr(dw);
for i := 0 to dw-1 do
begin
Memo1.Text := Memo1.Text + ^m^j + IntToStr(p1[i]);
end;

Всё отлично работает, если принять, что данные хранятся в файле с данными в виде 32-битных интейджеров.

У меня же файле исключительно строковое представление данных (неважно - integer или extended). Как читать строковае представление? array of string делает бред.


 
Zeqfreed ©   (2006-02-28 16:05) [27]


> array of string делает бред

К счастью «array of string»"а, бред может делать только программист. Сомневаюсь, что отображение в память как-то поможет при обработке небольших объемов (вроде, у Вас набольшие?). Чем не понравилось чтение в TStringList и обработка его методами?


 
Сергей М. ©   (2006-02-28 16:12) [28]


> SMAC   (28.02.06 15:55) [26]


На то тебе и был намек - TStringList.LoadFromFile.

Исходные тексты доступны, проанализировать их и приспособить под свои нужды думающему человеку не составит труда.


 
Mikhail V ©   (2006-02-28 16:25) [29]


> Zeqfreed ©  

> SMAC   (27.02.06 18:20)  
...Файл довольно большой (неск. мегабайт). ...

> SMAC   (28.02.06 15:55) [26]

Миллион способов сделать то, что Вы хотите. Напр. подключиться через
ODBC используя драйвер CVS и.т.д...
Бросте мне на мыло свой "довольно большой" файл (предварительно
заархивировав :)). Посмотрим, подумаем...


 
SMAC   (2006-02-28 17:56) [30]

Короче я понял, что строковые представления чисел некаким методом кроме загрузки в TStringList никто кроме Mikhail V предложить не может?

Для Mikhail V.
Файлы дома. Завтра постараюсь не забыть и прислать один из них.

Всем спасибо.
"Завтра нас рассудит"


 
SMAC   (2006-02-28 18:24) [31]

Mikhail V!

Ничего, что 2Мб кусок файла в RAR-архиве с максимальным сжатием будет весить около 1 Мб?

"Представления о жизни бывают разные"


 
SMAC   (2006-02-28 18:30) [32]

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

Столбец A: значения от 0 с шагом 0,1
Столбец B: функция вида SIN(A1/100)*20+COS(A1/10)*80
Столбец C: функция вида SIN(A1/5)*20+COS(A1/10)*80
и т.д.

Растянуть до конца листа и сохранить в *.txt или *.csv с разделителями запятыми, а потом в том же Word заменить запятые на пробелы.
Файл будет весить около 2Мб (при трех столбцах). Потом можно склеить раз пять и будут все 10Мб.

Ей-богу будет тот же объем и чистота эксперимента нарушится минимально.


 
SMAC   (2006-03-01 10:20) [33]

Всем спасибо.

Меня устраивает TStringList. Во всяком случае пока. Выигрыш по времени колоссальный.

Насколько я понимаю есть только неумолимое ограничение в 2147483647 ($7FFFFFFF)строк (тип integer). Но у меня даже при 10Мб файле количество строк около 350000 ($55555). Запас более чем достаточный, в несколько тысяч. В связи с этим хочу предположить, что ограничение в 10Мб от Eraser было получено не без использования Randomize. :)

Мне хотелось разделить процесс загрузки данных из файла от процесса обработки, минимизировать по времени первый процесс и это всё получилось.

Ещё раз спасибо всем.

ЗЫ
А вот про запись данных в файл я видимо погодя темку создам. ;)



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

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

Наверх




Память: 0.53 MB
Время: 0.016 c
2-1141053632
SMAC
2006-02-27 18:20
2006.03.19
FileRead(Write)


15-1140778468
paza
2006-02-24 13:54
2006.03.19
Нестандартные шрифты


15-1140681266
Igorek
2006-02-23 10:54
2006.03.19
Новый LCD монитор :)


15-1140582029
ЮЮ
2006-02-22 07:20
2006.03.19
С Днем защитника Отечества !!!


9-1124125200
Dgt
2005-08-15 21:00
2006.03.19
Glscene &amp; Gl_Ext_Separate_Specular_color





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский