用C++编写.csv文件

56
我正在尝试将一些数据输出到一个 .csv 文件中,虽然它已经成功地输出到了文件中,但是它没有将数据分成不同的列,并且似乎输出的数据是不正确的。
    ofstream Morison_File ("linear_wave_loading.csv");         //Opening file to print info to
    Morison_File << "Time Force(N/m)" << endl;          //Headings for file
    for (t = 0; t <= 20; t++) {
      u = sin(omega * t);
      du = cos(omega * t); 
      F = (0.5 * rho * C_d * D * u * fabs(u)) + rho * Area * C_m * du; 

      cout << "t = " << t << "\t\tF = " << F << endl;
      Morison_File << t;                                 //Printing to file
      Morison_File << F;

    }

     Morison_File.close();

时间和力(N/m)分别在A列和B列中,但t和F值都打印在第一行。

如何使用语法将它们分开,将t打印到A列中,将F打印到B列中?


3
您可以使用分隔符字符,如;,通常受电子表格编辑器支持,而不是制表符。 - remi
2
“CSV” 中的 “S” 代表 “Separated”(分隔)。您不需要编写任何分隔符。不在值之间,也不在记录末尾。 - Some programmer dude
顺便说一下,标题本身没有通过制表符分隔时间和力。 - remi
@remi,分号在它们之间也不起作用... - user3460758
然后再读一遍我的第一个评论。你需要两个分隔符,第一个在tF之间(逗号),然后一个(通常是换行符)来分隔每个记录。你的C++代码与C代码不等价,因为在C代码中,你确实写了分隔符,但在C++代码中没有写。 - Some programmer dude
显示剩余5条评论
6个回答

111

CSV 文件并没有什么特别之处。您可以通过遵循基本规则使用文本编辑器来创建它们。RFC 4180 (tools.ietf.org/html/rfc4180) 接受逗号 ',' 而不是分号 ';' 作为分隔符。像 MS Excel 这样的程序期望使用逗号作为分隔符。

有些程序将逗号视为小数点,将分号视为分隔符,但这些实际上是 CSV 格式文件“被接受”的标准之外的技术。

因此,在创建 CSV 时,您需要创建文件流并添加行,如下所示:

#include <iostream>
#include <fstream>
int main( int argc, char* argv[] )
{
      std::ofstream myfile;
      myfile.open ("example.csv");
      myfile << "This is the first cell in the first column.\n";
      myfile << "a,b,c,\n";
      myfile << "c,s,v,\n";
      myfile << "1,2,3.456\n";
      myfile << "semi;colon";
      myfile.close();
      return 0;
}

在 MS Excel 中打开 CSV 文件将会看到以下内容:

用 C++ 创建的 CSV 文件的图像


19
根据用户的区域设置不同,MS Excel会以不同的方式解析CSV文件。对于“欧洲版”Excel来说,它期望使用分号作为字段分隔符(并将逗号作为小数点)。 - Kris
我的Excel期望分号,但我的Libre Office却只给我一堆东方字符。你知道为什么吗? - user3083324
我不熟悉Libre Office,但根据他们的网站,当导入CSV文件时,您可能需要设置列分隔符。具体操作请参考此处说明:https://help.libreoffice.org/Calc/Importing_and_Exporting_CSV_Files - BHawk
1
你忘记转义包含分隔符的值了。 - Dzmitry Lazerka
我在使用上述代码中的close()调用时遇到了访问冲突错误。但是这个方法对我起作用了:std::fstream myFile; myfile.open ("example.csv", std::ios::out | std::ios::app); - tzg

15

这是一个类似STL的类。

文件名为"csvfile.h"。

#pragma once

#include <iostream>
#include <fstream>

class csvfile;

inline static csvfile& endrow(csvfile& file);
inline static csvfile& flush(csvfile& file);

class csvfile
{
    std::ofstream fs_;
    const std::string separator_;
public:
    csvfile(const std::string filename, const std::string separator = ";")
        : fs_()
        , separator_(separator)
    {
        fs_.exceptions(std::ios::failbit | std::ios::badbit);
        fs_.open(filename);
    }

    ~csvfile()
    {
        flush();
        fs_.close();
    }

    void flush()
    {
        fs_.flush();
    }

    void endrow()
    {
        fs_ << std::endl;
    }

    csvfile& operator << ( csvfile& (* val)(csvfile&))
    {
        return val(*this);
    }

    csvfile& operator << (const char * val)
    {
        fs_ << '"' << val << '"' << separator_;
        return *this;
    }

    csvfile& operator << (const std::string & val)
    {
        fs_ << '"' << val << '"' << separator_;
        return *this;
    }

    template<typename T>
    csvfile& operator << (const T& val)
    {
        fs_ << val << separator_;
        return *this;
    }
};


inline static csvfile& endrow(csvfile& file)
{
    file.endrow();
    return file;
}

inline static csvfile& flush(csvfile& file)
{
    file.flush();
    return file;
}

文件 "main.cpp"

#include "csvfile.h"

int main()
{
    try
    {
        csvfile csv("MyTable.csv"); // throws exceptions!
        // Header
        csv << "X" << "VALUE"        << endrow;
        // Data
        csv <<  1  << "String value" << endrow;
        csv <<  2  << 123            << endrow;
        csv <<  3  << 1.f            << endrow;
        csv <<  4  << 1.2            << endrow;
    }
    catch (const std::exception& ex)
    {
        std::cout << "Exception was thrown: " << e.what() << std::endl;
    }
    return 0;
}

最新版本在这里


4
如果这个CSV写入器类能够接受一个打开的 std::ostream 进行操作,那将会更加有用。可以考虑使用 std::stringbuf - Wolf

8
改变
Morison_File << t;                                 //Printing to file
Morison_File << F;

To

Morison_File << t << ";" << F << endl;                                 //Printing to file

使用逗号也可以代替分号;


4
您必须使用 ";" 分隔符,将 CSV 转换为逗号分隔的值。
 ofstream Morison_File ("linear_wave_loading.csv");         //Opening file to print info to
    Morison_File << "'Time'; 'Force(N/m)' " << endl;          //Headings for file
    for (t = 0; t <= 20; t++) {
      u = sin(omega * t);
      du = cos(omega * t); 
      F = (0.5 * rho * C_d * D * u * fabs(u)) + rho * Area * C_m * du; 

      cout << "t = " << t << "\t\tF = " << F << endl;
      Morison_File << t << ";" << F;

    }

     Morison_File.close();

0
如果你想在C++中写入一个.csv文件 - 你应该使用以下语法:
myfile <<" %s; %s; %d", string1, string2, double1 <<endl;

这将把三个变量(字符串1&2和double1)写入单独的列,并在它们下面留下空行。在Excel中,; 表示新行,所以如果您只想在文件中加入新行,您可以在写入新数据之前写入一个简单的 ";" 。如果你不想在下面有一个空行 - 你应该删除endl并使用:

myfile.open("result.csv", std::ios::out | std::ios::app);

打开 .csv 文件时的语法(例如 result.csv)。通过这种方式,下次当你往 result.csv 文件中写入内容时,它会直接写在上一行的下方,以便于你如果需要管理 for 循环的话可以更加容易地处理。


我怀疑 myfile <<" %s; %s; %d", string1, string2, double1 <<endl; 能否正常工作。应该使用哪个版本的C++? - Wolf

0
如@kris所述,根据MS Excel的区域配置,逗号可能不会被解释为分隔符。在我的情况下,我必须将其更改为分号。

一个例子可能会很有用。@user3460758评论说分号对他不起作用。如果一个或多个值有逗号,那么逗号应该没有任何问题,通常最好在具有逗号的值周围加上引号,例如5,“2,000”,12。 - EpicVoyage
正如我之前所说的那样,这是一个Excel区域配置问题。我不知道如何从这个陈述中提供一个例子。 - Edson Manoel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接