Сейчас на форуме: vasilevradislav, tyns777, zombi-vadim (+3 невидимых)

 eXeL@B —› Программирование —› Изменение куска файла
Посл.ответ Сообщение

Ранг: 113.4 (ветеран)
Активность: 0.130
Статус: Участник
Ветеран

Создано: 09 февраля 2008 17:37 · Поправил: locker_fx
· Личное сообщение · #1

Всем привет!
Скорее всего название темы не совсем точно раскрывает вопрос, но ничего лучше в голову не пришло.

Вобщем есть прога(Delphi). Необходимо прочитать файл, найти метку, и заменить её на что-то(это что-то вычисляется программой в процессе работы). Сейчас делаю так читаю весь файл в одну строку, потом ищу там метки заменяю их и сохраняю в другие файлы.
НО появилась проблема. Если так читать/писать файл, то файл превращается в однострочную кашу. И это создаёт большие трудности.
Собственно как можно обойти мои грабли? Читать построчно и одновременно записывать нерезонно, т.к. файлов должно получаться на выходе много.

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

Делать блочное чтение/запись кажется не рационально, т.к. работаю с текстовыми файлами.

Понимаю, что вопрос глуп, но уже голова не соображает, а сделать надо срочно.

Вобщем очень надеюсь на ваши советы. Заранее огромное спасибо!

-----
моя подпись!




Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 09 февраля 2008 17:54
· Личное сообщение · #2

Если скорость не важна, то можно воспользоваться форматом "ini"(Через WritePrivateProfileString):
[section1]
variable1=value1
variable2=value2
[section2]
variable1=value1
variable2=value2
и т.п.
Очень удобно и быстро (в смысле кодинга).

-----
продавец резиновых утёнков





Ранг: 107.6 (ветеран)
Активность: 0.110
Статус: Участник

Создано: 09 февраля 2008 18:01
· Личное сообщение · #3

locker_fx пишет:
Появилась идея читать файл строками в массив

Хорошая идея.. если обрабатываемый файл - не больше метра.. Дальше могут начаться косяки... (правда, справедливо для Borland C++.. на дельфях не кодил..)

-----
программистом не рождаются - им умирают




Ранг: 113.4 (ветеран)
Активность: 0.130
Статус: Участник
Ветеран

Создано: 09 февраля 2008 18:48
· Личное сообщение · #4

Gambit пишет:
Хорошая идея.. если обрабатываемый файл - не больше метра.. Дальше могут начаться косяки... (правда, справедливо для Borland C++.. на дельфях не кодил..)

меньше метра. скореее всего даже за 100кб выходить не будет.

-----
моя подпись!





Ранг: 340.0 (мудрец), 22thx
Активность: 0.120
Статус: Участник
THETA

Создано: 09 февраля 2008 21:45
· Личное сообщение · #5

locker_fx пишет:
найти метку, и заменить её на что-то(это что-то вычисляется программой в процессе работы)

Хм, 1-ый и вполне логичный вопрос: метки, раз ты их заменяешь на свои, ты заменяешь на свои, по своему какому-то алгоритму? Если файлы однотипные, то вообщем-то есть резон создавать именно массив у указателями на каждый конкретный элемент, потому как в случае сортировки можно будет применить стандартный сортировочный алгоритм...

-----
Программист SkyNet




Ранг: 113.4 (ветеран)
Активность: 0.130
Статус: Участник
Ветеран

Создано: 09 февраля 2008 22:20 · Поправил: locker_fx
· Личное сообщение · #6

FrenFolio пишет:
Хм, 1-ый и вполне логичный вопрос: метки, раз ты их заменяешь на свои, ты заменяешь на свои, по своему какому-то алгоритму? Если файлы однотипные, то вообщем-то есть резон создавать именно массив у указателями на каждый конкретный элемент, потому как в случае сортировки можно будет применить стандартный сортировочный алгоритм...

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

Думаю вариант с чтением в массив оптимален.

HiEndsoft пишет:
Если скорость не важна, то можно воспользоваться форматом "ini"(Через WritePrivateProfileString):
[section1]
variable1=value1
variable2=value2
[section2]
variable1=value1
variable2=value2
и т.п.
Очень удобно и быстро (в смысле кодинга).

