Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Работа с большими текстовыми файлами


Автор: Stern87 17.2.2008, 02:30
Столкнулся с проблемой работы с большими файлами и перерыв DRKB и сей форум не смог найти именно то, что меня интересует. Поэтому и создал эту тему.

Есть программа, которая исполняя роль прокси-сервера, попутно индексирует адреса, и их HTTP-залоговки, которые запросил пользователь.
Для индексации программа использует текстовый файл и работает с ним посредством StringList. Сначала записывается адрес, далее - заголовки. Потом второй адрес и его заголовки и т.д. Как вы уже поняли, такой список сортировать нельзя.
Когда пользователь заново запрашивает адрес, который уже "проиндексирован", программа должна определить номер строки необходимого адреса в индекс-файле и выдать следующие строки (это как бы заголовки) до тех пор, когда первые символы следующей выдаваемой строки будут "http://", к примеру.
Поначалу поиск необходимого адреса я делал с помощью функции IndexOf, но когда размер индекс-файла переваливает за 20Мб уже создаются сложности в виду медлительности. Частично "порог" удалось отодвинуть заменив эту функцию на Pos(CRLF+link+CRLF, indx.Text) (CRLF =  #$0D+#$0A;).
Но уже на 30Мб всё уже возвращается на свои места.

Вопрос: существует хоть какой-то вид альтернативы StringList'у? Необходимо записывать данные в конец, но при этом иметь возможность читать файл с начала, чтобы искать необходимые строки (адреса ссылок) и читать строки далее (получать заголовки) (ReadLn???)

Спасибо за понимание.

Автор: VICTAR 17.2.2008, 04:18
Может стоит посмотреть в сторону базы данных?

Автор: Stern87 17.2.2008, 10:59
Нет. Условие - работа с текстовыми файлами, простота доступа пользователя к этому файлу.
В конце-концов это как суточный лог-файл - сутки закончатся и будет новый индекс-файл.
Зачем же это всё впихать в одну базу?
Необходимо, чтобы это был именно файл, а не БД.
Помогите.

Автор: VICTAR 17.2.2008, 15:14
Цитата(Stern87 @  17.2.2008,  10:59 Найти цитируемый пост)
Зачем же это всё впихать в одну базу?

Есть "легкие" базы данных, например VolgaDB. Высокая скорость работы, вся база в одном файле и т.д. 
Если не устраивает, попробуй FileMapping.

Автор: Esperito 17.2.2008, 17:30
Как насчёт TFileStream?

Автор: Akella 17.2.2008, 19:59
а списки... TList

Автор: Poseidon 18.2.2008, 10:39
Цитата(Stern87 @  17.2.2008,  10:59 Найти цитируемый пост)
Условие - работа с текстовыми файлами, простота доступа пользователя к этому файлу.В конце-концов это как суточный лог-файл - сутки закончатся и будет новый индекс-файл.
Что мешает работать с базой данных, а когда нужен лог - один раз его создавать из базы и давать пользователю (или что там надо?). А саму непосредственную работу проводить с базой.

Автор: Alexeis 18.2.2008, 10:57
Цитата(ms-help://borland.bds5/delphivclwin32/IniFiles_THashedStringList.html)

THashedStringList is a string list that uses a hash table internally to speed the process of locating strings. It is used internally by TMemIniFile to manage the strings from an INI file, but can be used in the same way as any other string list. By using THashedStringList instead of TStringList, you can improve performance when the list contains a large number of strings. 

Автор: Stern87 18.2.2008, 11:01
Ага, я понял, щас объясню.
Обычно файлы индексации весят от 200Мб, поэтому использовать TList, на мой взгляд, не уместно, т.к. файл будет грузиться в оперативную память, а она не резиновая.
TFileStream не позволяет работать с файлом как с набором строк (как это делает TextFile) произвольной длины.
Но TextFile, в свою очередь не может решить вопрос о работе с файлом как для записи строк (в конец) так и чтения всех строк (от 0 - необ. задачи).
THashedStringList такой же тупой как и TStringList - он помещает мой 340Мб файл в ОЗУ, а что другим программам оставить???
К тому же это не лог-файл. Он должен так выглядеть (как лог-файл).
Условие осталось прежним: это должен быть текстовый файл, и ни какая БД.

Автор: Alexeis 18.2.2008, 11:47
  Поскольку строки не меняются и не удаляются, то для их хранения можно использовать файл подкачки или просто файл отображаемый в память. Вместо AnsiString юзать PChar. Каждый раз когда нужно будет выделить новый кусок мы просто присваиваем текущий указатель и затем смещаем его на длину строки. Тогда строки будут подгружаться в память по мере обращения, но работа замедлится по сравнению если бы они были в оперативке. Освобождаем удалением файла. Не будет 2х копий. 
  Stern87, в любом случае дешевле купить 2 гига оперативки чем платить тебе зарплату, за то что ты будешь месяц прогу писать smile . 

Автор: Stern87 18.2.2008, 12:20
Причём здесь моя зарплата и работа как таковая??
Это - прихоть.
А если индекс-файл может быть больше 2Гб - еще оперативы докупать?
Можно получить такой же "инструмент" как TStringList (в частности: добавление в конец и обращение к конкретной строке) только такой, который бы НЕ загружал этот текстовый файл в ОЗУ? (Это, можно сказать, тот самый вопрос из первого поста)

Автор: Poseidon 18.2.2008, 12:32
Цитата(Stern87 @  18.2.2008,  11:01 Найти цитируемый пост)
Условие осталось прежним: это должен быть текстовый файл, и ни какая БД.

Можно увидеть обоснование этого? Почему именно так и не иначе? Или дело просто в: 
Цитата(Stern87 @  18.2.2008,  12:20 Найти цитируемый пост)
Это - прихоть


Автор: Alexeis 18.2.2008, 12:43
Цитата(Stern87 @  18.2.2008,  11:20 Найти цитируемый пост)
А если индекс-файл может быть больше 2Гб - еще оперативы докупать?
Можно получить такой же "инструмент" как TStringList (в частности: добавление в конец и обращение к конкретной строке) только такой, который бы НЕ загружал этот текстовый файл в ОЗУ? 

  Так я ж описал механизм. Скопируй сорс TStringList и переопредели выделение памяти строк инициализацию и т.д. короче все что понадобиться. Но память выделяй сам используя файл отображаемый в память.

Автор: Данкинг 18.2.2008, 12:45
Я бы базу в Access хотя бы создал и с ней работал. Вот и альтернатива. 

Автор: Alexeis 18.2.2008, 12:45
Цитата(Stern87 @  18.2.2008,  11:20 Найти цитируемый пост)
Причём здесь моя зарплата и работа как таковая??

  Дело в цене, если игра не стоит свеч, то зачем мучаться? Да и как за день может набраться лог на 2 Гига? Поиск в ОЗУ будет самым быстрым. Если грузить с харда, то все намного замедлиться.

Автор: greenpc 18.2.2008, 13:45
Stern87, 
а если попробовать так:
пришем в файл фиксированную длину строки, заведомо большую чем самая длинная
далее через seek бегаем по файлу

Автор: Poseidon 18.2.2008, 14:04
Цитата(greenpc @  18.2.2008,  13:45 Найти цитируемый пост)
далее через seek бегаем по файлу
Задолбешься бегать по тридцатимегабайтному текстовому файлу...

Автор: Stern87 18.2.2008, 15:45
Цитата(Poseidon @  18.2.2008,  11:32 Найти цитируемый пост)
Можно увидеть обоснование этого?
Сокращенно "прихоть" не получилось smile
Можно. Программа уже n-й версии. И "структура" этих индекс-файлов не меняется уже очень долго. Люди пользуются разными версиями этой программы и они могут обменивать этими файлами, объединять их, или просто править в обыкновенном блокноте. Очень желательно, чтобы "структура" осталась такой же открытой и доступной.

Цитата(Alexeis @  18.2.2008,  11:43 Найти цитируемый пост)
Так я ж описал механизм. Скопируй сорс TStringList и переопредели выделение памяти строк инициализацию и т.д. короче все что понадобиться. Но память выделяй сам используя файл отображаемый в память. 
Звучит неплохо. Вот я и спросил: если ли уже что-то готовое, потому что найти неполучается((( ??

Цитата(Данкинг @  18.2.2008,  11:45 Найти цитируемый пост)
Я бы базу в Access хотя бы создал и с ней работал. Вот и альтернатива. 
Но это делает программу зависимой от Microsoft Office. А если программа работает на простеньком сервере в маленькой локальной сети? Ради её еще и Office ставить? Нет, спасибо за предложение, но альтернатива плохая.

Цитата(greenpc @  18.2.2008,  12:45 Найти цитируемый пост)
а если попробовать так:
пришем в файл фиксированную длину строки, заведомо большую чем самая длинная
далее через seek бегаем по файлу 
А как узнать какая может попаться самый большой HTTP-адрес? В принципе, по RTF это 4096 (поправьте, если я не прав). Но а как же тогда будут сохраняться POST или куки всякие??


Можно даже упростить главный вопрос сформулировав так: что вы будете предпринимать, если окажется, что некогда ваш механизм оперирования с текстовым файлом (посредством TStringList) будет слишком медлительным и использовать слишком много ОЗУ (увеличить которое сможет далеко не каждый ваш потенциальный пользователь), и изменить структуру того текстового файла вы не можете?

Автор: VICTAR 18.2.2008, 15:52
Stern87, ты хочешь и рыбку съесть и вырезано цензурой.
Выиграешь в скорости - потеряешь в памяти и наоборот.

Автор: Stern87 18.2.2008, 17:05
Цитата(VICTAR @  18.2.2008,  14:52 Найти цитируемый пост)
Stern87, ты хочешь и рыбку съесть и вырезано цензурой.
Выиграешь в скорости - потеряешь в памяти и наоборот. 
Да я уже скорость и не прошу. Мне просто нужно, чтобы ОЗУ не так кушало, а удобство было такое же как и работа с TStringList. Или, еще проще, навигация по строкам и добавление строки в конец. Вот и всё! Не так уж и много надо.

Автор: lukas 18.2.2008, 17:35
вместо tstringlist использовать массив строк, если сравнить: поиск по массиву будет происходить раз в 5-10 быстрее чем по tstringlist, т.к. если нужно быстрота, то объекты в твоем случае лучше отбросить, только лишь на вызов TStringList.Items[i] тратиться в 10 раз больше времени чем на тот же массив arr[i]... Так что загоняй строки в массив, и работай с ним ... естественно используй динамические массивы...

Автор: VICTAR 18.2.2008, 17:43
Цитата(Stern87 @  18.2.2008,  17:05 Найти цитируемый пост)
удобство было такое же как и работа с TStringList

Объясни в чем заключается удобство. Проще будет думать.

Добавлено через 10 минут и 46 секунд
Цитата(Stern87 @  18.2.2008,  11:01 Найти цитируемый пост)
Но TextFile, в свою очередь не может решить вопрос о работе с файлом как для записи строк (в конец)

Append? 

Цитата(Stern87 @  18.2.2008,  11:01 Найти цитируемый пост)
так и чтения всех строк

А вот это я не понял

Автор: Stern87 18.2.2008, 18:47
Цитата(VICTAR @  18.2.2008,  16:43 Найти цитируемый пост)
Объясни в чем заключается удобство. Проще будет думать.
Писал уже - можно легко добавить строку в конец, а также, можно обратиться к любой строчке.

Цитата(VICTAR @  18.2.2008,  16:43 Найти цитируемый пост)
Append
Он открывает текстовый файл для записи строк в конец. Читать им строки открытого файла, кажется, нельзя.

Автор: VICTAR 18.2.2008, 18:57
Цитата(Stern87 @  18.2.2008,  18:47 Найти цитируемый пост)
Он открывает текстовый файл для записи строк в конец.

Да, но что мешает Reset - прочитать - закрыть, Append - записать - закрыть. 
Или я что-то не понимаю?

Автор: Akella 18.2.2008, 18:59
Цитата(Stern87 @  18.2.2008,  11:01 Найти цитируемый пост)
Обычно файлы индексации весят от 200Мб, п

грузить 200 метров текста в память??? я бы тоже БД использовал

Добавлено через 7 минут и 49 секунд
Цитата(Данкинг @  18.2.2008,  12:45 Найти цитируемый пост)
Я бы базу в Access хотя бы создал и с ней работал. Вот и альтернатива.  

акцесс тормознутый

Добавлено через 9 минут и 46 секунд
Цитата(Stern87 @  18.2.2008,  15:45 Найти цитируемый пост)
Но это делает программу зависимой от Microsoft Office. А если программа работает на простеньком сервере в маленькой локальной сети? Ради её еще и Office ставить? Нет, спасибо за предложение, но альтернатива плохая.

firebird

Автор: aktuba 18.2.2008, 21:09
При таких жестких условиях я бы FileStream использовал. При более мягких:
Цитата(Akella @  18.2.2008,  19:59 Найти цитируемый пост)
firebird 


Автор: Akella 18.2.2008, 21:11
так если использовать файлстрим, то нужно весь файл грузить в память?
а как искать инфу в тексте, если текст не загрузить в память? по одной строчке? типа загрузил одну, проверил, не то, выгрузил и т.д.

Автор: aktuba 19.2.2008, 01:02
Цитата(Akella @  18.2.2008,  22:11 Найти цитируемый пост)
так если использовать файлстрим, то нужно весь файл грузить в память?
а как искать инфу в тексте, если текст не загрузить в память? по одной строчке? типа загрузил одну, проверил, не то, выгрузил и т.д. 

Скорее не целиком, а блоками...

Автор: mutex 19.2.2008, 03:41
Stern87
Запись текстового файла (то бишь Ваша строка) состоит из двух частей: ключ поиска - это URL-адрес поста, информация записи - текст поста юзера. Длина ключа поиска и длина информационной части записи являются переменными. Правильно понимаю условие задачи?

Мне кажется, что GreenPC предлагает хорошую идею: использовать Seek.

Только надо немного дополнить:
- надо преобразовать ключ поиска в 16-ный хэш, н-р, использовать SHA-1, который выдает 20 байтный хэш;
- в памяти хранить этот хэш и Integer-смещение записи от начала текстового файла; 
- итого: длина элемента динамического массива равна 24 байтам.

Тогда требование к памяти должно снизиться и Вы можете делать поиск хэша для ключа, введенного  юзером. 

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


Автор: aktuba 19.2.2008, 06:08
mutex, 
Цитата(Stern87 @  18.2.2008,  16:45 Найти цитируемый пост)
Программа уже n-й версии. И "структура" этих индекс-файлов не меняется уже очень долго. Люди пользуются разными версиями этой программы и они могут обменивать этими файлами, объединять их, или просто править в обыкновенном блокноте. Очень желательно, чтобы "структура" осталась такой же открытой и доступной.


Автор: greenpc 19.2.2008, 08:43
mutex, 
немного расширю твою идею
держать один файл с логом
и еще один файл индексов. например с номером строки в логе и темже хешем сторки
соответствено сразу можно после открытия файла лога перейти на нужную строку

Poseidon, зато не кушаю память smile,
на текущий момент средняя скорость чтения с винта 20-30 мб/с
а если файл еще записан одним куском (не дефрагментирован) то скорости должно хватить

ЗЫ: например Kerio держит в файле индексов абсолютное смещение от начала файла, соответственно нет фиксированной длины строки.
делаем seek & readln. кстати для лога 30мб файл индесков всего 800к

Автор: Stern87 19.2.2008, 11:42
Ребята!
Да не лог это. Это своеобразный индекс-файл: строка HTTP-адреса (текст, рисунок - всё что только может запросить браузер), а следующие строки - HTTP-заголовки этого адреса; потом опять строка HTTP-адреса, заголовки и так по кругу. Он может и выглядит из-за этого как лог, но им он не является.
Еще заметил, что когда я вызываю
Код

strno := Pos(link, indx.Text);
где indx - TStringList, то функция Pos зажирает примерно столько, сколько весит индекс файл. И не освободит память до тех пор, пока программа не выйдет из функции в которой и была вызвана эта Pos!!
Определил это на глаз с помощью sleep(7000).
Может я чего-то не понимаю? Почему Pos не освободил память, которую он для себя занял?

Автор: Rennigth 19.2.2008, 13:27
Цитата(Stern87 @  19.2.2008,  11:42 Найти цитируемый пост)
Почему Pos не освободил память, которую он для себя занял? 

Все он освободил, просто системе значит эта память пока не нужна. Как понадобиться она ее заберет.

Автор: ASGDeveloper 19.2.2008, 13:56
Мдя... smile

1) Качаешь этот архив: http://www.torry.net/vcl/internet/html/Alcinoe_cmp_3_52_15.zip
2) Находишь там юнит alFcnString
3) Используешь в своей программе аналоги функций, Pos -> ALPos, таким образом увеличишь скорость работы и не придется бороться с форматом
4) Внимательно посмотри состав архива, может еще что-нить интересное для себя найдешь.

5) Дополнительно, для освобождения памяти попробуй почаще вызывать такую функцию:
Код

