当前位置:   article > 正文

[C++]C语言读取写入CSV文件 [一]基础篇

[C++]C语言读取写入CSV文件 [一]基础篇

本系列介绍了如何利用C语言读取写入CSV文件,本篇是系列的第一篇,介绍了利用C语言读写CSV文件的基础内容,包括什么是CSV、C语言写入CSV文件、和C语言读取CSV文件

本系列文章目录

[一] 基础篇

[二] 进阶篇——写入CSV

[三] 进阶篇——读取CSV


什么是CSV?

CSV 是一种以纯文本形式存储的表格数据,具体介绍如下(来自维基百科):

逗号分隔值(Comma-Separated Values, CSV,有时也称为 字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

简单的说,CSV 是一种通用的、相对简单的表格文件格式,最广泛的应用就是在不同程序之间转移表格数据。值得注意的是,CSV 并没有一种单一的、定义明确的格式(虽然有一个 RFC 4180 的定义),一般地,CSV 文件具有如下特征:

  1. 纯文本,使用某个特定的字符集保存,例如 ASCII、Unicode 等
  2. 由一条条记录组成,一般每一行代表一条记录
  3. 每条记录被分隔符划分为不同的字段,最常见的分隔符是逗号,毕竟其中文名叫逗号分隔值:)
  4. 每条记录相同的字段序列

因为CSV 并没有一种单一的、定义明确的格式,因此下面的内容以最常见的格式为例,即逗号(,)分隔字段,换行符(\n)分隔记录。

C 语言写入 CSV 文件

首先我们来了解如何写入一个 CSV 文件,下面是示例代码:

  1. // 1-1.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main()
  5. {
  6. FILE *fp = fopen("tmp.csv", "w+");
  7. if (fp == NULL) {
  8. fprintf(stderr, "fopen() failed.\n");
  9. exit(EXIT_FAILURE);
  10. }
  11. fprintf(fp, "ID,Name,Points\n");
  12. fprintf(fp, "1,qwe,1.1\n");
  13. int id = 2;
  14. char *name = "asd";
  15. float point = 2.2;
  16. fprintf(fp, "%d,%s,%f\n", id, name, point);
  17. fclose(fp);
  18. return 0;
  19. }

上述代码中,首先便是打开一个 CSV 文件,若打开失败,那么则报告出错结束程序。接下来便是向打开的 CSV 文件写入内容:

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

常见的CSV文件的分隔符是逗号(,),被分隔符分开的字段会位于不同的列。在上述语句中,IDNamePoints 被分隔符分开,因此这个CSV文件共有3列,分别是IDNamePoints

CSV文件是由一条条记录组成的,常见划分不同记录的符号是换行符(\n)。在上述语句中,IDNamePoints 分别属于同一行上的不同三列,很显然,这条记录是表头。

接下来的 fprintf(fp, "1,qwe,1.1\n"); 语句写入的记录为 1、qwe、1.1,分为三列,正好对应于 ID=1、Name=qwe、Points=1.1。前一条语句采用了直接写入,但很多时候我们的值是变化的,幸运的是,CSV的写入同样支持格式化写入,代码如下:

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

最后写入的记录为 2(ID)、asd(Name)、2.2(Points)。运行程序,查看 CSV 文件内容,结果为:

图1. CSV文件内容截图

C 语言读取 CSV 文件

示例程序如下:

  1. // 1-2.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. int main()
  6. {
  7. FILE *fp = fopen("tmp.csv", "r");
  8. if (fp == NULL) {
  9. fprintf(stderr, "fopen() failed.\n");
  10. exit(EXIT_FAILURE);
  11. }
  12. char row[80];
  13. char *token;
  14. while (fgets(row, 80, fp) != NULL) {
  15. printf("Row: %s", row);
  16. token = strtok(row, ",");
  17. while (token != NULL) {
  18. printf("Token: %s\n", token);
  19. token = strtok(NULL, ",");
  20. }
  21. }
  22. fclose(fp);
  23. return 0;
  24. }

首先要打开将要读取的CSV文件,这一步和写入一样,不再赘述。

  1. while (fgets(row, 80, fp) != NULL) {
  2. printf("Row: %s", row);
  3. // other code
  4. }

因为CSV文件是一个纯文本文件,因此我们可以使用 fgets 函数一行一行地进行读取,这样读取得到的便是CSV文件中一条条记录。接下来要做的就是将不同字段从记录中分隔出来:

  1. token = strtok(row, ",");
  2. while (token != NULL) {
  3. printf("Token: %s\n", token);
  4. token = strtok(NULL, ",");
  5. }

char* strtok(char *restrict str, const char *restrict delim) 函数可以把字符串 str 按照给定的分隔符 delim 进行分隔,如果要解析仍是之前同一个字符串时,需要把 str 设为 NULL。因此 token = strtok(row, ","); 这条语句会尝试用逗号(,)来分割刚刚读取得到的记录,同时使用一个 while (token != NULL) 循环来不断进行分割,直到无法分隔为止,这样就得到每个字段的值。

程序运行输出的结果如下:

  1. $ clang 1-2.c -o 1-2
  2. $ ./1-2
  3. Row: ID,Name,Points
  4. Token: ID
  5. Token: Name
  6. Token: Points
  7. Row: 1,qwe,1.1
  8. Token: 1
  9. Token: qwe
  10. Token: 1.1
  11. Row: 2,asd,2.200000
  12. Token: 2
  13. Token: asd
  14. Token: 2.200000

最后总结一下,CSV 文件和普通文件一样,无论读写都需要先打开文件。而后写入或读取时所用的函数和普通文件没有区别,唯一需要注意的是,CSV 文件通过特定的分隔符来区分字段和记录:

  • 用换行符(\n)来区分记录,一条记录会占据CSV文件的一行
  • 用逗号(,)来区分一条记录中的不同字段,每个字段会单独占据一列
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/959227
推荐阅读
相关标签
  

闽ICP备14008679号