Frage

    

Diese Frage bereits eine Antwort hier:

    
            
  •              Wie kann ich CSV-Dateien in C ++?                                      33 Antworten                          
  •     
    

Pretty selbsterklärend, habe ich versucht, Google und bekam ohne Erfolg eine Menge von dem gefürchteten expertsexchange, ich auch hier gesucht. Ein Online-Tutorial oder Beispiel wäre am besten. Danke Jungs.

War es hilfreich?

Lösung

Wenn das, was Sie wirklich tun eine CSV-Datei selbst zu manipulieren, Nelson Antwort Sinn macht. Allerdings ist mein Verdacht, dass der CSV ist einfach ein Artefakt des Problems, das Sie lösen. In C ++, das wahrscheinlich bedeutet, dass Sie so etwas wie dies als Datenmodell haben:

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;
};

Wenn Sie also mit einer Sammlung von Daten arbeiten, macht es Sinn, std::vector<Customer> oder std::set<Customer> zu haben.

Mit dem im Verstand, denken Sie an Ihrer CSV als zwei Operationen Handhabung:

// 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);

Lese und eine einzelne Zeile zu einem Zeitpunkt, schreiben, anstatt eine komplette In-Memory-Darstellung der Datei selbst zu halten. Es gibt ein paar offensichtlichen Vorteile:

  1. Ihre Daten werden in einer Form dargestellt, die Sinn für Ihr Problem (Kunden), anstatt die aktuelle Lösung (CSV-Dateien).
  2. macht
  3. Sie können trivialer Adapter für andere Datenformate hinzufügen, wie Substanz- SQL Import / Export, Excel / OO Tabellenkalkulationsdateien oder auch eine HTML-<table> Rendering.
  4. Ihr Speicherbedarf ist wahrscheinlich kleiner sein (abhängig von den relativen sizeof(Customer) gegen die Anzahl von Bytes in einer einzelnen Zeile).
  5. CSVReader und CSVWriter können als Basis für ein In-Memory-Modell (wie Nelsons) wiederverwendet werden, ohne Verlust von Leistung oder Funktionalität. Das Gegenteil ist nicht wahr.

Andere Tipps

Weitere Informationen nützlich wären.

Aber die einfachste Form:

#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!!!!
        }
    }
 }

Auch diese Frage finden Sie unter: CSV-Parser in C ++

Sie können versuchen, die Boost-Tokenizer Bibliothek, insbesondere die List Separator

Ich habe mit vielen CSV-Dateien in meiner Zeit gearbeitet. Ich möchte den Rat hinzuzufügen:

1 - Je nach Quelle (Excel, usw.), Kommata oder Tabs kann in einem Feld eingebettet werden. Üblicherweise wird die Regel ist, dass sie ‚geschützt‘ werden, da das Feld doppelte Anführungszeichen begrenzt wird, wie in „Boston, MA 02346“.

2 - Einige Quellen werden nicht doppelte Anführungszeichen abgrenzen alle Textfelder. Andere Quellen werden. Andere werden alle Felder abgrenzen, auch Numerik.

. 3 - Felder enthalten doppelte Anführungszeichen in der Regel die eingebetteten doppelten Anführungszeichen verdoppelt (und das Feld selbst mit doppelten Anführungszeichen begrenzt, wie in „George‚‘Babe“ „Ruth“

4 - Einige Quellen bettet CR / LFs (Excel ist eine davon!). Manchmal wird es nur ein CR sein. Das Feld wird in der Regel doppelte Anführungszeichen begrenzt sein, aber diese Situation ist sehr schwierig zu handhaben.

Dies ist eine gute Übung für sich selbst zu arbeiten:)

Sie sollten Ihre Bibliothek in drei Teile brechen

  • Laden der CSV-Datei
  • Stellvertretend für die Datei im Speicher, so dass Sie es ändern können, und lesen Sie es
  • Speichern der CSV zurück auf die Festplatte Datei

So Sie das Schreiben eines CSVDocument Klasse suchen, der enthält:

  • Laden (const char * file);
  • Speichern (const char * file);
  • GetBody

Damit Sie Ihre Bibliothek wie folgt verwenden können:

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");

Was gibt uns folgende Schnittstellen:

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);
};

Jetzt müssen Sie nur noch in den Lücken füllen von hier:)

Glauben Sie mir, wenn ich das sage - investieren Sie Ihre Zeit in das Lernen, wie Bibliotheken zu machen, vor allem diejenigen, die sich mit der Belastung, Manipulation und Speicherung von Daten, nicht nur Ihre Abhängigkeit von der Existenz solcher Bibliotheken entfernen, aber Sie werden auch machen ein rundum besserer Programmierer.

:)

Bearbeiten

Ich weiß nicht, wie viel Sie bereits über String-Manipulation und Analyse wissen; also, wenn Sie nicht weiterkommen würde ich gerne zur Verfügung.

Hier finden Sie einige Code, den Sie verwenden können. Die Daten aus der CSV ist innerhalb einer Anordnung von Zeilen gespeichert. Jede Zeile ist ein Array von Zeichenketten. Hoffe, das hilft.

#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;
  }
}

Mit boost tokenizer Datensätze zu analysieren , siehe hier für weitere Details .

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;
}

Look at ' Die Praxis der Programmierung ' (TPOP) von Kernighan & Pike. Es enthält ein Beispiel für das Parsen von CSV-Dateien in C und C ++. Aber es würde sich lohnen, das Buch zu lesen, auch wenn Sie den Code nicht verwendet werden.

(vorherige URL: http://cm.bell-labs.com/ cm / cs / TPOP / )

Ich fand diesen interessanten Ansatz:

CSV-C-Struktur Dienstprogramm

Zitat: CSVtoC ist ein Programm, das eine CSV oder kommagetrennte Werte Datei als Eingabe und gibt sie als eine C-Struktur.

Natürlich können Sie nicht die CSV-Datei Änderungen vornehmen, aber wenn Sie nur im Arbeitsspeicher benötigen Lesezugriff auf die Daten, könnte es funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top