procedure TrimWorkingSet;
var
  MainHandle: THandle;
begin
  if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID);
    SetProcessWorkingSetSize(MainHandle, DWORD(-1), DWORD(-1));
    CloseHandle(MainHandle);
  end;
end;


ЗЫ Я конечно бы рекомендовал использовать базу данных. Ну раз хочется - то попробуй мой совет. В противном случае тебе здесь никто больше помочь ничем не сможет. smile

Автор: Poseidon 19.2.2008, 15:29
Цитата(Stern87 @  19.2.2008,  11:42 Найти цитируемый пост)
Да не лог это. Это своеобразный индекс-файл: строка HTTP-адреса (текст, рисунок - всё что только может запросить браузер), а следующие строки - HTTP-заголовки этого адреса; потом опять строка HTTP-адреса, заголовки и так по кругу. Он может и выглядит из-за этого как лог, но им он не является.
Тогда объясни нам зачем эти данные пользователям? Зачем они ими обмениваются?

Автор: Stern87 19.2.2008, 20:31
Каждый их использует по-своему.

Автор: lukas 19.2.2008, 21:16
возьми модуль QStrings, работа со строками, для сравнения я проверял аналогичная функция Q_PosStr работает ровно в 4 раза быстрее чем стандартная функция Pos, что уж говорить о других аналогичных функциях в этом модуле... Из всего что я перепробовал, этот модуль самый быстрый при работе со строками (например тот же AcedUtils и FastStrings работает медленнее QStrings), а вообще еще раз повторюсь, используй массив вместо tstringlist, по крайней мере поиск будет в раз десять быстрее....

