Как я могу считать и управлять данными файла CSV в C++? [дубликат]

Вы также можете просто сделать:

document.getElementById('id').classList.add('class');
document.getElementById('id').classList.remove('class');

И переключить класс (удалить, если есть еще добавить его):

document.getElementById('id').classList.toggle('class');
51
задан yesraaj 19 January 2009 в 06:52
поделиться

9 ответов

Если то, что Вы действительно делаете, управляет самим файлом CSV, ответ Nelson имеет смысл. Однако мое подозрение - то, что CSV является просто артефактом проблемы, которую Вы решаете. В C++, который, вероятно, означает, у Вас есть что-то вроде этого как Ваша модель данных:

struct Customer {
    int id;
    std::string first_name;
    std::string last_name;
    struct {
        std::string street;
        std::string unit;
    } address;
    char state[2];
    int zip;
};

Таким образом, когда Вы работаете с набором данных, имеет смысл иметь std::vector<Customer> или std::set<Customer>.

, Имея это в виду, думают о Вашем CSV, обрабатывающем как две операции:

// if you wanted to go nuts, you could use a forward iterator concept for both of these
class CSVReader {
public:
    CSVReader(const std::string &inputFile);
    bool hasNextLine();
    void readNextLine(std::vector<std::string> &fields);
private:
    /* secrets */
};
class CSVWriter {
public:
    CSVWriter(const std::string &outputFile);
    void writeNextLine(const std::vector<std::string> &fields);
private:
    /* more secrets */
};
void readCustomers(CSVReader &reader, std::vector<Customer> &customers);
void writeCustomers(CSVWriter &writer, const std::vector<Customer> &customers);

Read и пишут единственную строку за один раз, вместо того, чтобы сохранить полное представление в оперативной памяти самого файла. Существует несколько очевидных преимуществ:

  1. Ваши данные представлены в форме, которая имеет смысл для Вашей проблемы (клиенты), а не текущее решение (файлы CSV).
  2. можно тривиально добавить адаптеры для других форматов данных, таких как объемный импорт/экспорт SQL, файлы электронной таблицы Excel/OO, или даже рендеринг HTML <table>.
  3. Ваш объем потребляемой памяти, вероятно, будет меньшим (зависит от родственника sizeof(Customer) по сравнению с числом байтов в единственной строке).
  4. CSVReader и CSVWriter может быть снова использован как основание для модели в оперативной памяти (такой как Nelson) без потери производительности или функциональности. Обратное неверно.
9
ответ дан Tom 7 November 2019 в 20:01
поделиться

Я нашел этот интересный подход:

CSV к утилите структуры C

Кавычка: CSVtoC является программой, которая берет CSV или разделенный от запятой файл значений, как введено и выводит его как структуру C.

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

0
ответ дан Kevin P. 7 November 2019 в 10:01
поделиться

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

ifstream in(data.c_str());
if (!in.is_open()) return 1;

typedef tokenizer< escaped_list_separator<char> > Tokenizer;

vector< string > vec;
string line;

while (getline(in,line))
{
    Tokenizer tok(line);
    vec.assign(tok.begin(),tok.end());

    /// do something with the record
    if (vec.size() < 3) continue;

    copy(vec.begin(), vec.end(),
         ostream_iterator<string>(cout, "|"));

    cout << "\n----------------------" << endl;
}
2
ответ дан 7 November 2019 в 10:01
поделиться

Больше информации было бы полезно.

, Но самая простая форма:

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream  data("plop.csv");

    std::string line;
    while(std::getline(data,line))
    {
        std::stringstream  lineStream(line);
        std::string        cell;
        while(std::getline(lineStream,cell,','))
        {
            // You have a cell!!!!
        }
    }
 }

Также посмотрите этот вопрос: синтаксический анализатор CSV в C++

56
ответ дан Community 7 November 2019 в 20:01
поделиться

Можно попробовать библиотеку Boost Tokenizer, в особенности Оставленный Разделитель элементов списка

21
ответ дан Alessandro Jacopson 7 November 2019 в 20:01
поделиться

Я работал с большим количеством файлов CSV в мое время. Я хотел бы добавить совет:

1 - В зависимости от источника (Excel, и т.д.), запятые или вкладки могут быть встроены в поле. Обычно, правило состоит в том, что они будут 'защищены', потому что поле будет разграниченной двойной кавычкой, как в "Бостоне, Массачусетс 02346".

2 - Некоторые источники не будут двойная кавычка разграничивать все текстовые поля. Другие источники будут. Другие разграничат все поля, даже численные данные.

