c - 在 C 中将结构写入文本文件
问题描述
我想要做的是在 C 中解析一个文件(WireShark 解析器到一个小描述符文件)。
我设法解析成功(结构中的值是正确的),但是当我写入文本文件时,它在最后添加了一行空值(添加的空值的数量总是等于我写的结构的数量到文件)。比如我写了6行,所以最后加了6个null。
我很想知道是否有人可以确定问题所在。
这是我使用的写宏:
#define WRITE_F(file_name,modifier,value) fprintf(file_name,"%"#modifier,value);
//the used function - **space_val = " "**
void write_to_file(FILE* lua_descriptor, lua_line *line)
{
WRITE_F(lua_descriptor,s, line->name);
WRITE_F(lua_descriptor,s, line->str_size);
WRITE_F(lua_descriptor,c, SPACE_VAL);
WRITE_F(lua_descriptor,d, line->opcode);
WRITE_F(lua_descriptor, s, "\n");
}
//the lua_line struct:
typedef struct lua_line{
char * name;
char * str_size;
int opcode;
}lua_line;
这由客户端-服务器解决方案处理。这是客户端,我将其发送到服务器,如下所示:
/*
============================================
General : function is responsible for sending the length of the file to the server
Parameters : sock - socket connection between client and server
*filesize - holds a pointer to the size that needs to be sent
filesize_len - the length of the file size pointer
Return Value : returns TRUE when the length of the data was sent correctly.
returns FALSE when there was a socket error.
============================================
*/
bool send_file_length(SOCKET sock, long* filesize, int filesize_len)
{
bool retval = true;
unsigned char* pbuf = (unsigned char*)filesize;
int num = send(sock, pbuf, filesize_len, 0);
if (num == SOCKET_ERROR){retval = false;}
return retval;
}
/*
============================================
General : transfers the size to network byte order
and sends data to the server
Parameters : sock - socket for the client - server connection
filesize - the value of the file size
Return Value : returns TRUE when the length of the data was sent correctly.
returns FALSE when there was a socket error.
============================================
*/
bool convert_size(SOCKET sock, long filesize)
{
printf("file size %d\n", filesize);
filesize = htonl(filesize);
return send_file_length(sock, &filesize, sizeof(filesize));
}
/*
============================================
General : function is responsible of sending the new lua
file to the server
Parameters : sock - socket between the client and the server
f - file that needs to be sent to the server
Return Value : returns TRUE when the file was sent correctly
returns FALSE when the file is empty or when there was a socket error
============================================
*/
bool send_file(SOCKET sock, FILE* f)
{
bool retval = true;
fseek(f, 0, SEEK_END);
long filesize = ftell(f);
char buffer[BUFFER_SIZE];
rewind(f);
if (filesize == EOF) { retval = false; }
if (retval && !convert_size(sock, filesize)) { retval = false; }
if (filesize > 0 && retval){
while (filesize > 0 && retval){
size_t num = filesize;
num = fread(buffer, 1, num, f);
if (num < 1) {
retval = false;
}
if (!send(sock, buffer, num, 0)){
retval = false;
}
filesize -= num;
}
}
return retval;
}
在服务器端,我接收它并将其写入文件(添加了一个额外的空行),如下所示:
/*
===================================================
General : receives the length of the file and updates it
Parameters : sock - client socket to receive the data from
*filesize - holds a pointer to the size of the buffer that needs to update
filesize_len - the length of the file size pointer
Return Value : returns TRUE when the size is read correctly
else, FALSE when there was a socket error or no bytes are received.
===================================================
*/
bool recv_file_len(SOCKET sock, long* filesize, int filesize_len)
{
unsigned char* psize = (unsigned char*)filesize;//changes the pointer type so we can receive the data to it from recv
bool retval = true;
int num = recv(sock, psize, filesize_len, 0);//receive to size
if (num == SOCKET_ERROR)
{
retval = false;
}
else if (num == 0)
{
retval = false;
}
return retval;
}
/*
===================================================
General : writes to the lua file the data from the file
that was received in the socket
Parameters : sock - the socket between the client and server
*f - the file to write the data received to
Return Value : returns TRUE when everything was written to the file.
returns FALSE if there's no data received or detected a socket problem.
===================================================
*/
bool write_to_lua(SOCKET sock, FILE *f)
{
long filesize;//size of address
char buffer[BUFFER_SIZE];
ZeroMemory(buffer, BUFFER_SIZE);
bool retval = recv_file_len(sock, &filesize, sizeof(filesize));
if (retval)//if the size of the file didn't fail to update
{
filesize = ntohl(filesize);
printf("file size (From C client) : %ld\n", filesize);
while (filesize > 0 && retval)
{
int num = filesize;
if (!recv(sock, buffer, sizeof(buffer), 0))//reads the data
{
retval = false;
}
int offset = 0;
while (offset < num && retval)//writes to the file
{
size_t written = fwrite(&buffer[offset], 1, num - offset, f);
//size_t written = fprintf(f,&buffer[offset]);
if (written < 1)
{
retval = false;
}
offset += written;
}
filesize -= num;
}
}
return retval;
}
解决方案
如果设置正确(您没有显示),您对write_to_file()
我来说看起来不错。lua_line
但是,您对send()
and的处理recv()
都是错误的。返回值是发送/接收的字节数,而不是bool
像您对待它的那样。而且,返回值可能小于请求的字节数,您无需检查是否必须再次调用send()
/recv()
来发送/接收更多字节(类似于您正在执行的操作fwrite()
)。
如果文件大于send_file()
您的buffer
. 并且write_to_lua()
循环也可能会在其中接收太多字节,并在将其写入输出文件时buffer
忽略实际。这很可能是您额外的 nuls 的来源。filesize
buffer
尝试更多类似的东西:
客户:
/*
============================================
General : function is responsible for sending the length of data to the server
Parameters : sock - socket connection between client and server
*buf - holds a pointer to the data that needs to be sent
bufsize - the length of the data pointer
Return Value : returns TRUE when the length of the data was sent correctly.
returns FALSE when there was a socket error.
============================================
*/
bool send_raw(SOCKET sock, void* buf, int bufsize)
{
unsigned char* pbuf = (unsigned char*)buf;
while (bufsize > 0) {
int num = send(sock, pbuf, bufsize, 0);
if (num == SOCKET_ERROR){ return false; }
pbuf += sent;
bufsize -= sent;
}
return true;
}
/*
============================================
General : function is responsible for sending the length of the file
to the server in network byte order
Parameters : sock - socket connection between client and server
filesize - the value of the file size
Return Value : returns TRUE when the length of the data was sent correctly.
returns FALSE when there was a socket error.
============================================
*/
bool send_file_length(SOCKET sock, long filesize)
{
filesize = htonl(filesize);
return send_raw(sock, &filesize, sizeof(filesize));
}
/*
============================================
General : function is responsible of sending the new lua
file to the server
Parameters : sock - socket between the client and the server
f - file that needs to be sent to the server
Return Value : returns TRUE when the file was sent correctly
returns FALSE when the file is empty or when there was a socket error
============================================
*/
bool send_file(SOCKET sock, FILE* f)
{
if (fseek(f, 0, SEEK_END) != 0) { return false; }
long filesize = ftell(f);
rewind(f);
if (filesize == -1L) { return false; }
if (!send_file_length(sock, filesize)) { return false; }
if (filesize > 0) {
char buffer[BUFFER_SIZE];
do {
size_t num = fread(buffer, 1, min(filesize, BUFFER_SIZE), f);
if (num < 1) { return false; }
if (!send_raw(sock, buffer, num)) { return false; }
filesize -= num;
}
while (filesize > 0);
}
return true;
}
服务器:
/*
============================================
General : function is responsible for receiving a length of data from the client
Parameters : sock - client socket to receive the data from
*buf - holds a pointer to the buffer that needs to update
bufsize - the length of the buffer
Return Value : returns TRUE when the data is read correctly
else, FALSE when there was a socket error or no bytes are received.
============================================
*/
bool recv_raw(SOCKET sock, void* buf, int bufsize)
{
unsigned char* pbuf = (unsigned char*)buf;
while (bufsize > 0) {
int num = recv(sock, pbuf, bufsize, 0);
if (num <= 0) { return false; }
pbuf += num;
bufsize -= num;
}
return true;
}
/*
===================================================
General : receives the length of the file and updates it
Parameters : sock - client socket to receive the data from
*filesize - holds a pointer to the size of the buffer that needs to update
filesize_len - the length of the file size pointer
Return Value : returns TRUE when the size is read correctly
else, FALSE when there was a socket error or no bytes are received.
===================================================
*/
bool recv_file_len(SOCKET sock, long* filesize)
{
if (!recv_raw(sock, filesize, sizeof(*filesize)) { return false; }
*filesize = ntohl(*filesize);
return true;
}
/*
===================================================
General : writes to the lua file the data from the file
that was received in the socket
Parameters : sock - the socket between the client and server
*f - the file to write the data received to
Return Value : returns TRUE when everything was written to the file.
returns FALSE if there's no data received or detected a socket problem.
===================================================
*/
bool write_to_lua(SOCKET sock, FILE *f)
{
long filesize;//size of address
if (!recv_file_len(sock, &filesize)) { return false; }
printf("file size (From C client) : %ld\n", filesize);
if (filesize > 0)
{
char buffer[BUFFER_SIZE];
do {
int num = min(filesize, BUFFER_SIZE);
if (!recv_raw(sock, buffer, num)) { return false; }
int offset = 0;
do
{
size_t written = fwrite(&buffer[offset], 1, num - offset, f);
if (written < 1) { return false; }
offset += written;
}
while (offset < num);
/* alternatively, no loop is needed:
if (fwrite(buffer, num, 1, f) < 1) { return false; }
*/
filesize -= num;
}
while (filesize > 0);
}
return true;
}
推荐阅读
- javascript - 在javascript中将输入设置为只读
- windows - 我将如何编写一个批处理文件来命名目录中的文件,如 Windows 资源管理器自动重命名?
- python - Windows 7-python 上的交互式 shell
- typescript - 打字稿泛型,使用泛型字段作为映射类型
- java - 如何使用 retrofit2 在数据类中显示类别 - Kotlin
- python - 为什么从 python 脚本创建的可执行文件被检测为病毒?
- php - 将引导程序包含到 wordpress 插件前端
- list - 如何在redis的列表中获取项目的位置以及为什么有lrem而没有llocation命令
- flutter - 颤动的sliding_up_panel插件如何在关闭时跳转到面板顶部?
- typescript - 打字稿联合破坏反应高阶组件类型推断