web-dev-qa-db-fra.com

Comment lire / écrire dans / depuis un fichier texte avec des valeurs séparées par des virgules

Comment lire les données d'un fichier si mon fichier est comme ça avec des valeurs séparées par des virgules

1, 2, 3, 4, 5\n
6, 7, 8, 9, 10\n
\n

et après avoir lu le fichier, je veux réécrire les données dans un autre fichier au même format que ci-dessus.

Je peux obtenir le nombre total de lignes en utilisant

string line;
while(!file.eof()){
      getline(file,line);
      numlines++;
    }
    numline--; // remove the last empty line

mais comment puis-je savoir le nombre total de chiffres dans une ligne/ligne ??

J'ai également un vecteur d'entiers pour stocker les données. Donc, je veux lire la première ligne, puis compter le nombre total d'éléments dans cette ligne, ici 5 (1,2,3,4,5) et les stocker dans le tableau/vecteur, et lire la ligne suivante et les stocker dans le vecteur encore et ainsi de suite jusqu'à ce que j'atteigne l'EOF.

Ensuite, je veux écrire les données dans un fichier, encore une fois, je suppose que cela fera le travail d'écrire des données dans un fichier,

numOfCols=1;
for(int i = 0; i < vector.size(); i++)
{
    file << vector.at(i);
    if((numOfCols<5) file << ",";//print comma (,)
    if((i+1)%5==0)
    {
                  file << endl;//print newline after 5th value
                  numOfCols=1;//start from column 1 again, for the next line
    }
    numOfCols++;
}
file << endl;// last new line

Donc, mon principal problème est de savoir comment lire les données du fichier avec des valeurs séparées par des virgules ??

Merci

24
Curious

Étape 1: ne faites pas cela:

while(!file.eof())
{
    getline(file,line);
    numlines++;
}
numline--; 

Le EOF n'est pas vrai tant que vous n'avez pas essayé de le lire. Le modèle standard est:

while(getline(file,line))
{
    ++numline;
}

Notez également que std::getline() peut éventuellement prendre un troisième paramètre. C'est le personnage sur lequel se briser. Par défaut, c'est le terminateur de ligne mais vous pouvez spécifier une virgule.

while(getline(file,line))
{
    std::stringstream   linestream(line);
    std::string         value;

    while(getline(linestream,value,','))
    {
        std::cout << "Value(" << value << ")\n";
    }
    std::cout << "Line Finished" << std::endl;

}

Si vous stockez toutes les valeurs dans un seul vecteur, imprimez-les à l'aide d'une largeur fixe. Ensuite, je ferais quelque chose comme ça.

struct LineWriter
{
        LineWriter(std::ostream& str,int size)
                :m_str(str)
                ,m_size(size)
                ,m_current(0)
        {}

        // The std::copy() does assignement to an iterator.
        // This looks like this  (*result) = <value>;
        // So overide the operator * and the operator = to
        LineWriter& operator*() {return *this;}   
        void operator=(int val)
        {
                ++m_current;
                m_str << val << (((m_current % m_size) == 0)?"\n":",");
        }

        // std::copy() increments the iterator. But this is not usfull here
        // so just implement too empty methods to handle the increment.
        void operator++()       {}
        void operator++(int)    {}

        // Local data.
        std::ostream&           m_str;
        int const               m_size;
        int                     m_current;
};

void printCommaSepFixedSizeLinesFromVector(std::vector const& data,int linesize)
{
    std::copy(data.begin(),data.end(),LineWriter(std::cout,linesize));
}
28
Martin York

ici, je publie le code pour lire et écrire du code CSV. J'ai vérifié son bon fonctionnement.

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;

void readCSV(istream &input, vector< vector<string> > &output)
{
   string csvLine;
    // read every line from the stream
    while( getline(input, csvLine) )
    {
            istringstream csvStream(csvLine);
           vector<string> csvColumn;
            string csvElement;
            // read every element from the line that is seperated by commas
            // and put it into the vector or strings
            while( getline(csvStream, csvElement, ',') )
            {
                    csvColumn.Push_back(csvElement);
            }
            output.Push_back(csvColumn);
    }
}

int main()
{
    ofstream myfile;
    string a;
    fstream file("b.csv", ios::in);
    myfile.open ("ab.csv");
    if(!file.is_open())
    {
           cout << "File not found!\n";
            return 1;
    }
    // typedef to save typing for the following object
    typedef vector< vector<string> > csvVector;
    csvVector csvData;

    readCSV(file, csvData);
    // print out read data to prove reading worked
    for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
    {
            for(vector<string>::iterator j = i->begin(); j != i->end(); ++j)
            {
          a=*j;
                  cout << a << " ";
          myfile <<a<<",";

 }
 myfile <<"\n";
 cout << "\n";
 }
 myfile.close();
 system("pause");

}
8
amrita Jaiswal

Essayez la classe stringstream :

#include <sstream>

Au cas où, recherchez l'exemple de la page 641 de "The C++ Programming Language Special Edition" de Stroustrup.

Cela fonctionne pour moi et j'ai eu beaucoup de temps à essayer de comprendre celui-ci.

1
hock