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