58_fread()和fwrite()

使用fwrite与fread进行文件读写
本文介绍了一个简单的C++程序实例,演示如何利用fwrite函数将整型、长整型及浮点型数据写入文件,并通过fread函数读回这些数据。程序首先定义了三个不同类型的变量,然后打开一个名为test.txt的文件,在写入数据后重新读取并打印出来,验证数据的一致性。
//_58_fread()和fwrite()
//_58_main.cpp

//用于向文件中读写长于一个字节的数据类型

#include <stdio.h>
#include <stdlib.h>

int main()
{
	FILE *fp;
	int i = 156;
	long l = 9701076l;
	double d = 3.456;
	if((fp=fopen("test.txt","w"))==NULL)
	{
		printf("不能打开文件\n");
		exit(0);
	}
	printf("i = %d\n",i);
	printf("l = %ld\n",l);
	printf("d = %f\n",d);
	//通过fwrite函数,将数据写入文件
	fwrite(&i,sizeof(int),1,fp);
	fwrite(&l,sizeof(long),1,fp);
	fwrite(&d,sizeof(double),1,fp);

	rewind(fp);
	
	//通过fread函数,将数据读出文件
	fread(&i,sizeof(int),1,fp);
	fread(&l,sizeof(long),1,fp);
	fread(&d,sizeof(double),1,fp);
	
	printf("i = %d\n",i);
	printf("l = %ld\n",l);
	printf("d = %f\n",d);
	
	fclose(fp);
	
	system("pause");
	return 0;
}