3 - Поля, содержащие двойные кавычки обычно, сгибали встроенные двойные кавычки (и само поле, разграниченное с двойными кавычками, как в "George"""Babe""" Ruth".

4 - Некоторые источники встроят CR/LFs (Excel является одним из них!). Иногда это будет просто CR. Поле обычно будет разграниченной двойной кавычкой, но эту ситуацию очень трудно обработать.

8
ответ дан Marc Bernier 7 November 2019 в 20:01
поделиться

Взгляд' Практика Программирования ' (TPOP) Kernighan & Пика. Это включает пример парсинга файлов CSV и в C и в C++. Но стоило бы прочитать книгу, даже если Вы не используете код.

(Предыдущий URL: http://cm.bell-labs.com/cm/cs/tpop/ )

2
ответ дан Jonathan Leffler 7 November 2019 в 20:01
поделиться

Вот некоторый код, который можно использовать. Данные из csv хранятся в массиве строк. Каждая строка является массивом строк. Надежда это помогает.

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
typedef std::string String;
typedef std::vector<String> CSVRow;
typedef CSVRow::const_iterator CSVRowCI;
typedef std::vector<CSVRow> CSVDatabase;
typedef CSVDatabase::const_iterator CSVDatabaseCI;
void readCSV(std::istream &input, CSVDatabase &db);
void display(const CSVRow&);
void display(const CSVDatabase&);
int main(){
  std::fstream file("file.csv", std::ios::in);
  if(!file.is_open()){
    std::cout << "File not found!\n";
    return 1;
  }
  CSVDatabase db;
  readCSV(file, db);
  display(db);
}
void readCSV(std::istream &input, CSVDatabase &db){
  String csvLine;
  // read every line from the stream
  while( std::getline(input, csvLine) ){
    std::istringstream csvStream(csvLine);
    CSVRow csvRow;
    String csvCol;
    // read every element from the line that is seperated by commas
    // and put it into the vector or strings
    while( std::getline(csvStream, csvCol, ',') )
      csvRow.push_back(csvCol);
    db.push_back(csvRow);
  }
}
void display(const CSVRow& row){
  if(!row.size())
    return;
  CSVRowCI i=row.begin();
  std::cout<<*(i++);
  for(;i != row.end();++i)
    std::cout<<','<<*i;
}
void display(const CSVDatabase& db){
  if(!db.size())
    return;
  CSVDatabaseCI i=db.begin();
  for(; i != db.end(); ++i){
    display(*i);
    std::cout<<std::endl;
  }
}
6
ответ дан 7 November 2019 в 20:01
поделиться

Это - хорошее осуществление для себя, чтобы продолжить работать:)

необходимо повредить библиотеку в три части

  • Загрузка файла CSV
  • Представление файла в памяти так, чтобы можно было изменить его и считать его
  • Сохранение на диск файла CSV назад, Таким образом, Вы смотрите на запись класса CSVDocument, который содержит:

    • Загрузка (символ константы* файл);
    • Сохраняют (символ константы* файл);
    • GetBody

    Так, чтобы можно было пользоваться библиотекой как это:

    CSVDocument doc;
    doc.Load("file.csv");
    CSVDocumentBody* body = doc.GetBody();
    
    CSVDocumentRow* header = body->GetRow(0);
    for (int i = 0; i < header->GetFieldCount(); i++)
    {
        CSVDocumentField* col = header->GetField(i);
        cout << col->GetText() << "\t";
    }
    
    for (int i = 1; i < body->GetRowCount(); i++) // i = 1 so we skip the header
    {
        CSVDocumentRow* row = body->GetRow(i);
        for (int p = 0; p < row->GetFieldCount(); p++)
        {
            cout << row->GetField(p)->GetText() << "\t";
        }
        cout << "\n";
    }
    
    body->GetRecord(10)->SetText("hello world");
    
    CSVDocumentRow* lastRow = body->AddRow();
    lastRow->AddField()->SetText("Hey there");
    lastRow->AddField()->SetText("Hey there column 2");
    
    doc->Save("file.csv");
    

    , Который дает нам следующие интерфейсы:

    class CSVDocument
    {
    public:
        void Load(const char* file);
        void Save(const char* file);
    
        CSVDocumentBody* GetBody();
    };
    
    class CSVDocumentBody
    {
    public:
        int GetRowCount();
        CSVDocumentRow* GetRow(int index);
        CSVDocumentRow* AddRow();
    };
    
    class CSVDocumentRow
    {
    public:
        int GetFieldCount();
        CSVDocumentField* GetField(int index);
        CSVDocumentField* AddField(int index);
    };
    
    class CSVDocumentField
    {
    public:
        const char* GetText();
        void GetText(const char* text);
    };
    

    Теперь просто необходимо восполнить пробелы отсюда:)

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

    :)

    РЕДАКТИРОВАНИЕ

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

7
ответ дан 7 November 2019 в 20:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: