Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.147.47.59] |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Насколько я понял, задание в #1 выделено жирным шрифтом, и там ничего не сказано о том, что можно, а что нельзя. Но у ТС это не первое задание на обработку текстовых файлов размером до 500-700 Мб, и все его попытки использовать TStringList в XE4 приводят к out of memory. Причина, надеюсь, всем понятна - удвоение занимаемой памяти при (тупом, и в данном случае совершенно ненужном) преобразовании AnsiString в юникод. Если бы стояла задача решить проблему только на уровне работы с файлами без их полной загрузки в память, то можно было бы сразу задать размер файла в 2 и более Гб. Но поскольку речь идет именно о 500-700 Мб, то это явно вопрос "на засыпку", который предполагает, что данную задачу можно решить и с загрузкой всего файла в память. |
Сообщ.
#17
,
|
|
|
Как вообще при наличии свопа может взбухать out of memory на жалких полтора гига? Тем паче что это не один кусок, а куча независимых строк.
Автору: задача явно учебная, ибо осмысленности в ней ноль, поэтому надо сразу указывать четкую формулировку. По сабжу: - первый проход - чтение построчно, сохранение для каждой строки смещений относительно начала файла - перемешивание - создание второго массива смещений, наполнение его рандомными элементами из первого массива. Либо проход по каждому элементу исходного массива и обмен значениями текущего элемента с рандомным - выдача результата - проход по перемешанному массиву, позиционирование+readln(f_src, s)+writeln(f_dst, s) |
Сообщ.
#18
,
|
|
|
Цитата Fr0sT @ Как вообще при наличии свопа может взбухать out of memory на жалких полтора гига? Тем паче что это не один кусок, а куча независимых строк. Ты знаешь, как работает TStrings.LoadFromFile\Stream? В D7 весь файл читается в локальную переменную s:AnsiString и затем формируется список строк простым вызовом Strings.Text:=s. При размере файла до 700 Мб и более, это уже может вызвать проблемы в 32-битном приложении, т.к. из-за фрагментации адресного пространства (АП) может просто не оказаться непрерывного диапазона адресов такого размера (из-за некоторых дурных dll, норовящих загрузиться в середину АП). Но в современных XE это реализовано еще тупее - сначала весь файл читается в дин.массив TBytes, а затем вызовом TEncoding.GetString из этого массива формируется юникод-строка (удвоенного размера, если файл представлен в ANSI), которая затем используется для формирования списка тем же Strings.Text:=s. Сам понимаешь, что в 32 битном приложении два непрерывных куска памяти по 700 и 1400 Мб, плюс более 1400 Мб отдельных строк - уже ни в какие ворота не лезут. Отсюда и out of memory. И никакой своп тут ни при чем, т.к. просто\банально не хватает нужного адресного пространства. PS: Такая реализация прекрасно работает для текстовых файлов "нормального" размера. Поэтому это не тупость Борланда\Эмбаркадеро, а тупость тех, кто пытается использовать TStrings.LoadFromFile для текстовых файлов нереально большого размера. |
Сообщ.
#19
,
|
|
|
leo, да, про момент загрузки я забыл, каюсь. К сожалению, с покусочным чтением не стали заморачиваться (хотя Эмбы и не одни в этом - даже более специализированный редактор Akelpad тоже грешит таким неоптимальным механизмом).
Связка TFileStream+TStreamReader (либо старый добрый Readln) поможет избежать перерасхода памяти |
Сообщ.
#20
,
|
|
|
Цитата Fr0sT @ Связка TFileStream+TStreamReader (либо старый добрый Readln) поможет избежать перерасхода памяти В том-то и дело. По моему, эта задачка не школьно-учебная, а скорее тестовая\конкурсная. Да, можно ее решить универсально с индексацией строк файла и его повторным рандомным чтением. Но тут можно нарваться на ужасные тормоза при рандомном чтении файла (а можно и не нарваться, если винда при наличии свободной физ. памяти закэширует весь файл при первом чтении). Хотя 700 Мб (не одним куском, а в виде отдельных строк), это действительно не много, поэтому эту задачку можно решить и с загрузкой всех строк в память, но не на основе стандартного TStringList, а на основе TList или дин.массива AnsiString с блочным чтением файла (хоть тем же Readln, хотя для увеличения скорости и "крутизны" я бы добавил к нему SetTextBuf размером в 8-16 кБ). |
Сообщ.
#21
,
|
|
|
Друзья, тут
https://stackoverflow.com/questions/2700790...arge-text-files предлагают использовать TStreamReader Я правильно понимаю что он считывает кусками, и ему не нужна память одним куском? Добавлено Т.е. можно просто в коде из первого поста поменять строку? на AssignFile(F,'C:\text.txt'); Reset(F); While not EOF(f) do Begin ReadLn(F,St); s.Add(St); End; CloseFile(F); ? |
Сообщ.
#22
,
|
|
|
Цитата ^D^ima @ предлагают использовать TStreamReader Я правильно понимаю что он считывает кусками, и ему не нужна память одним куском? Да. Судя по всему размер буфера по умолчанию составляет 4 Кб. PS: В принципе и у обычного TextFile есть буфер по умолчанию в 128 байт, который можно заменить на свой собственный любого размера через SetTextBuf. Цитата ^D^ima @ Т.е. можно просто в коде из первого поста поменять строку? Можно, но в современных юникодных дельфях это будет приводить к бестолковому увеличению занимаемой памяти в 2 раза (если исходный файл в ANSI). Хотя 700*2 Мб (в виде отдельных строк, а не одним непрерывным блоком) должны выделяться без особых проблем. Но все же правильнее\лучше не расходовать попусту память и реализовать свой список или массив AnsiString на основе TList или динамического массива. |
Сообщ.
#23
,
|
|
|
^D^ima
Цитата ^D^ima @ предлагают использовать TStreamReader Я правильно понимаю что он считывает кусками, и ему не нужна память одним куском? Когда последний раз его изучал это было не так. Может и допилили. leo Цитата leo @ к бестолковому увеличению занимаемой памяти в 2 раза (если исходный файл в ANSI). Пока современный дельфи моськой не ткнёшь он не конвертирует строки, а хранит в начале номер кодовой страницы. |
Сообщ.
#24
,
|
|
|
Цитата leo @ Да, можно ее решить универсально с индексацией строк файла и его повторным рандомным чтением. Но тут можно нарваться на ужасные тормоза при рандомном чтении файла (а можно и не нарваться, если винда при наличии свободной физ. памяти закэширует весь файл при первом чтении). Условия не озвучены, а значит, на тормоза пофиг... Цитата ^D^ima @ Я правильно понимаю что он считывает кусками, и ему не нужна память одним куском? Да. Именно для этого стримы и предназначены. Цитата Pavia @ Пока современный дельфи моськой не ткнёшь он не конвертирует строки, а хранит в начале номер кодовой страницы. Зависит от. Readln уже возвращает wide строку. Правда, возможно, есть и оверлоад вариант для ansi |
Сообщ.
#25
,
|
|
|
Цитата Pavia @ Пока современный дельфи моськой не ткнёшь он не конвертирует строки, а хранит в начале номер кодовой страницы. Pavia, при всем уважении - либо ты не ту траву куришь (не те доки или блоги читаешь), либо говоришь о каких-то супер-пупер "современных дельфи", которых еще ни у кого нет Вот пришлось проверить твои заявления на недавней халявной D 10.1 Берлин-Хеми: 1) если читаем Readln в AnsiString, то ес-но и получаем AnsiString в однобайтовой кодировке; 2) если читаем просто в String, то также ес-но получаем юникод-строку с двухбайтовой кодировкой; 3) если добавляем AnsiString в TStringList, то она автоматом преобразуется в юникод с двухбайтовой кодировкой. Ну и где тут "моська"? А-у-у? |
Сообщ.
#26
,
|
|
|
Цитата Fr0sT @ Условия не озвучены, а значит, на тормоза пофиг... Какой-то странный подход... Ну и "Какой ты, нафиг, танкист?!"(С), ведь "Таких не берут в космонавты!" (С) В догонку к вопросу by ^D^ima из #21 Цитата ^D^ima @ Т.е. можно просто в коде из первого поста поменять строку? По хорошему еще нужно: 1) Заменить тип St на AnsiString, а s с TStringList на дженерик TList<AnsiString> 2) Выделить буфер чтения Buf:array[0..4096*2-1] of byte и установить его через SetTextBuf сразу после Reset(F) 3) Я бы еще дополнительно задал TList.Capacity:=GetFileSize(TTextRec(F).Handle) div N, (где N = 8-16), чтобы не гонять попусту данные при последовательном наращивании длины массива указателей в TList. |
Сообщ.
#27
,
|
|
|
Цитата leo @ Какой-то странный подход... Ну и "Какой ты, нафиг, танкист?!"(С), ведь "Таких не берут в космонавты!" (С) А смысл пузыриться оптимизировать, если задание учебное и в требованиях ничего не прописано? |