最近搞了电网的I1协议,其中涉及图片数据,包比较大,分了20包,每包5K大小,远程写的解析代码,没有连接真实设备测试,所以要了一些报文,奈何报文全是16进制字符紧挨在一起,没有合适的分割工具,只好自己写个了。
将以下代码保存为split.c
/** Includes -----------------------------------------------------------------*/ #include <stdint.h> /**< need definition of uint8_t */ #include <stddef.h> /**< need definition of NULL */ #include <stdbool.h>/**< need definition of BOOL */ #include <stdio.h> /**< if need printf */ #include <stdlib.h> #include <string.h> #include <errno.h> /** Private includes ---------------------------------------------------------*/ #include <fcntl.h> #include <unistd.h> #include <ctype.h> /** Private defines ----------------------------------------------------------*/ #ifndef OUT_FILE_NAME #define OUT_FILE_NAME "default.file" #endif /** Exported typedefines -----------------------------------------------------*/ /*文件打开权限*/ typedef enum { READ_ONLY = 0, READ_WRITE_ONLY, WRITE_CREAT_CLEAR, READ_WRITE_CREAT_CLEAR, WRITE_APPEND_CREAT, READ_WRITE_APPEND_CREAT, }FILE_OPEN_MODE; /*文件分割方式*/ typedef enum { SPACE_SPLIT = 0, COMMA_SPLIT, }FILE_SPLIT_MODE; /** Exported constants -------------------------------------------------------*/ /** Exported macros-----------------------------------------------------------*/ #define PRINT_ERRMSG(STR) fprintf(stderr,"line:%d,msg:%s,eMsg:%s\n", __LINE__, STR, strerror(errno)) /** Exported variables -------------------------------------------------------*/ /** Exported functions prototypes --------------------------------------------*/ /*返回指定文件是否存在*/ int file_is_exist(const char *fimename); /*打开指定文件返回文件描述符*/ FILE *file_open(const char *filename ,FILE_OPEN_MODE mode); /*读取指定打开的文件,返回总行数*/ int file_get_line_cnt(const char *filename); /*读取指定打开的文件指定行的内容到缓冲区*/ size_t file_read(const char *filename ,char *destbuf ,size_t size ,int linenum); /*替换字符*/ size_t file_replace_ch(char *sourcebuf ,char sourcech,char destch); /*清除字符串空格*/ char *strtriml(char *pstr); char *strtrimr(char *pstr); char *strtrim(char *pstr); /*清除文本中空格,忽略注释标识行*/ bool file_strip_comments(char *string, char comment); /** ****************************************************************** * @brief 判断文件是否存在 * @param [in]fimename 文件名 * @retval 返回0文件存在 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ int file_is_exist(const char *fimename) { return access(fimename ,F_OK | W_OK | R_OK); } /** ****************************************************************** * @brief 打开指定文件返回文件描述符,追加模式下fseek(fp, 0, SEEK_SET)无效 * @param [in]fimename 文件名 * @param [in]mode 打开文件的模式选择 * @retval 返回0文件存在 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ FILE *file_open(const char *filename ,FILE_OPEN_MODE mode) { FILE *fp = NULL; switch(mode) { case READ_ONLY: fp = fopen(filename ,"r"); break; case READ_WRITE_ONLY: fp = fopen(filename ,"r+"); break; case WRITE_CREAT_CLEAR: fp = fopen(filename ,"w"); break; case READ_WRITE_CREAT_CLEAR: fp = fopen(filename ,"w+"); break; case WRITE_APPEND_CREAT: fp = fopen(filename ,"a"); break; case READ_WRITE_APPEND_CREAT: fp = fopen(filename ,"a+");/**< 首次读取时,从文件头部开始读*/ break; } return fp; } /** ****************************************************************** * @brief 打开读取指定打开的文件,返回总行数 * @param [in]fp 文件指针 * @param [in]filename 文件名称 * @retval 返回-1读取失败 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ int file_get_line_cnt(const char *filename) { int cnt = 0; char buf[256]; FILE *fp = file_open(filename ,READ_ONLY); if(fp == NULL) { PRINT_ERRMSG("fopen"); printf("read file name :%s error.\n" ,filename); return -1; } char *ret = NULL; /*读取文件流中的内容*/ while((fgets(buf ,256 ,fp)) != NULL) { ret = strchr(buf ,'\n'); if(ret != NULL) { cnt++; } } /*关闭文件*/ fclose(fp); return cnt; } /** ****************************************************************** * @brief 读取指定打开的文件指定行的内容到缓冲区 * @param [in]filename 文件名称 * @param [in]读取到的数据存储区 * @param [in]限制长度 * @param [in]需读取的行 * @retval 执行结果,读取到字节数 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ size_t file_read(const char *filename ,char *destbuf ,size_t size ,int linenum) { int cnt = 0; char buf[1024]; /*初始化缓冲区*/ if(strlen(destbuf) > 0) { destbuf[0] = '\0'; } /*打开文件流*/ FILE *fp = file_open(filename ,READ_ONLY); if(fp == NULL) { PRINT_ERRMSG("fopen"); return -1; } /*读取文件流中的内容*/ char *ret = NULL; size_t len = 0; while((fgets(buf ,1024 ,fp)) != NULL) { ret = strchr(buf ,'\n'); if(ret != NULL) { cnt++; if(cnt == linenum) { if(len == 0) { strncpy(destbuf ,buf ,1024); if(size > 1024) { destbuf[1024] = '\0'; } else { destbuf[1023] = '\0'; } } else { /*追加字符串*/ len += strlen(buf); if(len > size) { break; } else { strcat(destbuf ,buf); } } fclose(fp); return strlen(destbuf); }//cnt == linenum } else { /*判断是否超出缓冲区大小*/ if(cnt == linenum-1) { /*目标缓冲区过小直接退出*/ if(size <= 1024) { break; } len = strlen(destbuf); if(len == 0) { strncpy(destbuf ,buf ,1024); destbuf[1024] = '\0'; } else { /*追加字符串*/ len += strlen(buf); if(len > size) { break; } else { strcat(destbuf ,buf); } } } } } fclose(fp); return strlen(destbuf); } /** ****************************************************************** * @brief 写入指定的内容到文件 * @param [in]filename 文件名称 * @param [in]buffer数据存储区 * @param [in]size写入的元素占总字节数 * @param [in]count写入元素数目 * @param [in]mode文件写入模式 * @retval 执行结果,写入元素的总数 * @author aron566 * @version V1.0 * @date 2020-10-09 ****************************************************************** */ size_t file_write(const char *filename ,const void* buffer ,size_t size ,size_t count ,FILE_OPEN_MODE mode) { /*打开文件流*/ FILE *fp = file_open(filename ,mode); if(fp == NULL) { return 0; } size_t cnt = fwrite(buffer ,size ,count ,fp); /*同步到文件中*/ fflush(fp); fclose(fp); return cnt; } /** ****************************************************************** * @brief 替换目标字符串中字符 * @param [in]目标字符串 * @param [in]源字符 * @param [in]目标字符 * @retval 执行结果,当前字符长度 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ size_t file_replace_ch(char *sourcebuf ,char sourcech,char destch) { int i; i = strlen(sourcebuf) - 1; while (sourcebuf[i] == sourcech && (i >= 0)) sourcebuf[i--] = destch; return strlen(sourcebuf); } /** ****************************************************************** * @brief 去除字符串右端空格 * @param [in]字符串指针 * @retval 修剪后的字符串地址 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ char *strtrimr(char *pstr) { int i; i = strlen(pstr) - 1; while (isspace(pstr[i]) && (i >= 0)) pstr[i--] = '\0'; return pstr; } /** ****************************************************************** * @brief 去除字符串左端空格 * @param [in]字符串指针 * @retval 修剪后的字符串地址 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ char *strtriml(char *pstr) { int i = 0,j; j = strlen(pstr) - 1; while (isspace(pstr[i]) && (i <= j)) i++; if (0<i) strcpy(pstr, &pstr[i]); return pstr; } /** ****************************************************************** * @brief 去除字符串两端空格 * @param [in]字符串指针 * @retval 修剪后的字符串地址 * @author aron566 * @version V1.0 * @date 2020-08-28 ****************************************************************** */ char *strtrim(char *pstr) { char *p; p = strtrimr(pstr); return strtriml(p); } /** ****************************************************************** * @brief 去掉字符串内所有空白,且忽略注释部分,最终得到没有空白的字符串 * @param [in]string:字符串 * @param [in]comment:注释标识 * @retval true表示数据可用 * @author aron566 * @version V1.0 * @date 2020-08-31 ****************************************************************** */ bool file_strip_comments(char *string, char comment) { if (NULL == string || '\n' == *string || '\r' == *string) { return false; /* 第一个字符为回车或换行,表示空行 */ } char *p, *q; /* 下面去掉字符串中所有空白字符 */ for (p = q = string; *p != '\0' && *p != comment; p++) { /* 不是空白字符则重写字符串 */ if (0 == isspace(*p)) { *q++ = *p; } } *q = '\0'; return 0 != strlen(string); /* 字符串长度不为0,表示数据可用 */ } /** * @brief 16进制字符转为数值 * * @param ch 16进制字符 * @return uint8_t 数值 */ uint8_t hex_char_to_value(uint8_t ch) { uint8_t result = 0; /*获取16进制的高字节位数据*/ if (ch >= '0' && ch <= '9') { result = ch - '0'; } else if (ch >= 'a' && ch <= 'z') { result = ch - 'a' + 10; } else if (ch >= 'A' && ch <= 'Z') { result = ch - 'A' + 10; } else { result = 0; } return result; } /** * @brief 将大写字母转换成小写字母 * * @param ch 大写字母 * @return uint8_t 小写字母 */ uint8_t ch_tolower(uint8_t ch) { if(ch >= 'A' && ch <= 'Z') { return ch + 'a' - 'A'; } else { return ch; } } /** * @brief 16进制的字符串转换成整数 * * @param s 16进制字符串 * @return int 数值 */ int hextoi(char s[]) { int i = 0; int ret = 0; if(s[0] == '0' && (s[1]=='x' || s[1]=='X')) { i = 2; } else { i = 0; } for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i) { if(ch_tolower(s[i]) > '9') { ret = 16 * ret + (10 + ch_tolower(s[i]) - 'a'); } else { ret = 16 * ret + (ch_tolower(s[i]) - '0'); } } return ret; } /** * @brief main入口 * * @param argc 参数个数 * @return argv[] 参数 */ int main(int argc ,char *argv[]) { if(argc < 4) { printf("Usage:%s filename strlen split_num\n" ,argv[0]); return -1; } int buf_len = atoi(argv[2]); char *strbuf = (char*)malloc(sizeof(char)*buf_len); if(strbuf == NULL) { printf("malloc error!\n"); return -1; } memset(strbuf ,0 ,buf_len); /*打开文件*/ FILE *fp = file_open(argv[1] ,READ_ONLY); if(fp == NULL) { printf("can't open file.\n"); return -1; } /*读取文件内容*/ char txt[64] = {0}; while((fgets(txt ,64 ,fp)) != NULL) { /* 去掉字符串所有空白,注释也忽略 */ if (file_strip_comments(txt ,' ')) { strcat(strbuf ,txt); } } int split_num = atoi(argv[3]); uint8_t temp = 0; for(int i = 0;i < buf_len;) { #if defined (ENABLE_PRINT_CH) if(i < split_num) { printf("%c%c" ,strbuf[i] ,strbuf[i+1]); } else { printf(" ""%c%c" ,strbuf[i] ,strbuf[i+1]); } #endif #if defined (ENABLE_OUT_FILE) temp = hex_char_to_value(strbuf[i]); temp <<= 4; temp |= hex_char_to_value(strbuf[i+1]); file_write(OUT_FILE_NAME ,&temp ,1 ,1 ,WRITE_APPEND_CREAT); #endif i += split_num; } return 0; }创建一个文本a.txt填入内容
a55ae513563030303030313230323031343139303405cd8401ff13000b00000000003dda000081114a7d029f6222af9128b340983d36b34a24cac4bd2a0b196a6338d19c288956cf0d090bf6533d20a4f95139c03992e83790219c45bea5ba0058790108b3ed380433b1399a22c9d3f7d2d00e9e00a12aebe12042421ea84481b26817db938633a33c410a4143fa7d1e99100e1e8a70d2a5038528053493d510ba4d2fd1281c4ef161413d5d2501606f60a52d21c03f433d00fd16b20bd3e8fc201d2545a21949b1602717d38634068ff674804da70e657a06b04d2756cc01cc16953ec059984f69d03468399d01a3191282e8d14d500ba3f1282c4e61764ce40e84cc2c0116c3d15168680c6116cc689a110dfc2f0e8129845d403bd3467863f40e69287417fd144034422e8105201d244fc5f281e94b9c920a7a756f8990165da6979c0339885d801a2806788bdc6504526618e17ec10520245c6900c5d103c15174808b4ea7abc0a922d84a98c6c16a676b369d059524caf0941081d02acf499c6d3d0589fa53d06995a811769bcaf387d8438917d4c82c9921b2cc8210017896a2e005fd4bb50424cad33b03c416fc822f0f48287b7a267802ed2af3d1121dcacd9aa044b05c022e31e9346c31a9364a96ad88daeb09a4d80ba88b0d88994f17d405f0e84d806a93280b700700e643f4d505fa4cf8b09e0a7d27f1738c613d05d44ba85a02d4d45bc4c885f8328bc03b845f32772b43ece174206304c7826340d6b1845ace81758136b54089fabe822de1e7108296e7687a82f0213404c10f71a5901286804319daf531980d567d5405f117080ba4cc5f139901af6e100543c5ce6cc0a9a4f579d2dc88245a77aa89e2c225fa41758fc4b8c028baca6972950593a9a29f6a2e0b7294a0a90cecfa021e1b00ba2e61b00f85d245209d589c5a082d4c6622afa42d2d0152fc1410ee57280ba25e218c81fec5fbc2598031d5897e96e73a0329ea8069339aa49e82787bc3c1517594ba5c24fb40f43f1146ba7129d05c6516c2d411719fa4505b86739a5b800b8c1562550a10e022f52ae2c10e19380b115167d81e0b1380b705c22e013dda2fa7a08bd3d2e843459988bff607aba4c7d9416a1165c0a9742c4a0161499a14a52148515305002c282e369c5f3592d0487a74a06bc4b72a5c081f28be0ab49a4ab71e209f85d85ce72a1f6545e0070b4a05dadd26367017f326b09a0173224318a7d7a02dd080019c403c4fe2e008a9420157984bb280529fa42ad85c32a14b929e900e9c4505ba4c117809bd8bf69dc805387807d95644fa00a2d9bc02502001f493f4414b345d80644154c10e016148a05f82fca2dc209c339a134053fe88289c5a4bd26c44fd5f49a4e0286d055542ec0a689b26843990ea02d422822f3111a04a521055e61152a068d10f540fb3d00bb32802db84fe1f8a21dea59959a202745f13d05c64bb4972505b345d22c045ee088055a7a80b4a99503ef075140d22dc44e82a75669202d348b40bb34202d2443f416af89d3c14d1e07806b26fd404d5d1fc45a05c7c14ba3809421a05ef152fc250586b21fc039a318a6d01758c94fa20255385d8161fd3d4b320a54de415559ab74140a700a5d953b9e88ba09bd9980216654045e928b10e2c3808b761c0328a77a26a2d09b042ae49a02d2632630700c94eac980657086340d65252808ba3d2822929cc8a615347404160169939828229a49a10c90b54122e8f09b04ee57f4e1c0222dd1f6070b53f5aa097097190d80001b8b83801348b4b7206325da632601a8054697f52ada806f253ec9f001a2900b82c101ab84a98cc5c640ab6e50ed03a26d60299ced2c2ec55ef53390bb046b133d6566445e2484fb33802989e9ca01ac09d500ce4fa405f0894a0673550516e0bf485d01f79caa774a2267a74ce0f01ae33e957ec05cb3eaa2ae93393f85b804fd59f4977b51008705087501a4ea2d033a2eca80a78802dd22a019fb2dd05ce151644a5c9905c19ca5984be8550f405e93054bf20b318c5225ba2fd20454bbd1d517cfb4c14a0b7425300b9d22e6f7298c50385f83c000abbf3d0417288aba8200bd3094011a9c39ac2a2717f12eca0bf897e4b4f002c45054f4b92e7a0bba9e820bf44d22e32a2732a9765c82a68a6f391054a82adf92fc0502f565f10d808a503a14c804d80117894bb05ef4fc4ab9de2a0652d339d15453f894b71b05b0b59017ff47dafe24d817356d4e99bf821f41e801e9729720b4a9e2d05b532100c616ee25994bb05356153f40be459a21404a00aa94e817fa1c4a0b77a3a9f4bc00ce7e12ecde41688b7415749c37f45d8b4bb090fb0a4df02ecbf4213d45b40307385fa01689d2e85a534140b0bf45d806cfd2a50aa64fb2d0a7d8633a86c427b09787334a0438972bf607a53d4a0bf65fa2a02df83da59e28a5f53a5d1c046bacad0589ed29761a52cc2173911697452fa091aacdab9c0193ce21805fa0fe82949b45a214a54054abfa9fc05a77d0157290e17205f0da17d11787bb4016ecea5f143045f505d5e6705d182ec4365d19c9d03a7a5f0cdc0177a2a1c05a54b4dd0aa612aec55a949b4f42a8962dba0a2d984fc2d12951668030258b7e80fa3d4f2ad02448bf45d82c984a7eed2ec16d459ac653a0be9f48be700f04e9c03aa9bc1416693c5b004feaf890e02f849b0b980789dcf0ab678067079b133a05fe2cf12eb650a2a53c169d2fc1e9a10fea2e7273a064d44b9282f88bd4e02e7f10b767e0176b50c034cd9958022d89c3a05b17cbea400a1c282dd9d39b4bb059845a5b9e0255ee50d02c4a52ec14d26fa02cf56b3bc2f8182ff00527d829ead64052e3d3a481522e92f8744586ec2e71836068a672502fc27fdad4be02fe0585f013eca2c805f0e200bd348505fc34802f4f11668054d1742aa7ab77c4f8c0264c2e78944016504f14e60b00cd3f4a50345fa49b5805a78420267385b10cf40b8c88a07dae3277a7d40219c2cfb4c8263ab13d5bad02cde93ddad3b946cc195e7533b10814ba0267e05bf1933fec121e2ef3a59815982e71889910fe22c35800d9858099d74c13c5c60127a4fb5841595c6567f12405ca4d2e3370b7180605b834221d598c131d022469338fb04e91ac60ce3ed519ce206a2cc024ce49b6bf1338c52898c7abfa459ad833e18cccd59a27c81d4ce0e7abaca0445d13609b22c2020d33a0161165151318aa700b0e94a04ca7ad54d504584c550648b70614662cd3513ce889346f0be268349c3d5893e443a1a24c8a6ec3b9597d2631cd81226702df841210c662f5422459f24b941082ebe544f11afb4f417f89bc6569f8824b95e64b0e81946a1a15927d2e8d40222ff007279044b985598f94d01a82ebe4e026cce0eae94657ea1a6b40cc3aa008d63644548131827d827727abc3f32232a45513ab0c61758f504d7c22e7f5141487e8248b9c433bc74a8243a2cc02402284d935b699d4402e70b3078a2740fb129b2417584549764dad9c0139927d2f7d45088ba34224daf7c218c01f67bac17063209c58bac9318c0322f8b3009116e0d01f782e3e149399287522c4e64a248b2acc54049b6b06b1a0133822f89a0222fe2cf0121cfd5e7a77a093e5265a9f66b209332a4cae7a5c700318ce4d1670164485c53d04d78b8fc3f48022cd68c63ec124caf42807f175f20acc169a1084598c64980499ce49f47abf4513ecfb5ee13450a8b218c01368d4c19c404d92a9c4589ea6f2d6708a421f4baf92e01384f95d7c882670b8d1d3e81358213193c54d33845f0d027ab739347e02a64a026d4d018b3e517a0a9339c922e789ff626a1bcafd2c0678ab30920211ad2500347e0108b7e4b804e2356a7bbc0245e689b5f45484526b40cacd1010c60de3c5c652dca09eed4b8c0a26d66c3f410c62b5138090fc5e1dc8194e3513407482821f8787d007d07413a4ab3d013f82fa9d03ab0a504a1e2e8099c8b3ed39d031821f802422a00bd2e309f804c9b5ff6bc04892e5aa93140e1287380936b9e8681176008b09859700cff0017be121412784caf4fe822f48700ce138b69e826fa0a04ce490ce4fd04dae000bf29f6b984d6c13a4d2c5ba0489868e0244584c7c81dd2670d4fb2033e2c9838024ded643a00482f80caff00e89a3ec122c0c4170911b498c820b3ed0a438a9eadc044c90e9f4224c9569904a459a00f0ce16690108ba506618c5164f4130b9c6516dc03235304c4ff00d824abc39e9cd81d4fb5b4e020bd00ee385340264166813a7e346b209099e1f8771a04ab821f8070f4ba2fc81dc9c5890587da4f571d5ce268226708b3ecd089c2657eea6fc06a99e24fb59ae827a5868a0a599e2e77b4ee51b5b52538d63b019c61718f9c55bba5049f096accff000038b6b36971c06ac67a5dacb9ff00f6093fec9f0b9d2086f0bdca5f326f00b26ca5f9405a752ecdd14ffb1171910fc45d100268b16825cf0ce4bbd267a0a7d98f82c116fca6739f3099cad045c64c6f440289614178b9f966adc285fb3be22e0820b369f281b3fecbf4550e17daa9f48157a9e80a45a98c808b718ca02cca0b6814c602e453995950a026f0b8cfc97008b3464aa88a5d25ba80bdd4389fdd98ce4436baa94ee5156e3053cda63300d9a5bf29ab905fc2c4b16d02e497ff00e96201366f0b4a06e24dadd20133c3995d61150f4a1c154fc3192fda08bd4282fd9fa957f4084a43fbc0482d4802e71a3f0ee3407e816f281bce341828abc3bd4a505b50b8281f8855eaa26d61f8633f282e33f281409726f3c2e0fb1536a74f32225d267357c14d31d3a7d2ef18113761b16a29e7ea2a5d82cc99ca55ea8c9bce0319d88b8a6c5bf62876ecba30818ea673e14ee14436bc2dd0879fa1c50426dafb668173eaa55e024de9798339d320d693d29e9033af4f8294806d6c4a819c9765b84e78a2a95282ff0013c85fb2ef604d18cc5a9416a534017394590804f82001214ba40587a55fb0369cdada973e818abbf12a5053c29403653f40e6122d8680c657f195e01ed2fd2ed906b7129699e81b3ecfb3c0152fc173416a2f524ea2aee24295458228218d9737450ab3d4b0bf26b2156a74e1742133c3a500d9333452c008a97608b670e9430d8be08a9d4bb6afa9d54d0a52e816d3a9765d02a67a5a500e64f52ec153ab4b737390116a03494a5017794eaee22d486f0b728a87abfd4bf05d01d3852ec13198a6b2966816a7e9c5dc037c0c6568184ce2e4b000d9616e4021c4a04f17bc298e6601b2e7e0ba5e833d59a378c8043214049e8be402e7e438740a1403c87870e81a4500b0b427a0173c0b3206e74e96976070f1166b60078502fc174957f40e9c29c0366ca9320bbc642940fb3a54bb05972b52c4a043b727e141abae27a6325045de30785d02ca67112e4ce681d4de3263317a05367a505a9b5c1714133816a78085deca0297395f19b320b0297340abdc268be01e9c3c5452e936b52a8a87727a08b1179b10e274a505b0f53b9360d1f8973ead04c85d2505f4ea55c640de3f0e89682d290026724cc4ab41245f0ce50171c4b95a9e80b27522f00e17667280bb9537e2f4a094a136074ff652ec17366cc68a514f57e53be0810ce76b9cb3545e9ea5c9dc08b117e8bb02e0ba3313201f5859f692641bfe9117711b4f92af899d02dce345de0ef4a05431959412132b61d1195a99e9ea867376bfc45e6043863a9f8b3d156245b787503f32485c1413f70670b27ea026314f74d6a6d35f60713c9f6b69c113df93388bf6022f7d2632451218e8b009b339a8b202169e9e80bacf10c02fe112e296f014fcc983550427caf10153c5ceb10b1426ce6529b038b12e72be207122f4027da2fea017fa10936a18e9ccae3858827abff61412e88b949b5148998bd02619b32d77093621264e756ed6c456664b9c17abd02d499c2e309360559fe5318a28743198bace3a82730ba84d7500dacf949f0281c16044f5624504d2cd916a09f5ea45e808bd484aa2ca93385b0ee100eff10805c1b845ba03e8b348b010f4f0e28a95652208426d62891644c45d60116f8549b4171b3c21013b96a4da2d99153d2153d80422f1159d21d2202f321166052a67ab04105f9a975a03584a4ab34a84bc590e60a29cf0fe92910227e2f524e81e909f255446ad4cf801667e00d7009a4be2f126c16e8e9c00f4ee4976807b57a0044b8f86a6ba93c809c3c1a9ad8277068e1fa09fabf64d80680808d71387ba02ec09a03eb868ef4a06887fb201f8784d1281622c3e80e908b8e019c78866e480526c913fd82dc24cf57ecc700f1767e2598805d24df56e8b4089c3f166681fc27daf004903680b8c4f56e268359809a2f800926561ba017643d250213e0fe0022fd133804e34cc50389f82cd007a9f8d4809f88bc27c814228218e9e9cc81cf0526b40cebc526719e2c04f4d94f7605f8c94cf4808b26e90e809f4b9d1e0270995a5d01cd9bc98fb00da4f5af1267808b364990098c1f64b84de00b165fd21009131a37826c171538b09a05efda66608a09e23533f9aa9009f0498fb0045b8437905fb3e61b27c022dda673b3c05fb27a4e1e740f4b8f84ab3608b027c013b0fe18282754d60ba04ddab75a4504d4fb5ea4594045e1dc81e025053a7779201e27d29a0222f0c81e24f9cafe9de01a3c210088b3e08085daed201a3a10086711710c821031c05d9e14e0134955202f4e18c1f809f8b0f4ccc815059f00684d2e300917c33d34073082e809f2971d597080bea1005f3e09e9f89b03a5267185a0972bb0042eb8b14199e954021346cfd02a6d73840374993d5048b0e9ce824995bf67f746413d59769e2f41058022c22007daf3a4f804de4ce4f0990171b4f346005aace40c2f596bfe81327e2fe809d38ab013ec3e8ef05a5458821b54c7aa07a9eafa801845053f42e202e3ed6cca6c4696a5d1b3390a52a2c02e70521900bc0036710e88bae271669318aa2d2dc98c12229aa5d1f6641148016e4a26817a957099c00b134b7530a852f87f0c61013792cce850d45de22528349509a05ba422827f0cac35413a8d6b09aa0b4bf09b5e8255fc48a4045cc8c82f1a66af3d0268fd45a81cf0a6f24c2c0a5f0a7fd817e44ca0357e131da6971940a9ec5984d01ec5b53d5b14398d97152dcef26834b8c99cfd22887a5da2cf7d696 #使用 ./test a.txt 10240 2