Delphi Binary / Текстовый файл Необходимость - PullRequest
2 голосов
/ 15 июня 2010

Я инженер, а не программист, поэтому прошу прощения за мое невежество.

Я написал программу Delphi (7SE) для чтения «реального» типа данных с порта USB, подключенного к двум цифровым термометрам.

Я завершил большую часть программы.

То, что я еще не выполнил, объясняется следующим:

Я хочу сохранить эти «реальные» данные вдвоичный файл (ы).Текстовый файл тоже подойдет, но меня беспокоит наличие большого файла данных.

Я также хотел бы прочитать эти данные из двоичного / текстового файла, чтобы отобразить данные с помощью моего приложения Delphi.

Не думаю, что это будет слишком сложно.В настоящее время я сохраняю свои данные в формате .CSV.

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

Поэтому, когда я нажимаю на сказать, кнопка под названием «исторические» данные, появится новое окно / форма, в которой будут показаны разные времена сеанса, которые я начал и остановил с более ранних времен.Затем будет выбран сеанс, и затем будут получены данные для отображения.

Можно ли это сделать в одном двоичном файле или использовать два файла: один для «настоящих» данных и другой, который индексирует другой сеансраз?

Мое требование для этого способа сохранения двоичных данных состоит в том, что мне не нужно было бы продолжать вводить имена файлов и, следовательно, отслеживать множество файлов данных.

Например thermo.hst (исторические данные) и файл thermo.idx (индексный файл) будут содержать всю информацию, такую ​​как фактические временные данные, время чтения данных, время начала и окончания сеанса и т. д.

Любые полезные указатели и, как мы надеемся, код смного деталей будет принята с благодарностью.

Ответы [ 3 ]

3 голосов
/ 28 июня 2010

Надеюсь, этот пример кода еще не слишком полезен.

(Я добавил это как еще один ответ от меня, чтобы я мог аккуратно перечислить код. Если этот или мой предыдущий пост отвечает на ваш вопрос, пожалуйста, нажмите значок ответа, чтобы я получил очки репутации!)

Ниже приведен примерный код, который показывает, как прочитать разделы в INI-файле и найти самое большое имя файла.Я подтвердил, что он компилируется и, похоже, возвращает допустимые значения, но вам нужно подтвердить, что он делает то, что вам нужно.Это больше, чтобы показать вам идею ...

Обратите внимание, что если ваши имена файлов данных имеют расширение, вы должны добавить код для удаления расширения в моем примере кода, используя что-то вроде: FileName: = ChangeFileExt (Filename, '').

  // Call with an open inifile.  Returns the name of the next filename, or '' if trouble
  Function GetNextFileName( const IniFile: TInifile):String;
  const
    BASE_FILENAME = 'File.'; // sections in the ini file will be [File.1], [File.2], ... [File.100], etc.
  var
    Sections: TStringList;
    NumericPartAsString: String;
    NumericPartAsInteger: Integer;
    ListIndex: Integer;
    LargestFileNumberSeenSoFar: Integer;
  begin
    Result := '';
    Sections := TStringList.Create;
    IniFile.ReadSections(Sections); // fills StringList with the names of all sections in the ini file
    if( Sections.Count = 0) then
      Result := BASE_FILENAME + '1'
    else
      begin  // find largest extension
        LargestFileNumberSeenSoFar := -1;
        ListIndex := 0;
        while ListIndex <= (Sections.Count - 1) do  // for every string (which is also a filename) in the string list:
          begin
            NumericPartAsString := StringReplace(Sections.Strings[ListIndex], BASE_FILENAME, '', []); // remove base filename
            if (NumericPartAsString <> '') then
              begin
                NumericPartAsInteger := StrToIntDef(NumericPartAsString, -1);
                if (NumericPartAsInteger > LargestFileNumberSeenSoFar) then
                  LargestFileNumberSeenSoFar := NumericPartAsInteger;
              end;
            inc(ListIndex);
          end;
        if (LargestFileNumberSeenSoFar > -1) then
          Result := BASE_FILENAME + IntToStr(LargestFileNumberSeenSoFar + 1);
      end;
    Sections.Free;
  end; { GetNextFileName }

  procedure TForm1.Button1Click(Sender: TObject);
  var
    IniFile: TInifile;
    NewFileName: String;
  begin
    IniFile := TInifile.Create('c:\junk\ini.ini');
    NewFileName := GetNextFileName(Inifile);
    if (NewFileName = '') then
      ShowMessage('Error finding new filename')
    else
      ShowMessage('New filename is ' + NewFileName);
    IniFile.Free;
  end;
2 голосов
/ 15 июня 2010

Используя базу данных, вы частично переименовали часть проблемы от «ввода имен файлов и отслеживания множества файлов данных» до «ввода имени набора данных и отслеживания множества наборов данных».

В обоих случаях, например, пользователь или программа должны создать новое имя файла / набора данных и выбрать из списка файлов / наборов данных, чтобы открыть их позже. И в обоих случаях вам нужно вызвать функцию с именем что-то вроде «DeleteDataSet».

Вы можете пересмотреть вопрос о том, действительно ли вам нужна база данных (с соответствующей кривой обучения для API, как определить структуру данных, обновить ее в поле, когда что-то меняется, просмотреть данные в средстве просмотра, получить доступ к данным программно, проприетарный формат, обслуживание базы данных, инструменты восстановления, установка и т. д.) Я уверен, что вы могли бы изучить все это, и они могут быть полезны в будущих проектах. Но, возможно, более простой подход был бы более уместным и адекватным для этого одноразового проекта инженером, не занимающимся программным обеспечением.

Если вы хотите, чтобы в одной папке было много уникальных, автономных файлов данных, я бы рекомендовал вам придерживаться того, что работает: используйте один CSV-файл на набор данных. (Были ли у вас проблемы со скоростью или размером для файлов CSV, содержащих один набор данных? Это было бы огромное количество данных!) Одна приятная вещь о файлах CSV - это то, что вы можете просто вставить их в редактор для просмотра или редактирования. ...

И затем добавьте второй файл, который содержит имена файлов и другую описательную информацию. Этот файл будет простым TIniFile:

[My Name one]
Date=06 June 2010
StartTime=12:30pm
StopTime=3:15pm
FileName=Data1.csv
[My Name two]
...

Инструменты, доступные в Delphi для TIniFile, позволят вам легко управлять этим списком, включая ReadSections в список строк, который вы можете просто назначить в поле со списком, чтобы пользователь мог выбрать набор данных. (См. Пример ниже) И, как и файлы CSV, вы можете просто отредактировать файл .ini в любом текстовом редакторе.

Вам нужно будет создать пользовательский интерфейс, чтобы пользователь мог удалить набор данных (раздел в INI-файле и связанном CSV-файле). Чтобы дать вам представление о том, как будет использоваться INI-файл, вот псевдокод для удаления набора данных:

(В Инспекторе объектов IDE установите ComboBox.Style: = csDropDownList, чтобы запретить пользователю вводить имя, которое не существует.)

Загрузить комбинированное окно, в котором отображаются доступные наборы данных.

1. ComboBox.Items := IniFile.ReadSections;

В обработчике события OnSelect комбинированного блока:

2. DeleteFile(IniFile.ReadString(CombBox.Text, 'FileName', '')); 
3. IniFile.EraseSection(ComboBox.Text); // remove the section from the inifile

Черт, это не так много кода, даже после того, как вы добавите немного защиты и проверки ошибок!

Возможно, вышеупомянутое решение будет отвергнуто другими здесь как попытка поставить круглый колышек в квадратное отверстие или заново изобрести колесо. И я мог бы согласиться с ними. Есть хорошие аргументы против этого подхода, в том числе распространение многих файлов. Но если бы это был я, я бы по крайней мере считал этот подход простым и не требующим ничего нового, кроме того, что вы изучаете объект TIniFile, который является довольно мощным.

0 голосов
/ 15 июня 2010

Данные могут чередоваться.Просто начните каждый блок (набор истории) с заголовка, который идентифицирует блок и содержит его длину.При чтении вы можете легко отделить это.

Вы можете держать дополнительный индексный файл рядом с этим для быстрого доступа, если вам требуется, но если это так, я бы начал изучать некоторые встроенные базы данных.(TDBF, sqlite или встроенный firebird).

Я бы также пошел в направлении базы данных, если бы ожидал, что мои запросы станут более сложными в будущем.

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

...