В данном случае скорость важна. А вообще интересная вещица можно будет где-нибудь применить. Например работа с файлом конфигурации(думаю логично что есть аналогичная функция для чтения).

-----
моя подпись!




Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 09 февраля 2008 22:43 · Поправил: HiEndsoft
· Личное сообщение · #7

locker_fx пишет:
думаю логично что есть аналогичная функция для чтения

Да есть, читай MSDN (GetPrivateProfileString и GetPrivateprofileInt),
разница в том что API ф-ции данного класса предназначены для работы с ini файлами и реестром и
в одном вызове выполняют CreateFile, ReadFile с поисковым алго и CloseHandle...Т.к. они при каждом вызове заново открывают файл, то их частое использование и в циклах очень накладно. Но для чтения конфигурации - самое то.
Для своей задачи попробуй спроецировать свой файл в память, и менять копии проекции, меньше работы с файлом - больше быстродействие.

-----
продавец резиновых утёнков




Ранг: 113.4 (ветеран)
Активность: 0.130
Статус: Участник
Ветеран

Создано: 10 февраля 2008 00:05
· Личное сообщение · #8

HiEndsoft пишет:
Для своей задачи попробуй спроецировать свой файл в память, и менять копии проекции, меньше работы с файлом - больше быстродействие.

Именно так и делаю. Но раньше вся проекция представляла из себя одну строку, а теперь переделал под массив.

-----
моя подпись!





Ранг: 340.0 (мудрец), 22thx
Активность: 0.120
Статус: Участник
THETA

Создано: 10 февраля 2008 09:58
· Личное сообщение · #9

locker_fx пишет:
Думаю вариант с чтением в массив оптимален.

Видимо, в этом случае, да. Дальше же HiEndsoft пишет:
попробуй спроецировать свой файл в память, и менять копии проекции
, тем самым по возможности минимизировав работу с жестким диском. Это позволит значительно увеличить быстродействие, особенно если потом последовательно переписывать выделенные текстовые файлы, уже из массива.

-----
Программист SkyNet




Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 10 февраля 2008 12:26
· Личное сообщение · #10

locker_fx пишет:
Но раньше вся проекция представляла из себя одну строку

Как это CreateFileMapping, в строку???

-----
продавец резиновых утёнков





Ранг: 107.6 (ветеран)
Активность: 0.110
Статус: Участник

Создано: 10 февраля 2008 15:42
· Личное сообщение · #11

locker_fx пишет:
меньше метра. скореее всего даже за 100кб выходить не будет.

Тогда обрати внимание на функу ReadFile

Вот как я реализовывад подобное:

char buffFile[1000000]; // максимальный размер файла - 1000000 байт

/*А тут мы открываем файлик*/
////////////////////////////////////////////////////////////////////// ///////////////
HANDLE hFile = CreateFile ("serial.txt",GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
MessageBox (0,"А где serial.txt ?\nВерните его взад!!! ","Ой!",MB_ICONERROR | MB_RTLREADING);
return 0;
}
////////////////////////////////////////////////////////////////////// ///////////////
if (GetFileSize(hFile,NULL)>1000000) {
MessageBox (0,"Аффигительный размер файла!\n"
"Я столько не выпью. \n"
"(максимум - 976,5625 Кбайт)","Да Вы с ума сошли!?",0);
return 0;
}


ReadFile (hFile,buffFile,GetFileSize(hFile,NULL),&dwBytesRead,NULL);

Далее, читаешь из массива buffFile... и записываешь все что нужно через WriteFile

-----
программистом не рождаются - им умирают




Ранг: 43.2 (посетитель)
Активность: 0.020
Статус: Участник

Создано: 11 февраля 2008 09:30
· Личное сообщение · #12

Ну если на Delphi, то проще так:
var tmpS: TStrings;
begin
try
tmpS:=TStringList.Create;
// читаем файл
TmpS.LoadFromFile('myfile.txt');
// тут работаем как с массивом строк через TmpS[i]
...
// сохраняем файл
TmpS.SaveToFile('myfile.txt');
finally
tmpS.Free
end;
end;



Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 11 февраля 2008 11:59 · Поправил: HiEndsoft
· Личное сообщение · #13