bool tpsocket_event_filelog_to_hub(struct tpsocket_handler *handler, struct list_head *buf, int event) { struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); FileLogSession *session = handler->priv; if(!session){ return false; } int decrypt_flag = session->decrypt_flag; struct tpsocket_buf *nbuf = NULL; FILE *fp = session->fp; if (!fp) { DBG_ERR("File pointer is NULL, cannot write\n"); return false; } int remaining = session->remaining; char *filepath = session->filepath; DBG_ERR("sock=%p, event=%s\n", sock, tpsocket_event_name(event)); switch(event) { case TPSOCKET_EVENT_LISTEN: DBG_ERR("TPSOCKET_EVENT_LISTEN: %s:%s Listen\n", sock->addr, sock->port); break; case TPSOCKET_EVENT_SHUTDOWN: DBG_ERR("TPSOCKET_EVENT_LISTEN: %s:%s Shutdown\n", sock->addr, sock->port); break; case TPSOCKET_EVENT_ACCEPT: DBG_ERR("TPSOCKET_EVENT_LISTEN: %s:%s Accepted\n", sock->addr, sock->port); break; case TPSOCKET_EVENT_CONNECTED: DBG_ERR("TPSOCKET_EVENT_LISTEN: %s:%s connected\n", sock->addr, sock->port); break; case TPSOCKET_EVENT_REQ_HEAD: DBG_ERR("TPSOCKET_EVENT_LISTEN: %s Requested path: %s\n", sock->path, sock->parser.http.url); break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_SUB_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_MESSAGE: nbuf = tpsocket_merge_buf(buf); if (!nbuf) { DBG_ERR("Failed to merge buffer\n"); break; } unsigned char *input_data = tpbuf_data(nbuf); bool error = false; int input_len = tpbuf_data_len(nbuf); DBG_ERR("input_len:%d", input_len); if (decrypt_flag) { DBG_ERR("+++++++++++++++++++++++++++++"); int decoded_len = tpsocket_base64_decode(input_data, input_len, input_data); if (decoded_len < 0) { DBG_ERR("Base64 decoding failed\n"); error = true; } DBG_ERR("tpsocket_base64_decode\n"); // unsigned char *plain_data = tpbuf_data(nbuf); // if (!plain_data) // { // DBG_ERR("Memory allocation failed for plain buffer\n"); // error = true; // } int plain_len = decoded_len; if (remaining > decoded_len) { remaining = decoded_len; DBG_ERR("decode session->remaining:%d\n", remaining); } unsigned char *plain_data = calloc(plain_len, sizeof(unsigned char)); work_tapo_log_decrypt(tpbuf_data(nbuf), decoded_len, plain_data, &plain_len); DBG_ERR("plain_len:%d\n",plain_len); // 写入解密后的内容 if (fwrite(plain_data, 1, plain_len, fp) < plain_len) { DBG_ERR("File write error after decryption: %s\n", strerror(errno)); error = true; } else { const char newline = '\n'; if (fwrite(&newline, 1, 1, fp) != 1) { DBG_ERR("Failed to write newline character: %s\n", strerror(errno)); } remaining -= plain_len; } } else { if (fwrite(input_data, 1, input_len, fp) < input_len) { DBG_ERR("File write error: %s\n", strerror(errno)); error = true; } else { const char newline = '\n'; if (fwrite(&newline, 1, 1, fp) != 1) { DBG_ERR("Failed to write newline character: %s\n", strerror(errno)); } remaining -= input_len; } } DBG_ERR("session->remaining: %d\n", remaining); // 传输完成处理 if (remaining <= 0 || error) { if (fp) { fclose(fp); session->fp = NULL; } char resp[256]; if (error) { snprintf(resp, sizeof(resp), "HTTP/1.1 500 Internal Error\r\n" "Connection: close\r\n" "\r\n"); } else { snprintf(resp, sizeof(resp), "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 0\r\n" "Connection: close\r\n" "\r\n"); } struct tpsocket_buf *resp_buf = tpbuf_snprintf(strlen(resp) + 1, resp); if (resp_buf) tpsocket_write(sock, resp_buf); // if (error) unlink(filepath); // if(session){ // free(session); // handler->priv = NULL; // } } // tpsocket_close(sock); break; case TPSOCKET_EVENT_STREAM: return true; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_TIMEOUT: break; case TPSOCKET_EVENT_CLOSED: DBG_ERR("TPSOCKET_EVENT_CLOSED\n"); if (session != NULL) { // 异常关闭时清理资源 DBG_ERR("entering TPSOCKET_EVENT_CLOSED\n"); if (session->fp) { fclose(session->fp); session->fp = NULL; } unlink(filepath); free(session); handler->priv = NULL; } tpsocket_close(sock); break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; }if (!strncmp(sock->parser.http.url, "/diagnose_log/set", sizeof("/diagnose_log/set"))) { if (false == worker_file_log_set_handle(handler->priv, sock, buf)) { tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return false; } }bool worker_file_log_set_handle(WORKER_CTX *worker_ctx, struct tpsocket_fd *sock, struct list_head *buf) { // 1. 获取设备MAC地址 char *mac = common_find_key_from_buf(buf, "Device-Mac"); if (!mac || strlen(mac) < 12) { DBG_ERR("Invalid MAC address\n"); return false; } DBG_ERR("mac: %s\n", mac); // 2. MAC格式化处理(冒号转下划线) char processed_mac[18] = {0}; strncpy(processed_mac, mac, sizeof(processed_mac)-1); for (char *p = processed_mac; *p; p++) { if (*p == ':') *p = '_'; } DBG_ERR("processed_mac: %s\n", processed_mac); // 3. 创建目标目录 char dirpath[128]; snprintf(dirpath, sizeof(dirpath), "%s/%s", FILELOG_PATH , processed_mac); // 检创建父目录(/mnt/sd_card) if (access(FILELOG_PATH, F_OK) != 0) { if (mkdir(FILELOG_PATH,0755) != 0) { DBG_ERR("SD card mount failed: %s\n", strerror(errno)); return false; } } // 创建设备目录(/mnt/sd_card/<processed_mac>) if (access(dirpath, F_OK) != 0) { if (mkdir(dirpath, 0755) != 0) { DBG_ERR("Device dir '%s' creation failed: %s\n", dirpath, strerror(errno)); return false; } } // 4. 构建文件路径 char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/log.txt", dirpath); DBG_ERR("filepath: %s\n", filepath); // 5. 获取内容长度( char *content_length_str = common_find_key_from_buf(buf, "Content-Length"); if (!content_length_str || *content_length_str == '\0') { DBG_ERR("Missing Content-Length header\n"); return false; } size_t content_len = atol(content_length_str); if (content_len <= 0) { DBG_ERR("Invalid content length: %s\n", content_length_str); return false; } DBG_ERR("Content-Length: %zu\n", content_len); // 滚动写入 FILE *fp = fopen(filepath, "ab+"); if (!fp) { /* 错误处理 */ } fseek(fp, 0, SEEK_END); long file_size = ftell(fp); // 处理超大数据特殊情况 if (content_len > MAX_FILELOG_DIR_SIZE) { DBG_ERR("Unable to free sufficient space\n"); const char *resp = "HTTP/1.1 507 Insufficient Storage\r\n\r\n"; struct tpsocket_buf *resp_buf = tpbuf_snprintf(strlen(resp)+1, resp); if (resp_buf) tpsocket_write(sock, resp_buf); return false; } // 循环删除行直到空间足够 while (file_size > 0 && file_size + content_len > MAX_FILELOG_DIR_SIZE) { rewind(fp); long line_start = 0; long line_end = 0; // 增强行定位:逐字符扫描换行符 int ch; while ((ch = fgetc(fp)) != EOF) { line_end = ftell(fp); if (ch == '\n') { // 找到完整行边界 line_start = line_end; // 检查剩余空间 if (file_size - line_start + content_len <= MAX_FILELOG_DIR_SIZE) break; } } // 截断并移位(避免大内存分配) if (line_start > 0) { FILE *temp = tmpfile(); // 创建临时文件 fseek(fp, line_start, SEEK_SET); // 流式复制保留内容 char buffer[1024]; size_t bytes; while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { fwrite(buffer, 1, bytes, temp); } // 原子替换原文件 ftruncate(fileno(fp), 0); rewind(fp); rewind(temp); while ((bytes = fread(buffer, 1, sizeof(buffer), temp)) > 0) { fwrite(buffer, 1, bytes, fp); } fclose(temp); file_size = ftell(fp); } else { ftruncate(fileno(fp), 0); file_size = 0; break; } } // fclose(fp); //session FileLogSession *session = calloc(1, sizeof(FileLogSession)); if (!session) return false; // session->fp = fopen(filepath, "ab"); session->fp = fp; if (!session->fp) { free(session); return false; } session->remaining = content_len; session->total_size = content_len; char *if_encrypt = common_find_key_from_buf(buf, "X-If-Encrypt"); DBG_ERR("if_encrypt:%s\n",if_encrypt); if (if_encrypt) { session->decrypt_flag = atoi(if_encrypt); DBG_ERR("session->decrypt_flagt:%d\n",session->decrypt_flag); char *nonce = NULL; if ((nonce = common_find_key_from_buf(buf, "X-Nonce"))) { DBG_ERR("nonce:%s\n",nonce); work_tapo_log_refresh_nonce(nonce); free(nonce); } } else { session->decrypt_flag = 0; } free(if_encrypt); snprintf(session->filepath,sizeof(session->filepath),"%s",filepath); sock->handler.cb = tpsocket_event_filelog_to_hub; sock->handler.priv = session; return sock->handler.cb; }打印:[1103 09:59:36][Error] mediacenter: [worker.c:6600][tpsocket_event_worker_listen_cb] WORKERC: 192.168.137.1:50592 connected [1103 09:59:36][Error] mediacenter: [worker.c:3961][worker_file_log_set_handle] mac: 40AE30181089 [1103 09:59:36][Error] mediacenter: [worker.c:3968][worker_file_log_set_handle] processed_mac: 40AE30181089 [1103 09:59:36][Error] mediacenter: [worker.c:3990][worker_file_log_set_handle] filepath: /mnt/sdcard/40AE30181089/log.txt [1103 09:59:36][Error] mediacenter: [worker.c:4002][worker_file_log_set_handle] Content-Length: 216 [1103 09:59:36][Error] mediacenter: [worker.c:4077][worker_file_log_set_handle] if_encrypt:1 [1103 09:59:36][Error] mediacenter: [worker.c:4081][worker_file_log_set_handle] session->decrypt_flagt:1 [1103 09:59:36][Error] mediacenter: [worker.c:4085][worker_file_log_set_handle] nonce:1234567890abcdef [1103 09:59:36][Error] mediacenter: [worker.c:240][work_tapo_refresh_encrypt_key] tapo_nonce: [1103 09:59:36][Error] mediacenter: [worker.c:256][work_tapo_refresh_encrypt_key] tapo_key: 9a33cbb078ebbf78533f35b2ad7a58db [1103 09:59:36][Error] mediacenter: [worker.c:258][work_tapo_refresh_encrypt_key] tapo_iv: 1f7d50c56381bb05217922bda930004c [1103 09:59:36][Error] mediacenter: [storage.c:916][tpsocket_event_filelog_to_hub] sock=0xd37090, event=TPSOCKET_EVENT_STREAM [1103 09:59:36][Error] mediacenter: [storage.c:916][tpsocket_event_filelog_to_hub] sock=0xd37090, event=TPSOCKET_EVENT_MESSAGE [1103 09:59:36][Error] mediacenter: [storage.c:948][tpsocket_event_filelog_to_hub] input_len:216 [1103 09:59:36][Error] mediacenter: [storage.c:951][tpsocket_event_filelog_to_hub] +++++++++++++++++++++++++++++ [1103 09:59:36][Error] mediacenter: [storage.c:958][tpsocket_event_filelog_to_hub] tpsocket_base64_decode [1103 09:59:36][Error] mediacenter: [storage.c:969][tpsocket_event_filelog_to_hub] decode session->remaining:160 [1103 09:59:36][Error] mediacenter: [storage.c:973][tpsocket_event_filelog_to_hub] plain_len:160 [1103 09:59:36][Error] mediacenter: [storage.c:1002][tpsocket_event_filelog_to_hub] session->remaining: 0 [1103 09:59:36][Error] mediacenter: [storage.c:911][tpsocket_event_filelog_to_hub] File pointer is NULL, cannot write [1103 09:59:36][Error] mediacenter: [storage.c:911][tpsocket_event_filelog_to_hub] File pointer is NULL, cannot write 分析为什么会出现这种情况?
最新发布
11-04
从你提供的日志代码来看,出现 `File pointer is NULL, cannot write` 的错误,是因为在处理加密日志写入时,文件指针 `fp` 被提前关闭了,导致后续写入失败。 --- ### 一、问题定位 #### 关键日志分析: ``` [storage.c:973][tpsocket_event_filelog_to_hub] plain_len:160 [storage.c:1002][tpsocket_event_filelog_to_hub] session->remaining: 0 [storage.c:911][tpsocket_event_filelog_to_hub] File pointer is NULL, cannot write ``` - `plain_len:160`:表示解密后的数据长度是 160 字节。 - `session->remaining: 0`:表示 `remaining` 已被减到 0,说明本次数据已处理完毕。 - **关键问题**:`File pointer is NULL` —— 文件指针在写入时已经为 `NULL`。 --- ### 二、代码逻辑分析 #### 1. **写入逻辑:** 在 `tpsocket_event_filelog_to_hub` 中: ```c if (remaining <= 0 || error) { if (fp) { fclose(fp); session->fp = NULL; // 关闭文件并置空 fp } ... } ``` 一旦 `remaining <= 0`,`fp` 就被 `fclose()` 并设置为 `NULL`。 #### 2. **后续事件触发:** 从日志中看到: ``` [storage.c:916][tpsocket_event_filelog_to_hub] sock=0xd37090, event=TPSOCKET_EVENT_STREAM [storage.c:916][tpsocket_event_filelog_to_hub] sock=0xd37090, event=TPSOCKET_EVENT_MESSAGE ``` - 在 `TPSOCKET_EVENT_MESSAGE` 处理完成后,后续又触发了 `TPSOCKET_EVENT_STREAM` 或 `TPSOCKET_EVENT_MESSAGE`。 - 此时 `fp` 已经被关闭为 `NULL`,所以再次写入时就会失败。 --- ### 三、根本原因 #### 1. **`fp` 被提前关闭** 在 `remaining <= 0` 时,`fp` 被 `fclose()` 并设为 `NULL`,但后续事件(如 `TPSOCKET_EVENT_STREAM`)仍试图使用 `fp`,导致访问空指针。 #### 2. **未及时退出或忽略后续事件** 在 `remaining <= 0` 后,函数没有直接返回,而是继续执行,导致后续的事件处理中访问 `fp`。 --- ### 四、解决方案 #### ✅ 修复建议: ```c if (remaining <= 0 || error) { if (fp) { fclose(fp); session->fp = NULL; } ... return true; // ✅ 加上 return 提前退出,避免后续访问 fp } ``` 这样可以确保在完成写入后不再处理后续事件,避免空指针访问。 --- ### 五、其他建议优化 1. **在 `TPSOCKET_EVENT_STREAM` 中直接返回 true**: ```c case TPSOCKET_EVENT_STREAM: return true; ``` 表示我们不处理流事件,防止误操作。 2. **检查 `fp == NULL` 后直接返回**: ```c if (!fp) { DBG_ERR("File pointer is NULL, cannot write\n"); return false; // ✅ 返回 false,避免继续执行 } ``` 3. **统一资源释放逻辑**: 使用 `goto cleanup` 或统一的清理函数,避免资源泄漏或多次释放。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值