Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.19;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.027 c
6-1134163974
Змей
2005-12-10 00:32
2006.03.19
ошибка при закрытии программы


3-1138109339
Tornado
2006-01-24 16:28
2006.03.19
MS SQL Server Connect


1-1139816713
BanderLog
2006-02-13 10:45
2006.03.19
Отображение длительных процессов


1-1139837066
Gamer
2006-02-13 16:24
2006.03.19
Работа с файлом и несколькими RichEdit ами


3-1138366105
diz22
2006-01-27 15:48
2006.03.19
Кол-во записей в DBF. Критично ли 600 000?