1. 程式人生 > >CSV格式特殊字元轉義處理

CSV格式特殊字元轉義處理

  • CSV是逗號分隔值(comama separated value)的縮寫,也有一說是字元分隔值。因為分隔符也可以是其他字元。
  • 當csv某個欄位中包含換行(CRLF)、雙引號、逗號(分隔符)時,整個欄位必須用雙引號括起來。例如:
"aaa","b CRLF
bb","ccc" CRLF
zzz,yyy,xxx
  • 當csv某個欄位用雙引號括起來且欄位中內容中還包含雙引號時,必須在該引號前面再新增一個雙引號進行轉義。
"aaa","b""bb","ccc"
// gcc main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define CSV_DELIM "," #define CSV_QUOTE "\"" #define CSV_QUOTE_CHAR '"' #define CSV_CRLF "\r\n" #define CSV_SPECIAL_CHARS ",\"\r\n" // 注意: // 1, 這裡假設escape buf足夠大,不會出現溢位問題 // 2, 並未考慮原始字串就已經被雙引號括起來的場景,如: "abc"這種可能已經不需要再加雙引號了
int escape_csv_string(char* escape_buf, const char* raw_data) { int found_special_char = 0; // 標識是否發現了雙引號、逗號、CRLF中的任意一個特殊字元 const char* first_non_quote_char = NULL; // 記錄“後面第一個字元的位置 const char* special_chars = CSV_SPECIAL_CHARS; int buf_used_len = 0; const
char* tmp_val = raw_data; while (*tmp_val) { if (!found_special_char) // 只要發現一個特殊字元,就需要在該欄位前後加". 後面就不需要再查詢特殊字元了 { for (const char* c = special_chars; *c; ++c) { if (*tmp_val == *c) { // 發現特殊字元,首先在整個字串前面加一個",並設定標誌位,以便整體遍歷結束後在尾部也追加一個" strcat(escape_buf, CSV_QUOTE); ++buf_used_len; found_special_char = 1; break; } } } // 如果特殊字元是",直接追加寫進去兩個"" if (*tmp_val == CSV_QUOTE_CHAR) { if (NULL != first_non_quote_char) { // 發現"後,首先將上一個"之後到這個"之前的部分拷貝到buf中 strncpy(escape_buf + buf_used_len, first_non_quote_char, tmp_val - first_non_quote_char); buf_used_len += tmp_val - first_non_quote_char; escape_buf[++buf_used_len] = '\0'; } buf_used_len += 2; strcat(escape_buf, CSV_QUOTE); strcat(escape_buf, CSV_QUOTE); first_non_quote_char = NULL; } else { // 記錄第一個非"字元的位置 if (NULL == first_non_quote_char) first_non_quote_char = tmp_val; } tmp_val++; } if (found_special_char) { if (NULL != first_non_quote_char) // 最後一個字元是" { strcat(escape_buf, first_non_quote_char); } strcat(escape_buf, CSV_QUOTE); } else // 說明字串中沒有特殊字元 { strcat(escape_buf, raw_data); } return 0; } int main(int argc, char* argv[]) { while (1) { printf("\nplsese input a string:\n"); char input[1024] = {0}; scanf("%s", input); char output[1024] = {0}; escape_csv_string(output, input); printf("After escape: s\n", output); } return 0; }