Плоский файл в делфи

В моем приложении я хочу использовать файлы для хранения данных. Я не хочу использовать базу данных или открытый текстовый файл, цель состоит в том, чтобы сохранить двойные и целочисленные значения вместе со строкой только для определения имени записи; Мне просто нужно сохранить данные на диск для создания отчетов. Файл может вырасти даже до гигабайта. Какой формат вы предлагаете использовать? Двоичный? Если да, то какой компонент / библиотеку vcl вы знаете, что хорошо использовать? Моя цель - создать приложение, которое создает и обновляет файлы, в то время как другой инструмент будет "съедать" эти файлы, создавая хорошие отчеты в формате PDF для пользователя по запросу. Что вы думаете? Любая идея или предложение?

Заранее спасибо.


person marcostT    schedule 28.04.2011    source источник
comment
Звучит как отличная возможность разработать собственный формат двоичных файлов, используя только стандартный ввод-вывод Pascal. Но я не осмеливаюсь публиковать такие возмутительные идеи в качестве ответа...   -  person Andreas Rejbrand    schedule 28.04.2011
comment
pascal io имеет ограниченный размер файла   -  person David Heffernan    schedule 28.04.2011
comment
Индексация будет рассмотрена. Вам не захочется выполнять поиск методом грубой силы каждый раз. Если вы это сделаете, вы будете в среднем 500 МБ на операцию чтения! Если ваши данные расположены в алфавитном порядке, вы, вероятно, могли бы использовать двоичный поиск, чтобы найти их быстрее. Но если они разбросаны в случайном порядке, например, если вы просто добавляете данные в конец журнала, вам нужен способ узнать, с чего начать поиск.   -  person Chris Thornton    schedule 28.04.2011
comment
Я читал это: powerbasic.com/support/help/pbcc/random_access_files.htm, я думаю, файл с произвольным доступом.   -  person marcostT    schedule 28.04.2011
comment
Дэвид: только типизированный файл ограничен, афаик.   -  person Marco van de Voort    schedule 28.04.2011
comment
Обратите внимание, что функции Pascal IO (AssignFile, Append, Rewrite, Read(Ln), Write(Ln) и т. д.) НЕ поддерживают Unicode. В любой версии Delphi, Unicode или нет.   -  person Marjan Venema    schedule 28.04.2011
comment
О типизированном файле паскаля: его больше не следует использовать ни в одном серьезном проекте, а записи фиксированного размера не являются хорошим решением для производительности (вы должны поддерживать свои индексы вручную) или хранилища размера (если вы хотите хранить какой-то текст внутри - это будет короткая строка, поэтому никогда не используйте Unicode).   -  person Arnaud Bouchez    schedule 29.04.2011
comment
Пользователь ранее упоминал файлы с произвольным доступом, как в PowerBasic, но, похоже, удалил это из вопроса.   -  person Warren P    schedule 29.04.2011


Ответы (5)


Если вы не хотите изобретать велосипед, вы можете найти все необходимые Open Source инструменты для вашей задачи у нас:

  • Synopse Big Table для хранения огромного количества данных — см. в частности, класс TSynBigTableRecord для хранения неограниченного количества записей с полями, включая индексы, если это необходимо - он определенно будет быстрее и будет использовать меньший размер диска, чем любая другая обычная база данных SQL.
  • Synopse SQLite3 Framework, если вы предпочитаете использовать стандартный механизм SQLite. для хранилища - поставляется с полным ORM клиент/сервер
  • Отчетность из кода, включая файл PDF поколение

С полным исходным кодом, работающим от Delphi 6 до XE.

Я только что обновил документацию фреймворка. Более 600 страниц с подробным описанием каждого метода класса и новым расширенным общим введением. См. документ SAD.

Обновление. Если вы планируете использовать SQLite, вам следует сначала угадать, как будут храниться данные, какие индексы должны быть созданы и как SQL-запрос может ускорить ваши запросы. Плохая идея читать все содержимое файла для каждого запроса: вам следует лучше структурировать свои данные, чтобы один SQL-запрос мог вернуть затраченные результаты. Иногда хорошей идеей является использование дополнительных значений (например, временных сумм или средних значений) к данным. Также рассмотрите возможность использования виртуальной таблицы RTree SQLite3, предназначенной для ускорения доступ к double мин./макс. многомерным данным: это может намного ускорить ваши запросы.

person Arnaud Bouchez    schedule 29.04.2011
comment
О SQLite Привет. Хорошо, я просмотрел документацию по SQLite и у меня возник вопрос. Я планирую иметь как минимум два процесса для чтения базы данных и только один для записи. 1. Вы предлагаете доверять блокировкам SQLite или мне следует реализовать свой собственный мьютекс? 2. Я использую delphi 2009. Как насчет AnyDAC для SQLite? Есть смысл его использовать. Думаю не обязательно. Никто не пользовался? 3. Платформа SQLite3 и SQLite. Кто-то еще может их сравнить? Использовали SQLite3 Framework раньше? - person marcostT; 29.04.2011
comment
@marcosT 1. SQLite действительно ACID и заблокирует файл, как и ожидалось - вы можете быть уверены в этом 2. AnyDAC хорош, но гораздо больше, чем оболочка SQLite 3. Платформа SQLite3 представляет собой ORM, основанную на SQLite, но у вас есть оболочка для прямого доступа к движку SQlite без ORM - он также добавляет архитектуру клиент-сервер на основе JSON в SQLite - person Arnaud Bouchez; 29.04.2011

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