Автор: Stern87 19.2.2008, 21:51
Цитата(ASGDeveloper @  19.2.2008,  12:56 Найти цитируемый пост)
3) Используешь в своей программе аналоги функций, Pos -> ALPos, таким образом увеличишь скорость работы и не придется бороться с форматом

Код
var ALPos: function(const SubStr: AnsiString; const Str: AnsiString): Integer;
{from FastCode John O'Harrow (john@elmcrest.demon.co.uk)
 original name: CharPosJOH_IA32, CharPosJOH_MMX, CharPosJOH_SSE, CharPosJOH_SSE2}

Я и так использую модуль FastCode (а также FastMove) в своих компонентах.

Автор: ASGDeveloper 20.2.2008, 00:30
Цитата(Stern87 @  19.2.2008,  21:51 Найти цитируемый пост)
Я и так использую модуль FastCode

И там есть такая функция? 

Автор: Stern87 20.2.2008, 00:45
Цитата(ASGDeveloper @  19.2.2008,  23:30 Найти цитируемый пост)
И там есть такая функция?

Цитата
from FastCode John O'Harrow (john@elmcrest.demon.co.uk)
 original name: CharPosJOH_IA32, CharPosJOH_MMX, CharPosJOH_SSE, CharPosJOH_SSE2

Автор: WaReZMEN 20.2.2008, 01:41
а де  QString   скачать? Нашел правда последнее изменение в 2000 году были может и не то... Но я провел эксперемен взял текстовый файл размером 50000 строк (2.6 мб) 
Делал я слудующие искал в каждои строке символ "=" и все что боло до него писал в БД.
Попробовал 3 способа:

1. Символ искал с помощью Copy если не "=" то прибовлял к строке текущий символ (тоесть проверял каждый символ пока не встречал "=") затрачено времяни 1 минута 27 секунд.

2. Символ искал с помощью Pos затем результат делал с помощью Copy () затрачено времяни 1 минута 32 секунд.

3. Символ искал с помощью Q_PosStr затем результат делал с помощью Q_Copyleft () затрачено времяни 1 минута 48 секунд.
Отсюда вывод что QString нехрена не быстрее... Либо я что то не так делаю...

Автор: ASGDeveloper 20.2.2008, 09:33
Цитата(WaReZMEN @  20.2.2008,  01:41 Найти цитируемый пост)
Попробовал 3 способа:

А где пункт 4 с ALPos?

Автор: WaReZMEN 20.2.2008, 09:58
ASGDeveloper, а это где взять?

Автор: Stern87 20.2.2008, 11:39
WaReZMEN, внимательно перечитай ветку. или хотя бы последние 15 постов.
QStrings можешь скачать на http://www.torry.net - просто введи в поиск "QStrings" и всё.

P.S. Q_PosStr хрена и быстрее. просто ты что-то не так делаешь.

Автор: lukas 20.2.2008, 17:20
WaReZMEN, 

Где нибудь вставь эти 2 процедуры, и сравни что быстрее.... как говориться всю работу со строками я испытал на своей крове, и ни один из FastStrings, AcedUtils не дает больше скорости чем QString, просто нужно смотреть, какие функции там работают быстрее чем обычно, например замена Delete (Q_Delete), тоже работает там намного быстрее чем обычно...

Код

uses QStrings
...

// Стандартная библиотека....
procedure PosEV;
   Var
   I,T: Integer;
begin
T := GetTickCount;
 for i:=0 to 99999999 do 
   Pos('ABC-','CDKJHABC-DKJ');
ShowMessage(IntToStr(GetTickCount-T));
end;

// QString....
procedure QPosEV;
   Var
   I,T: Integer;
begin
T := GetTickCount;
 for i:=0 to 99999999 do 
   Q_PosStr('ABC-','CDKJHABC-DKJ'); 
ShowMessage(IntToStr(GetTickCount-T));
end;


Автор: WaReZMEN 21.2.2008, 01:53
Ну так я ж писал что может у меня либа не та я скачал щас с TORRY.net  посмотрел эта деиствительно работает быстрее...

Автор: WaReZMEN 21.2.2008, 07:23
Вот вы лучше раскажите как в lingvo так быстро слова фильтруются??? там же дофига слов... я вот базу сделал из 300000 слов так задержка заметная (около 1-2 сек). (База на Файрберде) 

Автор: Poseidon 21.2.2008, 10:21
Цитата(WaReZMEN @  21.2.2008,  07:23 Найти цитируемый пост)
Вот вы лучше раскажите как в lingvo так быстро слова фильтруются??? там же дофига слов... я вот базу сделал из 300000 слов так задержка заметная (около 1-2 сек). (База на Файрберде) 
Это смотря как ты фильтруешь. Запросом все делается быстро. А вообще тут это оффтоп.

Автор: Stern87 21.2.2008, 17:17
Я предлагаю конкретизировать вопрос еще сильнее, чтобы не было вариантов типа БД и т.д.

Задача:
Есть огромный текстовый файл (он уже существует) размером 400Мб.
Есть чёткий запрет "Не загружать весь файл в ОЗУ", по объективным причинам (не все же могут позволить себе закупаться памятью).
Вы должны уметь записывать новые строки в конец этого файла, а также уметь читать все строки от самой первой, до последней.

Какие есть предложения?
Если есть возможность показывайте и код.
К примеру, если вы предлагаете использовать TFileStream - покажите код, который бы показывал как бы вы реализовывали эти "умения".
Спасибо!!

Автор: Poseidon 21.2.2008, 17:31
Stern87, как же ты не поймешь...

Что бы реализовать это 
Цитата(Stern87 @  21.2.2008,  17:17 Найти цитируемый пост)
уметь записывать новые строки в конец этого файла
 и это 
Цитата(Stern87 @  21.2.2008,  17:17 Найти цитируемый пост)
 уметь читать все строки от самой первой, до последней
 в принципе нужно загрузить фесь файл в память. Есле еще второй можно как-то обскакать, загружая построчно или по блокам, то что бы записать что-то в конец, нужно этот конец найти. А что бы найти конец файла, нужно загрузить в память весь файл.

А вообще, я считаю, что "текстовый файл размером 400Мб" - это немецкое порно-извращение. Не всегда такую БД увидешь. Ни о какой производительности с такими обьемами и в текстовом формате речь идти не может. Выход у тебя один - переделывать архитектуру программы в сторонну БД. В БД можно запросом выбрать что тебе надо, не загружая все в память. А так же запросом добавлять новые записи, вообще не трогая старые. Так что подумай.

Автор: greenpc 22.2.2008, 09:23
Poseidon, 
Цитата

что бы записать что-то в конец, нужно этот конец найти
 а что его искать smile - размер файла
Цитата

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

кто Вам такое сказал ?
Stern87, 
Цитата

Есть огромный текстовый файл (он уже существует) размером 400Мб.
 создавать файл индексов, но это уже почти переход на БД
Код

var
  TmpStr: string;
    fOut : TStream;
begin
   fOut := TFileStream.Create('c:\1.22', fmOpenReadWrite);
   TmpStr :='Test';
   fOut.Position := fOut.Size; // Куда ставим указатель
   fOut.WriteBuffer(TmpStr[1], Length(TmpStr));
   FreeAndNil(fOut);
end;


Poseidon, 
Цитата

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

Автор: Alexeis 22.2.2008, 10:16
Цитата(Poseidon @ 21.2.2008,  16:31)
Stern87, как же ты не поймешь...

Что бы реализовать это 
Цитата(Stern87 @  21.2.2008,  17:17 Найти цитируемый пост)
уметь записывать новые строки в конец этого файла
 и это 
Цитата(Stern87 @  21.2.2008,  17:17 Найти цитируемый пост)
 уметь читать все строки от самой первой, до последней
 в принципе нужно загрузить фесь файл в память. Есле еще второй можно как-то обскакать, загружая построчно или по блокам, то что бы записать что-то в конец, нужно этот конец найти. А что бы найти конец файла, нужно загрузить в память весь файл.

  Несогласен. Чтобы дописать конец файла ничего не нужно грузить в память, а чтобы иметь произвольный доступ к строкам, совсем не обязательно читать весь файл. Я вот писал специальный модуль для работы с большими XML файлами, парсинг проводиться в 2 этапа. На 1 м этапе произодиться предварительный парсинг, цель которого разобрать общую структуру и создать дерево индексов. Запоминается номер 1го и последнего символа в строке и такая запись сохраняется. Теперь для получения произвольного доступа к записи, сначала идет обращение к этому индексу, потом из файла читается фрагмент начиная с 1го символа и длиной (последний - первый + 1). Но тут я его привести не могу, так как он узкоспециализированный и написан на С++  smile 

Автор: Poseidon 22.2.2008, 11:31
Цитата(Alexeis @  22.2.2008,  10:16 Найти цитируемый пост)
Я вот писал специальный модуль для работы с большими XML файлами
Все это хорошо, но я не думаю что те XML были в 400МБ. Вы только вдумайтесь в это: 400МБ текста... Я вообще не представляю как с таким работать. Его хоть блокнот открывает?

Автор: Akella 22.2.2008, 12:23
блокнот такой файл не откроет, он с трудом открывает файлы размеров в несколько мегабайт

Автор: Alexeis 22.2.2008, 12:46
Цитата(Poseidon @  22.2.2008,  10:31 Найти цитируемый пост)
Я вообще не представляю как с таким работать. Его хоть блокнот открывает?

  Все зависит от того как работать. Если использовать файлы отображаемые в память вместо файловых потоков и поиск с конца (чтобы искать сначала последних записях), то мож и будет работать. А если говорить вообще о полном проходе по такому файлу с целью поиска строки в нем, то конечно ничего хорошего за адекватное время не выйдет smile .

Автор: Poseidon 22.2.2008, 14:31
Цитата(Alexeis @  22.2.2008,  12:46 Найти цитируемый пост)
Все зависит от того как работать.
 Я имел ввиду вот это:
Цитата(Stern87 @  18.2.2008,  15:45 Найти цитируемый пост)
Люди пользуются разными версиями этой программы и они могут обменивать этими файлами, объединять их, или просто править в обыкновенном блокноте.


Автор: mutex 22.2.2008, 15:05
Цитата(Alexeis @ 22.2.2008,  13:16)

... На 1 м этапе произодиться предварительный парсинг, цель которого разобрать общую структуру и создать дерево индексов. Запоминается номер 1го и последнего символа в строке и такая запись сохраняется. Теперь для получения произвольного доступа к записи, сначала идет обращение к этому индексу, потом из файла читается фрагмент начиная с 1го символа и длиной (последний - первый + 1)...  

Замечательная идея. При 400-ти мегах может выручить только индекс-технология баз данных. Как говорит автор - Stern87, файл - суточный, временный и не редактируемый, кроме дозаписи в его конец. Значит такой парсинг надо делать на лету, при созданий строк файла, начиная с ноля часов. Если уж надо минимизировать память, эту структуру надо сбрасывать в отдельный файл, который и будет индексом текстовой БД.

Stern87, на Вашем месте, я бы  выставил кусок файла и привел пример ключа поиска и ответа на поиск. Кстати, как это за 24 часа удается набрать такой объем данных? Что за болтливый сайт, если не секрет? smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)