Работа с оч. большими массивами тоже не быстрая, чтение/запись файла лучше производить выборочно, в зависимости от задачи по 1 Сектору или Track'у, быстрее будет + в асинхронном режиме с вкл. флагами оптимизации кеша FILE_FLAG_SEQUENTIAL_SCAN и т.п.

-----
продавец резиновых утёнков




Ранг: 284.8 (наставник), 6thx
Активность: 0.150
Статус: Участник

Создано: 11 февраля 2008 14:30
· Личное сообщение · #14

locker_fx
А длина искомых меток и тех на которые заменяешь одинакова? ( скажем, например, 4 байта )



Ранг: 24.1 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 14 февраля 2008 19:39 · Поправил: RedAbishai
· Личное сообщение · #15

Я так понимаю, файл текстовый, а не какой-нибудь бинарник? В общем случае длина метки до/после изменения будет отличаться? Если длина не отличается, то неплохо использовать мемори-маппинг (плюсы: нет проблем с чтением/записью, о буферизации заботится сама винда, как-то читал результаты тестирования - довольно неплохо справляется).



Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 14 февраля 2008 19:48 · Поправил: HiEndsoft
· Личное сообщение · #16

RedAbishai Ты сначала читать умеешь & даты видишь? Я это уже 5 дней назад предложил. Посты набивать нехорошо. А про кеширование см. пост выше с флагом FILE_FLAG_SEQUENTIAL_SCAN. И не "читай где-то" а сам пробуй.

-----
продавец резиновых утёнков




Ранг: 24.1 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 14 февраля 2008 20:09
· Личное сообщение · #17

HiEndsoft Молодец, что первый предложил мемори-маппинг использовать, теперь копирайт поставить можешь. И посты я не набиваю. А насчет сравнения скорости - покажи результаты замеров, всем будет интересно посмотреть и со своими сравнить. Мне достаточно было того, что прочитал - незачем каждый раз учиться на собственных ошибках и велосипед изобретать.



Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 14 февраля 2008 20:30 · Поправил: HiEndsoft
· Личное сообщение · #18

Я про скорость ничего не говорю, поэтому и предложил сразу же проекцию, потому что чуваку часто к файлу обращаться.
Не втему: Если хочешь знать: скорость работы с проекцией и "сырым файло" практически одинакова, если указать флаг кеширования и правильно подобрать размеры буферов ReadFile и WriteFile исходя из DISK_GEOMETRY (что и нужно делать всегда). Совсем недавно "ручками" нужно было делать копию флэшки в виде RAW-образа, так вот что в мап писать что сразу на диск - один хрен все в кэш пишется и флюшится системой в фоне. Причем если вкл. сжатие файло, то у меня (т.к. на флеши 40% занято всего было) кеш отлично оптимизировался системой и реально (ч/з QueryVMem видно) не был забит лишними нулями и был 40% (иди прочитай где про это написано, если найдешь).
Иди читай "тесты" дальше. Мне проще и интересней велосипед поизобретать, если из него в итоге мотоцикл получается (а если нет +опыт), чем "тупотесты" по ламер-сайтам искать.

-----
продавец резиновых утёнков




Ранг: 113.4 (ветеран)
Активность: 0.130
Статус: Участник
Ветеран

Создано: 16 февраля 2008 20:21
· Личное сообщение · #19

RSI пишет:
А длина искомых меток и тех на которые заменяешь одинакова? ( скажем, например, 4 байта )

Нет длинна отличается.

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

-----
моя подпись!




Ранг: 6.4 (гость)
Активность: 0=0
Статус: Участник

Создано: 18 февраля 2008 19:53
· Личное сообщение · #20

Сам немного таким занимался вопросом, решение нашел в TStringList, но при загрузке возникали ньансы с метками конца файла. Посмотри в сторону TFileStream, TMemoryStream.

Еще записывая файлы блоками на больших объемах это занимает много времени, особенно если через Writeln.


 eXeL@B —› Программирование —› Изменение куска файла
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати