Sign in Join
Wiki copytemporary

CSV/ru

English · Русский

Обзор

CSV означает Comma-Separated Values (значения, разделенные запятыми) и является популярным форматом файлов, который, к сожалению, не полностью стандартизирован.

Это текстовый формат файла с

RFC4180 (см.здесь) пытается кодифицировать и стандартизировать существующую практику; имеет смысл соответствовать этому стандарту при записи данных CSV (и принимать все данные RFC4180 при чтении).

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

Образец фрагмента CSV:

text
FirstName,Surname,DOB,Remarks
Jim,Weston,19560818,"Also known as ""The Butcher"""
Alice,Cooper,19760312,""

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

Пакеты электронных таблиц, такие как Microsoft Excel и OpenOffice/LibreOFfice Calc, могут экспортировать и импортировать из этого формата. Однако, поскольку Microsoft Excel может интерпретировать некоторые поля, такие как поля даты, по-разному в зависимости от языкового стандарта операционной системы пользователя, возможно целесообразнее найти альтернативные способы передачи данных (например, используя код FPSpreadsheet).

CSV и SDF

Delphi (и FreePascal) имеют очень похожий (но не идентичный) формат SDF. См. SDF для получения более подробной информации.

Реализации

CsvDocument

CsvDocument является надежной реализацией как CSV-формата RFC 4180 ,так и альтернативного CSV-формата Creativyst/Excel. Он предлагает как линейный, так и документный доступ. Рекомендуется для использования с FPC/Lazarus. См. CsvDocument.

DelimitedText

TStringList предлагает свойство DelimitedText. Оно разбивает строку текста на отдельные поля. Обратите внимание, однако, что DelimitedText должен быть в SDF-формате, специфичном для Delphi, который очень похож на CSV, но не полностью соответствует RFC4180.

Совет: при чтении данных CSV установите для свойства StrictDelimiter значение true.

При записи CSV-данных установите для StrictDelimiter значение false и выведите свойство DelimitedText. Тут есть одна странность, заключающаяся в том, что, например, символы табуляции удаляются при записи данных с использованием StrictDelimiter:=false

Формат SDF

См. формат SDF

SDFDataset

FreePascal предлагает TSdfDataSet, который хранит данные в формате SDF. Примечание: FPC 2.6.x и более ранние версии хранят данные sdfdataset в формате, который не является полностью CSV или SDF-совместимым. Sdfdataset планируется переписать для хранения данных в формате CSV.

Как указано, SDF отличается от CSV. В зависимости от разновидности CSV этот формат может быть достаточно близок к тому, что ожидает от него читающее приложение.

Warning:

Note:

Файлы с примерами TSdfDataset и TFixedDataset

Ниже приведен пример базы данных для TSdfDataset. Обратите внимание, что в первой строке указаны имена полей и мы используем запятые в качестве разделителей:

pascal
ID,NAMEEN,NAMEPT,HEIGHT,WIDTH,PINS,DRAWINGCODE
1,resistor,resistor,1,1,1,LINE
2,capacitor,capacitor,1,1,1,LINE
3,transistor npn,transistor npn

Каждая запись занимает фиксированное количество пробелов, и если поле меньше, пробелы должны использоваться для заполнения оставшегося размера.

pascal
Name = 15 chars; Surname = 15 chars; e_mail = 20 chars;
Piet           Pompies                  piet@pompies.net

Использование наборов данных: пример кода

Иногда полезно создать набор данных и работать с ним полностью в коде, и следующий код сделает это точно. Обратите внимание на некоторые особенности TSdfDataset/TFixedDataset:

pascal
uses sdfdata, db;

constructor TComponentsDatabase.Create;
var
  FDataset: TSdfDataset;
begin
  inherited Create;

  FDataset := TSdfDataset.Create(nil);
  FDataset.FileName := vConfigurations.ComponentsDBFile;
  FDataset.FileMustExist := false; // существующий CSV-файл не требуется

  // Не обязательно с TSdfDataset:
  //  FDataset.TableName := STR_DB_COMPONENTS_TABLE;
  //  FDataset.PrimaryKey := STR_DB_COMPONENTS_ID;

  // Добавляем определения полей
  FDataset.FieldDefs.Add('ID', ftString);
  //необходимо добавить схему, чтобы sdfdataset правильно записал заголовок csv:
  FDataset.Schema.Add('ID'); 
  FDataset.FieldDefs.Add('NAMEEN', ftString);
  FDataset.Schema.Add('NAMEEN'); 
  FDataset.FieldDefs.Add('NAMEPT', ftString);
  FDataset.Schema.Add('NAMEPT'); 
  FDataset.FieldDefs.Add('HEIGHT', ftString);
  FDataset.Schema.Add('HEIGHT'); 
  FDataset.FieldDefs.Add('WIDTH', ftString);
  FDataset.Schema.Add('WIDTH'); 
  FDataset.FieldDefs.Add('PINS', ftString);
  FDataset.Schema.Add('PINS'); 
  FDataset.FieldDefs.Add('DRAWINGCODE', ftString);
  FDataset.Schema.Add('DRAWINGCODE'); 

  // Необходимо для TSdfDataset
  FDataset.Delimiter := ',';
  FDataset.FirstLineAsSchema := True;

  FDataset.Active := True;

  // Устанавливаем начальную запись
  CurrentRecNo := 1;
  FDataset.First;
end;

При использовании TSdfDataSet следует помнить, что RecNo, хоть и реализован, но не работает как способ перемещения по набору данных при чтении или записи записей. Стандартные процедуры навигации, такие как First, Next, Prior и Last, работают как и положено, поэтому вам нужно использовать их, а не RecNo.

Если вы привыкли использовать абсолютные номера записей для навигации по базе данных, вы можете реализовать свою собственную версию RecNo. Объявите глобальную переменную longint с именем CurrentRecNo, которая будет содержать текущее значение RecNo. Помните, что эта переменная будет иметь то же соглашение, что и RecNo, поэтому первая запись имеет номер 1 (а не начинается с нуля). После активации базы данных инициализируйте базу данных для первой записи с помощью TSdfDataset.First и установите CurrentRecNo:= 1.

Пример кода:

pascal
{@@
  Перемещение к нужной записи с использованием TDataset.Next и TDataset.Prior. 
  Это позволяет избегать использования TDataset.RecNo, который не обеспечивает надежную навигацию в любом наборе данных.

  @param AID Указывает номер записи. Первая запись имеет номер 1
}
procedure TComponentsDatabase.GoToRec(AID: Integer);
begin
  // Мы находимся перед искомой записью, двигаемся вперед
  if CurrentRecNo < AID then
  begin
    while (not FDataset.EOF) and (CurrentRecNo < AID) do
    begin
      FDataset.Next;
      FDataset.CursorPosChanged;
      Inc(CurrentRecNo);
    end;
  end
  // Мы находимся после искомой записи, двигаемся назад
  else if CurrentRecNo > AID  then
  begin
    while (CurrentRecNo >= 1) and (CurrentRecNo > AID) do
    begin
      FDataset.Prior;
      FDataset.CursorPosChanged;
      Dec(CurrentRecNo);
    end;
  end;
end;

Экспорт данных

Функциональность экспорта базы данных FreePascal/Lazarus (например, TCSVExporter на вкладке «Data Export») предлагает функцию экспорта CSV для наборов данных.

CSV компоненты Jan

См. JCSV (Jans CSV Components).

ZMSQL

ZMSQL хранит данные в файлах, разделенных точкой с запятой (используя SDF?).


From the Free Pascal wiki, page "CSV/ru", as it stood on 2020-07-15 after a change by Zoltanleo, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 4, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.