Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  23:46[Войти] | [Зарегистрироваться]
Ответ на вопрос № 59475

Вопросы с аналогичными сообщениями об ошибках:
  • Stack overflow (27)

    15-02-2008 06:11
    Всем привет. Помогите разобраться в чом проблема.
    прочитал статью
    "Быстрая функция для замены строк"
    http://delphikingdom.com/asp/viewitem.asp?catalogid=1059

    функция


    function StrReplace(const Find, Replace, S: AnsiString;
                        const CaseSensitive: Boolean): AnsiString;



    попробовал на файле 40 000 байт.
    но на файле 9 000 000 байт быдает ошибку!!!

    raised exception class EStackOverflow with message  Stack Overflow. Process stoped. Use Step or Run to continue.

    Вообщем незнаю что делать помогите.



    procedure TForm1.Button2Click(Sender: TObject);
    var
      List:TStringList;
    begin
      List := TStringList.Create;
      List.LoadFromFile(strProgramDir + 'TestRepl.txt');
      List.Text := StrReplace(' THE ', ' eht ', List.Text, true);
      List.SaveToFile(strProgramDir + 'TestRepl.txt');
      List.Free;
    end;

    [+] Добавить в избранные вопросы

    Отслеживать ответы на этот вопрос по RSS

    Ответы:


    Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
    Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

    24-03-2008 03:38 | Комментарий к предыдущим ответам
    >>> По-видимому, здесь лучше использовать TFileStream c собственным буфером
    Угу. Можно так, можно BlockRead, если Pascal знаешь лучше Delphi. Именно на это я и намекал в ответе от 15-02-2008 07:20

    24-03-2008 03:26 | Комментарий к предыдущим ответам
    Доброго времени суток!

    To Geo

    По-видимому, здесь лучше использовать TFileStream c собственным буфером - быстродействие будет на уровне LoadFromFile, но переполнения не возникнет.

    С уважением,

    23-03-2008 16:15 | Комментарий к предыдущим ответам
    >>> Я бы все-равно в таком случае пользовался бы Readln - Writeln, это работает медленнее <...>
    Хм... Не просто медленнее, а существенно медленнее. Файд в 9 мегабайт -- это 131072 строки длиной 70 символов. Сейчас забабахал тестовую программу. TStringList, в который я в цикле загнал 131072 строки, а потом сбросил все это в файл, отработал быстрее, чен я успел заметить. А тестовая процедура, которая читала этот файл построчно и тут же каждую строку безо всякой обработки сбрасывала в другой текстовый файл, работала порядка секунды. Вот сижу и думаю, что будет если файл будет побольше или компьютер помедленнее.

    23-03-2008 15:28
    >>> нужно превратить в подобие CSV
    Я бы все-равно в таком случае пользовался бы Readln - Writeln, это работает медленнее, чем TStringList.LoadFromFile, но зато не грозит никаким переполнением при сколь угодно больших файлах в пределах 2 гигабайт (надеюсь, пока до такого не дошло :-))

    18-02-2008 08:54
    To  Banderas
    >>>Если нужно, могу порыться, поискать.

    Да интересно было бы взглянуть.
    Volniy.Strelok@gmail.com
    З.Ы.
    Если не сложно то с коментами. :)

    To Бел Амор

    Я думаю что читая из файла по одной строке это сужественно замедлит скорость замены.
    Тем более что в каждой строке файла вхождение для замены всего одно.
    А строк приблизительно 200 000.

    To Geo
    >>>Кстати, а что на что Вы меняете. Случайно не все пробелы на какие-нибудь подчерки?
    Файл правится для того чтобы потом залить его в таблицу базы данны т.е. его нужно превратить в подобие CSV файла

    16-02-2008 06:40
    Однажды мне пришлось адаптировать эту функцию под Unicode, заметил переполнения стека, харнящего позиции вхождения. Исправил проблему путем введения использования блоков динамической памяти перед тем исчерпается стек.

    Если нужно, могу порыться, поискать.

    15-02-2008 15:21 | Комментарий к предыдущим ответам
    Похоже, я угадал ;-)
    Да-да-да, я уже написал свои ответы, а потом увидел еще раз, что у вас, Geo, написано про это. Так что, читай и пиши я внимательнее, м.б. написал бы вместо: В стек там записываются все позиции вхождений искомой подстроки в текст. -
    В стек там записываются все позиции вхождений искомой подстроки в текст, как уже написал Geo.
    )))

    15-02-2008 14:52 | Комментарий к предыдущим ответам
    >>> Сейчас, прочитав это обсуждение, попробовал в том же файле заменить русское "о" на "а". "о" встречается 842 585 раз и я получил stack overflow.
    Похоже, я угадал ;-)

    *гордо бьет себя правой пяткой в левую грудь*

    15-02-2008 13:29 | Комментарий к предыдущим ответам
    P.S.Понятно, что какая-то часть стека занимается, когда внутри функции StrReplace вызываются другие функции (MovMem например), но поскольку рекурсии и многоуровневых вызовов нет, то это некритично, насколько я понимаю. Выполнилась внутренняя функция - стек снова освободился.

    15-02-2008 13:25 | Комментарий к предыдущим ответам
    Коллеги, в функции StrReplace рекурсии нет. В стек там записываются все позиции вхождений искомой подстроки в текст. По умолчанию максимальный размер стека в программе Дельфи - $100000=1048576. Позиция вхождения - целое число, т.е. занимает 4 байта. Соответственно, если число вхождений подстроки больше, чем 1048576/4=262144, то стек переполнится. В этом - ограничение функции.
    Я сегодня ответил автору вопроса на вопрос в комментариях к статье. Там он не написал, что ошибка - переполнение стека. Перед ответом я проверил функцию на большом файле. Взял стихотворения Пушкина (600 Кб, у меня лежит скачанный с библиотеки Машкова) и последователльным применением операции
    copy a.txt+b.txt c.txt создал файл размером 12.6 Мб.
    Я пробовал заменить тег параграфа (<p>). Он встречается в файле 79 655 раз и отлично заменился на что-то другое.
    Сейчас, прочитав это обсуждение, попробовал в том же файле заменить русское "о" на "а". "о" встречается 842 585 раз и я получил stack overflow. Потом увеличил в опциях проекта стек в 10 раз и всё быстро заменилось.

    Т.е., конечно, у этой функции есть ограничения.

    15-02-2008 10:00
    777:
    Стек переполняется из-за рекурсивных вызовов ф-й внутри StrReplace.
    Полностью согласен, что столь длинные строки - нонсенс.


    Заглянул мельком в указанную статью - StrReplace позиционируется именно как замена StringReplace для случая очень больших строк с очень частым вхождением заменяемого фрагмента. В этом случае использование рекурсии на кажное вхождение - ещё больший нонсенс, чем строки в 9 Мб... Код функции я не смотрел, так что могу в чём-то и ошибаться, но, думаю, не очень сильно...

    Geo:
    Повторяю цитату: "Заставь кое-кого молиться...". Далее по тексту.
    После совета в такой форме человек начнет строчки из файла по одной читать ;-)


    За него это уже делает TStringList...

    Geo:
    Читайте из файла все же блоками, но не такими большими. Особое внимание уделите тому, чтобы заменяемая строка не оказалась разорвана: часть в одном блоке, часть в другом. Иначе она не будет заменена.


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

    P.S. Обращаю особое внимание на то, что это должен быть именно чистый текст. Наличие в файле символов #0 в случае применения TStringList принесёт большие проблемы... Отсутствие символов #0 (и некоторых других) должно быть гарантировано. К сожалению, на практике не так уж редко встречаются случаи, когда вроде бы чистый текст (отчёт в виде текстового файла) таковым не является. Если есть хоть малейшая возможность появления в файле "ненормативных" символов, настоятельно советую отказаться от использования TStringList.LoadFromFile, тем более, что в вашем первоначальном варианте его использование ничем не оправдано.
    P.P.S. Думаю, наиболее безопасным вариантом будет читаль файл старым добрым ReadLn по одной строке, заменять всё, что надо, и записывать в другой файл старым добрым WriteLn. Им глубоко по барабану все спецсимволы, кроме #26 (конец текстового файла)...

    15-02-2008 08:23
    >>> А c помощью TStringList можно читать файл блоками
    Насколько я помню, нельзя. Все или ничего.

    15-02-2008 08:08 | Сообщение от автора вопроса
    А c помощью TStringList можно читать файл блоками а лючше всего например по 10 000 строк?

    15-02-2008 07:20
    >>> Так надо не сразу со всем файлом работать, а как минимум построчно.
    Повторяю цитату: "Заставь кое-кого молиться...". Далее по тексту.

    После совета в такой форме человек начнет строчки из файла по одной читать ;-)

    to Автор:
    Читайте из файла все же блоками, но не такими большими. Особое внимание уделите тому, чтобы заменяемая строка не оказалась разорвана: часть в одном блоке, часть в другом. Иначе она не будет заменена.

    Кстати, а что на что Вы меняете. Случайно не все пробелы на какие-нибудь подчерки? Потому что в упомянутой Вами функции, вроде бы, стек расходуется на сохранение позиций найденных вхождений. То есть, получается, что у Вас очень много вхождений искомого контекста. А даже для файла в 9 мегабайт обычное слово или фраза русского языка будут встречаться не так уж и много раз.

    15-02-2008 07:08
    но на файле 9 000 000 байт выдает ошибку!!!
    Заставь кое-кого молиться, так он и лоб себе расшибет.

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

    15-02-2008 07:01
    Стек переполняется из-за рекурсивных вызовов ф-й внутри StrReplace.

    Полностью согласен, что столь длинные строки - нонсенс.

    15-02-2008 06:44
    Тут дело не в конкретно StrReplace, а в размере стека программы, в котором вызываемые подпрограммы хранят свои внутренние переменные. Какой максимальный размер стека - можно почитать Help. Но вообще-то строка длиной в 9 миллионов символов - это нонсенс, на который явно не рассчитывали создатели функции. Придется либо резать строку, либо писать свою функцию без внутренних переменных размером с результат.

    15-02-2008 06:39
    Ну это уж самые крайние меры.
    Т.е по другому не как? И если вы знакомы с StrReplace то какой максимальный обьём части?

    15-02-2008 06:17
    Вообщем незнаю что делать помогите.
    Разбивайте текст на части и запускайте для каждой StrReplace.

    Добавьте свое cообщение

    Вашe имя:  [Войти]
    Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
    контрольный вопрос:
    Зимой — белый, летом — серый. Кто?
    в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
    Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
    Тип сообщения:
    Текст:
    Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Вопросы с аналогичными сообщениями об ошибках:
  • Stack overflow (27)


    Страница избранных вопросов Круглого стола.
  •   
    Время на сайте: GMT минус 5 часов

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

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования