ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C语言读取写入CSV文件 [二]进阶篇——写入CSV文件

2022-02-07 21:35:08  阅读:212  来源: 互联网

标签:fp 文件 写入 空格 字段 fprintf 包裹 CSV


本系列文章目录

[一] 基础篇

[二] 进阶篇——写入CSV

[三] 进阶篇——读取CSV


什么是 包裹(使用双引号)?

包裹的概念是面向字段的,包裹起来的字段将会被视为一个整体。尤其当字段中包含一些特殊符号(如逗号、换行符、双引号)时,如果不将这些字段包裹起来,则很有可能导致 CSV 文件解析发生错误。那么我们该如何包裹一个字段呢,通常将一个字段放置在双引号("")之间,例如"ID",ID就是一个被包裹的字段。任何字段都可以使用双引号("")将其包裹起来,并不存在任何限制。

字段中特殊符号的处理

根据上面的介绍,如果一个字段中包含特殊符号,那么在写入时必须使用双引号来包裹这个字段。有一点需要注意,C语言中字符串中的双引号需要通过使用转义符号来表示(\")

下面分别用逗号、换行符、双引号来做示例

  • 逗号fprintf(fp, "3,\"z,xc\",3.3\n");

  • 换行符fprintf(fp, "4,\"qw\nas\",4.4\n");

  • 双引号fprintf(fp, "5,\"\"aszx\"\",5.5\n");,第一个用作包裹字段,第二个双引号才是实际的双引号。

完整的程序如下:

// 2-1.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp = fopen("tmp.csv", "w+");
    if (fp == NULL) {
        fprintf(stderr, "fopen() failed.\n");
        exit(EXIT_FAILURE);
    }

    fprintf(fp, "ID,Name,Points\n");
    fprintf(fp, "1,qwe,1.1\n");

    int id = 2;
    char *name = "asd";
    float point = 2.2;
    fprintf(fp, "%d,%s,%f\n", id, name, point);

    // special symbols
    fprintf(fp, "3,\"z,xc\",3.3\n");
    fprintf(fp, "4,\"qw\nas\",4.4\n");
    fprintf(fp, "5,\"\"aszx\"\",5.5\n");

    fclose(fp);
    return 0;
}

运行程序,查看 CSV 文件内容,结果为:

Figure. 1

字段开头和结尾处的空格和制表符

CSV 文件中的字段中的开头和结尾上,可能会存在空格或制表符,但是该如何处理呢?按照 RFC 4180 标准的规定,“空格被看作字段的一部分,不应当被忽略”。但是RFC 4180 并不是强制标准,因此某些实现中,空格和制表符会被截断掉。因此 fprintf(fp, " 6,abc,6.6 \n"); 写入的字段可能是 6,abc,6.6 (按照 RFC 4180 标准) 或者是 6,abc,6.6(空格被截掉)

然而,在 RFC 4180 标准中,并未说明空格字符若出现在被包裹的值之外如何处理,例如在 fprintf(fp, " \"7\",def,\"7.7\" \n"); 语句中,如字段 \"7\",虽然7被包裹,但包裹之外的又有空格,因此目前标准中对这样的空格该如何处理还没有规定,可以保留也可以截掉。\"7.7\" 字段也面临着同样的问题。

想要将这种空格视为字段中有意义的数据,最省事的方法是将这些空格也包裹起来,例如 fprintf(fp, "\" 8\",ghi,\"8.8 \"\n"); 语句中的 "\" 8\"\"8.8 \"字段中,属于字段的空格已被包裹。

完整的程序如下:

// 2-2.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp = fopen("tmp.csv", "w+");
    if (fp == NULL) {
        fprintf(stderr, "fopen() failed.\n");
        exit(EXIT_FAILURE);
    }

    fprintf(fp, "ID,Name,Points\n");
    fprintf(fp, "1,qwe,1.1\n");

    int id = 2;
    char *name = "asd";
    float point = 2.2;
    fprintf(fp, "%d,%s,%f\n", id, name, point);

    // special symbols
    fprintf(fp, "3,\"z,xc\",3.3\n");
    fprintf(fp, "4,\"qw\nas\",4.4\n");
    fprintf(fp, "5,\"\"aszx\"\",5.5\n");

    // leading or trailing spaces
    fprintf(fp, "  6,abc,6.6  \n");
    fprintf(fp, "  \"7\",def,\"7.7\"  \n");
    fprintf(fp, "\"  8\",ghi,\"8.8  \"\n");

    fclose(fp);
    return 0;
}

运行程序,查看 CSV 文件内容,结果为:

Figure. 2

分隔符可能存在的问题

在某些国家(如德国、荷兰)中,小数点不是点而是逗号,因此如果依然用逗号作分隔符,那么将无法正确表示。那么该在保证小数点是逗号前提下,如何避免CSV文件解析错误,存在两种解决方法:

  1. 将所有包含小数点的数字包裹起来
  2. 使用分号而不是逗号作为分隔符

利用软件进行配置

无论是开头或结尾处的空格或制表符,还是分隔符的选择,在一些功能强大的软件中,这些其实都可以进行配置,下图分别展示了在 Microsoft Excel、LibreOffice Calc中如何解析CSV文件的配置界面。

Figure. 3

Figure. 4


如果想要了解偏基础的 C 语言读取写入 CSV 文件的内容,欢迎阅读:[一] 基础篇

如果想要了解进阶的 C 语言读取 CSV 文件的内容,欢迎阅读:[三] 进阶篇——读取CSV

标签:fp,文件,写入,空格,字段,fprintf,包裹,CSV
来源: https://www.cnblogs.com/mengxinayan/p/22-02-read-write-csv-in-c-2.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有