## 介绍 ### 什么是CSV文件? CSV(逗号分隔值)是一种常见的文件格式,用于存储和交换简单的数据表格。CSV文件由文本行组成,每行代表表格中的一行数据,每个数据字段之间使用逗号分隔。 ### CSV文件的特点 - **简单易用**:CSV文件使用纯文本格式,易于创建和编辑。几乎所有的电子表格软件和文本编辑器都支持CSV文件的读写操作。 - **跨平台兼容**:CSV文件是一种通用的数据交换格式,可以在不同操作系统上进行读取和处理,如Windows、Mac和Linux。 - **灵活性**:CSV文件可以包含任意数量的行和列,可以存储各种类型的数据,如文本、数字和日期。 - **可读性**:由于CSV文件采用纯文本格式,因此易于人类阅读和理解,也方便数据分析和处理。 ### CSV文件的用途 CSV文件广泛应用于数据导入、导出和交换的场景,包括: - **数据导入和导出**:CSV文件常用于将数据从一个应用程序导出到另一个应用程序,或从数据库导出到电子表格软件,反之亦然。 - **数据交换**:CSV文件作为一种通用的数据交换格式,常用于不同系统之间的数据交换,如数据集成、数据同步等。 - **数据备份和存储**:CSV文件可以作为一种简单的数据备份和存储格式,方便将数据以纯文本形式保存,并在需要时进行恢复。 - **数据分析和处理**:CSV文件可以方便地进行数据分析和处理,可以使用各种数据分析工具(如Excel、Python等)对CSV文件进行操作和计算。 ### 如何创建和编辑CSV文件? 创建和编辑CSV文件可以使用文本编辑器、电子表格软件或编程语言来实现。以下是一些常见的方法: - **文本编辑器**:可以使用文本编辑器(如Notepad++、Sublime Text等)创建和编辑CSV文件,按照逗号分隔每个数据字段。 - **电子表格软件**:常见的电子表格软件(如Microsoft Excel、Google Sheets等)提供导入、导出和编辑CSV文件的功能。可以使用电子表格软件创建和编辑CSV文件,并保存为CSV格式。 - **编程语言**:使用编程语言(如Python、Java等)可以读取、写入和处理CSV文件。许多编程语言提供了专门的CSV库和函数,方便对CSV文件进行操作和处理。 ### 注意事项 在创建和处理CSV文件时,需要注意以下事项: - **数据格式**:确保CSV文件中的数据按照正确的格式进行存储,如日期、数字等需要按照约定的格式进行输入。 - **数据编码**:根据需要选择适当的字符编码,在不同操作系统和应用程序中确保CSV文件的编码一致性。 - **数据转义**:当数据字段中包含逗号、换行符等特殊字符时,需要进行适当的转义或引用,以确保数据的正确性。 ### C语言版CSV库 varch提供的CSV库,简便易用,能完成大部分对于表格的基础操作,包含对csv的加载和保存,针对行、列、单元格的增删改查。 ## 接口 ### 创建和删除csv对象 ```c csv_t csv_create(unsigned int row, unsigned int col, const void *array); void csv_delete(csv_t csv); ``` 其中**csv_t**为csv的结构体,创建方法会生成一个指定行列的表格,同时初始化为指定的array。删除方法则删除指定的csv对象。 ### csv对象加载 ```c csv_t csv_loads(const char* text); csv_t csv_file_load(const char* filename); ``` csv对象可以从字符串文本中加载,也可以从文件中加载。加载成功则会返回一个csv对象,失败则返回NULL。 当csv对象加载失败的时候,可以调用`int csv_error_info(int* line, int* column);`函数进行定位错误。 错误类型包含 ``` #define CSV_E_OK (0) /* no error */ #define CSV_E_MEMORY (1) /* memory allocation failed */ #define CSV_E_OPEN (2) /* fail to open file */ ``` ### csv对象转储 ```c char* csv_dumps(csv_t csv, int* len); int csv_file_dump(csv_t csv, const char* filename); ``` 首先**csv_dumps**方法,将csv对象按格式转储为字符串。*len则是转换出来的字符串长度,传入NULL时候就是不获取长度。返回值则是转换出来的字符串,这个字符串是函数分配的,**在结束使用需要free掉**。 **csv_file_dump**方法则是在**csv_dumps**的基础上将csv转储到文件当中,filename传入文件名,返回值为转储的长度,负值表示转储失败。 ### csv获取行、列、单元格计数 ```c unsigned int csv_row(csv_t csv); unsigned int csv_col(csv_t csv); unsigned int csv_cell(csv_t csv); ``` 分别获取csv表格中的行列数以及非空的单元格计数。 ### csv深拷贝 ```c csv_t csv_duplicate(csv_t csv); ``` 根据源csv对象深拷贝出一份新的csv对象。 ### csv转数组 ```c int csv_to_array(csv_t csv, unsigned int o_row, unsigned int o_col, void *array, unsigned int row_size, unsigned int col_size); ``` 以[o_row, o_col]为起点,将(row_size, col_size)大小的选区内容转到array。 ### csv压缩 ```c void csv_minify(csv_t csv); ``` 该方法不会影响csv实际的存储内容,会将行末无效的空单元格去除掉,从而缩小存储空间。 ### csv设置单元格内容 ```c int csv_set_text(csv_t csv, unsigned int row, unsigned int col, const char* text); ``` 在(row, col)单元格覆盖性写入text文本,当单元格不存在的时候,也会新建单元格进行写入。 ### csv获取单元格内容 ```c const char* csv_get_text(csv_t csv, unsigned int row, unsigned int col); ``` 获取(row, col)单元格内容,返回NULL表示不存在这个单元格。 ### csv清空单元格内容 ```c void csv_clean_text(csv_t csv, unsigned int row, unsigned int col); ``` 清空(row, col)单元格内容。 ### csv插入行列 ```c int csv_insert_row(csv_t csv, unsigned int pos, const char **array, unsigned int count); int csv_insert_col(csv_t csv, unsigned int pos, const char **array, unsigned int count); ``` 在pos的位置插入行或列(pos为0时,默认尾插),如果指定array和count,则会把插入的行或列初始为array,count指定初始化的个数。 ### csv删除行列 ```c int csv_delete_row(csv_t csv, unsigned int pos); int csv_delete_col(csv_t csv, unsigned int pos); ``` 删除pos位置的行或列(pos为0时,默认尾删)。 ### csv移动行列 ```c int csv_move_row_to(csv_t csv, unsigned int pos, unsigned int dest); int csv_move_col_to(csv_t csv, unsigned int pos, unsigned int dest); ``` 将pos位置的行或列(pos为0时,默认尾删)移动到dest的位置。 ### csv复制行列 ```c int csv_copy_row_to(csv_t csv, unsigned int pos, unsigned int dest); int csv_copy_col_to(csv_t csv, unsigned int pos, unsigned int dest); ``` 将pos位置的行或列(pos为0时,默认尾删)复制到dest的位置。 ### csv插入单元格 ```c int csv_insert_cell(csv_t csv, unsigned int row, unsigned int col, int move_down); ``` 在(row, col)的位置插入空单元格,如果指定move_down为非0后面内容向下移动,否则向右移动。 ### csv删除单元格 ```c int csv_delete_cell(csv_t csv, unsigned int row, unsigned int col, int move_up); ``` 删除(row, col)的位置单元格,如果指定move_up为非0后面内容向上移动,否则向左移动。 ### csv复制单元格 ```c int csv_copy_cell_to(csv_t csv, unsigned int s_row, unsigned int s_col, unsigned int d_row, unsigned int d_col); ``` 将(s_row, s_col)单元格内容复制到(d_row, d_col)单元格。 ### csv剪切单元格 ```c int csv_cut_cell_to(csv_t csv, unsigned int s_row, unsigned int s_col, unsigned int d_row, unsigned int d_col); ``` 将(s_row, s_col)单元格内容剪切到(d_row, d_col)单元格。 ### csv查找 ```c int csv_find(csv_t csv, const char* text, int flag, unsigned int* row, unsigned int* col); ``` 在整个表格表格中查找`text`,匹配上单元格后返回1,匹配位置为(row, col)。查找到结束后,返回-1。 查找规则通过`flag`来控制 ```c #define CSV_F_FLAG_MatchCase (0x01) /* match case sensitive */ #define CSV_F_FLAG_MatchEntire (0x02) /* match the entire cell content */ #define CSV_F_FLAG_MatchByCol (0x04) /* match by column */ #define CSV_F_FLAG_MatchForward (0x08) /* match from back to front */ ``` ### csv遍历非空单元格 ```c #define csv_for_each(csv, row, col, text) ``` 按行从上往下遍历所有非空单元格。 ```c const char *text = NULL; csv_for_each(csv, row, col, text) { printf("[%d, %d]: %s\r\n", row, col, text); } ``` ## 参考例子 ### 生成csv文件 ```c static void dump_demo(void) { csv_t csv; const char *array[3][5] = { {"ID", "Name", "Gender", "Age", "Height"}, {"20240107001", "ZhangSan", "Man", "18", "178"}, {"20240107002", "LiSi", "Woman", "24", "162"}, }; csv = csv_create(3, 5, array); if (!csv) { printf("create csv fail!\r\n"); return; } if (csv_file_dump(csv, "info.csv") < 0) { printf("csv dump fail!\r\n"); } else { printf("csv dump success!\r\n"); } csv_delete(csv); } ``` 转储的文件 **info.csv** ```csv ID,Name,Gender,Age,Height 20240107001,ZhangSan,Man,18,178 20240107002,LiSi,Woman,24,162 ``` ### 加载csv文件 同样加载csv文件 **info.csv** ```csv ID,Name,Gender,Age,Height 20240107001,ZhangSan,Man,18,178 20240107002,LiSi,Woman,24,162 ``` ```c static void load_demo(void) { csv_t csv; csv = csv_file_load("info.csv"); if (!csv) { printf("csv load fail!\r\n"); return; } unsigned int row, col; const char *text = NULL; csv_for_each(csv, row, col, text) { printf("[%u, %u]: %s\r\n", row, col, text); } csv_delete(csv); } ``` 运行结果: ``` [1, 1]: ID [1, 2]: Name [1, 3]: Gender [1, 4]: Age [1, 5]: Height [2, 1]: 20240107001 [2, 2]: ZhangSan [2, 3]: Man [2, 4]: 18 [2, 5]: 178 [3, 1]: 20240107002 [3, 2]: LiSi [3, 3]: Woman [3, 4]: 24 [3, 5]: 162 ```