【问题标题】:How to read-write into/from text file with comma separated values如何使用逗号分隔值读写文本文件
【发布时间】:2023-03-02 23:57:02
【问题描述】:

如果我的文件是这样的逗号分隔值,我如何从文件中读取数据

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

读取文件后,我想将数据写回其他文件,格式与上述相同。

我可以得到总行数,使用

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

但是我怎么知道一行/行中的总位数??

我也有整数向量来存储数据。 所以,我想读取第一行,然后计算该行中的元素总数,这里是 5 (1,2,3,4,5) 并将它们存储在数组/向量中,然后读取下一行并将它们存储在向量中以此类推,直到我到达 EOF。

然后,我想将数据写入文件,我想这将完成将数据写入文件的工作,

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

所以,我的主要问题是如何用逗号分隔值从文件中读取数据??

谢谢

【问题讨论】:

    标签: c++ csv


    【解决方案1】:

    第 1 步: 不要这样做:

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

    在您尝试阅读之前,EOF 不是真的。 标准模式是:

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

    还要注意std::getline() 可以选择采用第三个参数。这是要突破的角色。默认情况下,这是行终止符,但您可以指定逗号。

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

    如果您将所有值存储在单个向量中,则使用固定宽度将它们打印出来。然后我会做这样的事情。

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

    【讨论】:

    • 这是做什么的? std::stringstream linestream(line);
    • 它创建一个字符串流对象。它就像一个流,如 std::cin、std::cout 或文件流 std::fstream,但使用字符串作为数据源。所以实际上它是一个只有一行的流。
    • 当我尝试编译时,我得到这个错误,变量 `std::stringstream linestream' 有初始化程序但类型不完整。我已经包含了所有需要的标题。
    • std::stringstream 已定义
    【解决方案2】:

    我在这里发布 CSV 读取和编写代码的代码。我检查了它的工作正常。

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

    【讨论】:

      【解决方案3】:

      试试stringstream 类:

      #include <sstream>
      

      以防万一,请查看 Stroustrup 的“The C++ Programming Language Special Edition”第 641 页示例。

      它对我有用,我花了很长时间试图弄清楚这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-13
        • 1970-01-01
        • 2018-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多