Пункты между ними включают:

  1. Что-то, что не является полной базой данных SQL, а больше похоже на хранилище ключей и значений, технически не будет плоским файлом, но оно предоставляет единый список «ключ + значение», который можно быстро найти по одному первичному ключу. Например, БСДБ. В названии есть буквы Д и Б. По вашему мнению, это делает его базой данных? Потому что это не реляционная база данных и не работает с SQL. Это всего лишь двоичный механизм хранения BLOB-объектов типа "ключ-значение" (хэш-таблица), использующий хорошо понятный формат двоичных файлов. Лично я бы не стал начинать новый проект и использовать что-либо из этой категории.

  2. Рекомендуется: что-то, что использует SQL, но не такое большое, как автономные серверы баз данных SQL. Например, вы можете использовать SQLite и оболочку Delphi. Он хорошо протестирован и используется во многих приложениях C/C++ и Delphi, и ему можно доверять больше, чем всему, что вы могли бы создать самостоятельно. Это очень легкая встроенная база данных, и многие ей доверяют.

  3. Создайте свой собственный ISAM или VLIR, который со временем превратится в вашу собственную СУБД. Здесь задействовано несколько файлов и есть индексы, поэтому вы можете быстро искать данные, не загружая все в память. Не рекомендуется.

  4. Самый плоский из плоских двоичных файлов с фиксированной длиной записи. Первоначально вы упомянули в своем вопросе, power basic, в котором есть что-то, называемое файлами произвольного доступа, а затем вы удалили это из своего вопроса. Вероятно, это то, что вы ищете, особенно запись только для добавления в качестве основной операции. Сверните свою собственную эру TurboPascal "файл записи". Если вы используете тип «ФАЙЛ ЗАПИСИ», вы достигаете предела в 2 ГБ и возникают проблемы с Unicode. Вместо этого используйте TStream, например это. Форматы двоичных файлов имеют много недостатков, особенно потому, что со временем трудно увеличивать и расширять формат двоичных файлов, не нарушая вашу способность читать старые файлы. Это ключевая причина, по которой я бы рекомендовал вам начать с того, что на первый взгляд может показаться излишним (SQLite), вместо того, чтобы создавать собственное бинарное решение.

    (Обновление 2: после обновления вопроса с упоминанием PDF-файлов и тем, что звучит как требование к системе отчетности, я думаю, что вам действительно следует использовать настоящую базу данных, но, возможно, небольшую и простой в использовании, например, firebird или interbase.)

person Warren P    schedule 28.04.2011
comment
(4) сильно преувеличено. РСУБД — это манипулирование производственными данными, а не формат экспорта. Вы действительно хотите видеть его как базу данных, а не как формат хранения. Но есть разница. - person Marco van de Voort; 28.04.2011
comment
Я переписал пункт 4 после того, как ОП дал более подробную информацию о том, что они хотят сделать. - person Warren P; 29.04.2011
comment
О пункте 2. Что-то, что использует SQL, но не является полной базой данных SQL, например SQLite, неверно. Это полная база данных SQL, но не клиент-серверная база данных SQL по умолчанию, но вы можете без проблем использовать ее в клиент-серверном приложении благодаря другому коммуникационному уровню, такому как DataSnap или тому подобное. - person Arnaud Bouchez; 29.04.2011
comment
Об обновлении 2 - я не понимаю, почему реальная база данных обязательна для отчетов - вы можете прекрасно создавать отчеты из чистого кода Delphi, вообще без SQL, с большинством механизмов отчетов. Даже SQlite можно использовать в качестве источника SQL, если вы хотите использовать такие классические механизмы отчетов, ориентированные на диапазоны. - person Arnaud Bouchez; 29.04.2011
comment
А. Бушез; Что означает для человека полная база данных SQL, очень субъективно. Некоторые люди думают, что SQLite — это Embedded SQL Engine, недостаточно автономный, чтобы называться полноценным продуктом базы данных SQL, под которым они подразумевают одного из больших мальчиков (MS SQL Server, Oracle и т. д.). Этот язык субъективен и расплывчат, и я не думаю, что смогу исправить его таким образом, чтобы все меня понимали одинаково. Таким образом, не полная база данных SQL нацелена на контактный язык, который используется OP, а не на попытку быть научным. - person Warren P; 29.04.2011
comment
@Warren Я только что отреагировал на это предложение, потому что создатель SQlite Д. Ричард Хипп тоже отреагировал бы на него! Покрытие движка SQL92 почти полное, и с некоторыми приятными доступными улучшениями (FTS, RTree, динамический печатание). - person Arnaud Bouchez; 29.04.2011
comment
Охват грамматики SQL92 — не единственный фактор, о котором люди могут подумать. - person Warren P; 29.04.2011
comment
Как вы справляетесь с управлением версиями (только с обратной совместимостью), чтением файлов данных, созданных более старыми версиями, в случае sqlite? - person Marco van de Voort; 29.04.2011
comment
Формат файла SQlite очень стабилен. Формат файла изменился только в зависимости от основной версии (SQLite 2, затем SQLite 3). - person Arnaud Bouchez; 29.04.2011

Я бы предложил использовать TClientDataSet и использовать его методы SaveToFile()/SaveToStream() с помощью генерирующей программы и LoadFromFile()/LoadFromStream() методы для программы, которая будет "потреблять" данные. Таким образом, вы по-прежнему можете делать проиндексированные записи без подключения к какой-либо внешней базе данных, сохраняя при этом данные обмена в одном файле.

person Cesar Marrero    schedule 28.04.2011
comment
Кроме того, вы собираетесь использовать более гигабайта памяти, когда набор данных достигает гигабайта, как сказал ОП. Чистое решение для набора данных в памяти (будь то CSV или ClientDataSet) подходит только в том случае, если вы согласны выполнять чтение 1 гигабайта при каждом запуске и запись 1 гигабайта каждый раз, когда вы в безопасности. Все хорошо? Ваш звонок. - person Warren P; 28.04.2011
comment
@Warren - Правда, этот подход наложил бы ограничение на память, поскольку весь файл загружается сразу, но ОП упомянул, что файл может достигать гигабайта, и я ничего не видел о целевая машина с ограниченным объемом памяти. Я предложил CDS как возможный способ обеспечить функциональность, подобную базе данных, без необходимости во внешней базе данных. Однако, если память ЯВЛЯЕТСЯ определяющим фактором, то OP также может рассмотреть возможность разбиения данных на более мелкие фрагменты... в противном случае CDS будет самым простым небазовым решением (помимо написания всего хранилища VCL). с нуля). - person Cesar Marrero; 29.04.2011
comment
Какова производительность TClientDataSet с огромным количеством маленьких записей? Он никогда не предназначался и не предназначался для обработки такой огромной базы данных с небольшими записями. Насколько я знаю, он использует API функций управления массивом для доступа к диску, который никогда не был разработан для этой цели, но для маршалинга данных в OLE-автоматизации. Я бы никогда не рекомендовал этот подход. - person Arnaud Bouchez; 29.04.2011
comment
В решениях на основе памяти, как правило, ОЧЕНЬ БЫСТРО во многих вещах, включая поиск, но они не только используют много памяти, многие могут быть ОЧЕНЬ МЕДЛЕННЫМИ при сохранении измененного набора данных обратно на диск. 1+ ГБ, сохраненные одновременно на вашем диске, могут занять некоторое время. - person Warren P; 29.04.2011
comment
@Warren и @A.Bouchez приводят очень веские аргументы. И +1 A.Bouchez за упоминание Synopse Big Table... Я совершенно забыл об этом замечательном решении без базы данных с открытым исходным кодом. - person Cesar Marrero; 02.05.2011

  1. Определите API для работы с вашим плоским файлом, чтобы API можно было реализовать с помощью отдельного уровня данных разными способами.
  2. Реализуйте API, используя стандартную встроенную базу данных SQL (например, SQLite или Firebird).
  3. Только если со стандартным решением что-то не так, придумайте свое.
person kludg    schedule 28.04.2011
comment
Я буду добавлять данные всегда в конец файла. Это тип данных тренда, скажем, одна запись: температура, 20, 12/12/2011:13:44 ; Каждые 5 минут я буду добавлять новую запись. Тогда мне понадобятся отличные компоненты vcl, которые могут извлекать данные между двумя датами и строить график в хорошем отчете в формате PDF. - person marcostT; 28.04.2011
comment
Дело в том, что файловая структура не имеет большого значения; вы можете использовать стандартную встроенную базу данных SQL (я рекомендую это) или создать свой собственный двоичный формат и код для работы с ним (что, вероятно, не имеет смысла, поскольку стандартного решения достаточно) - person kludg; 28.04.2011
comment
В случае кольцевого буферного файла с тремя полями (скажем, метка времени+температура и несколько целочисленных флагов) я бы использовал простой двоичный формат файла с записью заголовка, показывающей версию файла. - person Warren P; 29.04.2011

Я использую KBMMemtable — см. http://www.components4developers.com/ — быстрый, надежный, долгое время - поддерживает потоковую передачу двоичных файлов и CSV в файлы и из них, а также индексирование, фильтры и множество других полезных функций - TClientDataSet не будет хорошо работать с большими наборами данных.

person Community    schedule 30.04.2011