如何正确使用fwrite?

时间:2017-12-13 07:10:34

标签: c

所以我有一个名为bufptr的char *,大小为512.在前几个点中是我将要读取的文件的名称,之后的所有其他内容都是数据。

离。 char* bufptr = {'f', 'o', 'o', '.', 'c', '\0', ...}

我没有像那样初始化它,但这是一般的想法

在此之后,我使用strcpy

将文件名存储到另一个文件中

离。

auto int i = 0;
while(*bufptr != '\0')
{
    fname[i++] = *bufptr;
    bufptr++;
}
bufptr++;

之后,我打开文件

我遇到的问题是fwrite部分。

我尝试写fwrite(bufptr, 1, 512 - strlen(destString), fp)

但不是

// ============================================================================
// File: fcclient.c (Fall 2017)
// ============================================================================

我得到了þ================================================

如何正确调用fwrite以便我不会遇到此问题,或者是因为我没有跳过null?或者字符串在null之前或之后有什么东西?

修改: 我添加了一个循环来检查bufptr并将其作为输出

fcclient.c▒▒▒▒▒▒▒▒▒▒id▒.N=▒C▒h▒▒▒.8▒▒l▒ ▒ ▒▒▒`▒ ▒P▒▒▒H▒
▒`▒djd▒▒dd▒▒@▒
▒@▒(▒d▒p▒▒jd▒▒▒▒▒Бd▒=======================================================================
// File: fcclient.c (Fall 2017)
// ============================================================================
// This program is a file transfer client. The user at the keyboard is pread a total of 1 bytes

这是我使用的循环

auto int t = 0;
for(; t < 512; t+=)
   if(*(bufptr + t) != '\0')
     printf("%c", *(bufptr + t));

这是服务器代码

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <unistd.h>
#include    <sys/types.h>
#include    <netinet/in.h>
#include    <sys/socket.h>

// prototypes
int     CopyFile(int  src_sock);

// defined constants
#define BUFLEN              512
#define SERVER_PORT         50004 
#define TRUE                1
#define FALSE               0

// function prototypes
int     CopyFile(int  src_sock);




int     main(void)
{
    auto    char                buf[BUFLEN];       // local buffer
    auto    socklen_t           client_addr_size;  // used for call to accept
    auto    int                 client_socket;     // used for call to accept
    auto    int                 server_socket;     // used for call to socket
    auto    struct sockaddr_in  client_address;    // used for call to accept
    auto    struct sockaddr_in  server_address;    // used for call to bind

    // greet the user
    puts("Welcome to fcserver!");
    puts("Waiting to recieve file from client...");

    // create a socket for the server
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // prepare the socket address structure for the server
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_PORT);

    // bind the server socket to an address, using the address structure
    if(bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address)))
    {
        perror("server -- bind failed");
    }

    // put the server socket into a listening state
    if(listen(server_socket, 5))
    {   
        perror("server -- bind failed");
    }

    // let stdout know the server is waiting for a connection
    puts("server waiting...");

    // wait for an actual client connection (this will block)
    client_addr_size = sizeof(server_address);
    client_socket = accept(server_socket, (struct sockaddr*) &server_address, &client_addr_size);


    CopyFile(client_socket);

    // close the client and server sockets
    close(client_socket);
    close(server_socket);

    return 0;

}  // end of "main"





int     CopyFile(int  src_sock)
{
    auto    char                        buf[BUFLEN];
    auto    char                        *bufptr;
    auto    char                        fname[BUFLEN];
    auto    FILE*                       fptr;
    auto    int                         num_client_bytes;
    auto    unsigned long               total_bytes = 0;



    if(-1 == (num_client_bytes = recv(src_sock, bufptr, BUFLEN, 0)))
        perror("server -- recv failed");


    strcpy(fname, bufptr);;
    auto int t = 0;
    for(; t< num_client_bytes; t++)
    {
        if(*(bufptr + t) != '\0')
            printf("%c", *(bufptr + t));
    }


    fptr = fopen(fname, "w");


    auto  int i = strlen(fname) +1;
    bufptr += i;
    total_bytes = fwrite(bufptr, sizeof(bufptr), 1, fptr);
    printf("read a total of %lu bytes \n", total_bytes);


    // loop and read the rest of the file from the client
    do  {

        if(num_client_bytes == 0)
            break;


        printf("read a total of %d bytes \n", num_client_bytes);


        total_bytes += fwrite(buf, 1, num_client_bytes, fptr);

        } while (TRUE);



    fclose(fptr);

    printf("there were a total of %lu bytes written \n", total_bytes);

    return TRUE;

}  // end of "CopyFile"

这是客户端文件

  // ============================================================================
// File: fcclient.c (Fall 2017)
// ============================================================================

#include    <sys/types.h>
#include    <sys/socket.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <sys/un.h>
#include    <unistd.h>
#include    <string.h>
#include    <netinet/in.h>

#define BUFLEN          256
#define SERVER_PORT     50004


int     main(void)
{
    auto    char                buf[BUFLEN];       // general purpose buffer
    auto    int                 server_socket;     // used for server socket
    auto    struct sockaddr_in  server_address;    // used for server address
    auto    char                fname[BUFLEN];     // used for filename
    auto    char                *bufptr;           // used for heap block
    auto    FILE                *fptr;             // used for input file
    auto    int                 result;            // used to check return values
    auto    long                fileSize;          // used to store file size

    // greet the user
    puts("Welcome to fcclient!");

    // get the filename from stdin
    printf("Please enter in the filename: ");
    scanf("%s", fname);

    // open the input file
    fptr = fopen(fname, "r");
    if(fptr == NULL)
    {
        printf("Sorry there was an error trying to locate the file. Please exit and try again \n");
        return 0;
    }

    // get the size of the file
    fseek(fptr, 0, SEEK_END);
    fileSize = ftell(fptr);
    fseek(fptr, 0, SEEK_SET);

    // allocate a buffer to store the file in heap memory
    bufptr = malloc(sizeof(char) * fileSize);

    // create a socket to connect with the server
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // setup a socket address structure to target the server
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(SERVER_PORT);
    server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    printf("Currently connecting to server... \n");

    // connect to the server
    if(-1 == connect(server_socket, (struct sockaddr*) &server_address, sizeof(server_address)))
        perror("client -- connect failed"); 

    // send the filename to the server (include the NULL!)
    if(-1 == send(server_socket, fname, BUFLEN, 0))
        perror("client -- send failed");

    // read the file into the allocated buffer
    fseek(fptr, sizeof(bufptr),SEEK_SET); 
    if(0 == fread(bufptr, sizeof(bufptr), fileSize, fptr))
    {
        printf("There was an error sorry. \n");
        return 0;
    }

    // send the data to the server
    if(-1 == send(server_socket, bufptr, fileSize, 0))
            perror("client -- send failed");

    // close the input file and the sockets
    fclose(fptr);
    close(server_socket);

    return 0;

}  // end of "main"

2 个答案:

答案 0 :(得分:2)

bufptr未指向缓冲区的内容,因为bufptr += strlen(destString),它指向内容旁边的位置。更新bufptr的值以指向您实际要写的内容。

答案 1 :(得分:1)

代码中存在两组问题(其中一些问题在对问题的评论中被诊断出来)。首先,你编写一个全长缓冲区,即使它主要包含垃圾,然后你尝试将其解释为文件的一部分,但事实并非如此。第二,你在客户端文件复制代码中使用未初始化的变量 - 你(不)幸运它没有崩溃。

此代码有效。

fcserver.c

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <unistd.h>
#include    <sys/types.h>
#include    <netinet/in.h>
#include    <sys/socket.h>

#define BUFLEN              512
#define SERVER_PORT         50004

void    CopyFile(int src_sock);

int     main(void)
{
    socklen_t client_addr_size;
    int client_socket;
    int server_socket;
    struct sockaddr_in server_address;

    puts("Welcome to fcserver!");
    puts("Waiting to recieve file from client...");

    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_PORT);

    if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)))
    {
        perror("server -- bind failed");
    }

    if (listen(server_socket, 5))
    {
        perror("server -- bind failed");
    }

    puts("server waiting...");

    client_addr_size = sizeof(server_address);
    client_socket = accept(server_socket, (struct sockaddr *)&server_address, &client_addr_size);

    CopyFile(client_socket);

    close(client_socket);
    close(server_socket);

    return 0;
}

void     CopyFile(int src_sock)
{
    char buf[BUFLEN];
    char fname[BUFLEN];
    FILE *fptr;
    int num_client_bytes;
    unsigned long total_bytes = 0;

    if (-1 == (num_client_bytes = recv(src_sock, fname, BUFLEN, 0)))
    {
        perror("server -- recv failed");
        exit(1);
    }

    printf("File name: [%s]\n", fname);
    fptr = fopen(fname, "w");
    if (fname == 0)
    {
        perror(fname);
        exit(1);
    }

    while ((num_client_bytes = recv(src_sock, buf, BUFLEN, 0)) > 0)
    {
        printf("read a total of %d bytes\n", num_client_bytes);
        total_bytes += fwrite(buf, 1, num_client_bytes, fptr);
    }

    fclose(fptr);

    printf("there were a total of %lu bytes written\n", total_bytes);
}

那是85行,而不是170多行。

fcclient.c

#include    <sys/types.h>
#include    <sys/socket.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <sys/un.h>
#include    <unistd.h>
#include    <string.h>
#include    <netinet/in.h>

#define BUFLEN          256
#define SERVER_PORT     50004

int     main(void)
{
    int server_socket;
    struct sockaddr_in server_address;
    char fname[BUFLEN] = "";
    char                *bufptr;
    FILE                *fptr;
    size_t fileSize;

    puts("Welcome to fcclient!");

    printf("Please enter in the filename: ");
    scanf("%s", fname);

    fptr = fopen(fname, "r");
    if (fptr == NULL)
    {
        printf("Sorry there was an error trying to locate the file. Please exit and try again \n");
        return 0;
    }

    fseek(fptr, 0, SEEK_END);
    fileSize = ftell(fptr);
    fseek(fptr, 0, SEEK_SET);

    bufptr = malloc(sizeof(char) * fileSize);

    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(SERVER_PORT);
    server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    printf("Currently connecting to server... \n");

    if (-1 == connect(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)))
        perror("client -- connect failed");

    if (-1 == send(server_socket, fname, BUFLEN, 0))
        perror("client -- send failed");

    fseek(fptr, 0, SEEK_SET);
    if (fileSize != fread(bufptr, sizeof(char), fileSize, fptr))
    {
        printf("There was an error sorry. \n");
        return 0;
    }

    if (-1 == send(server_socket, bufptr, fileSize, 0))
        perror("client -- send failed");

    fclose(fptr);
    close(server_socket);

    return 0;
}

那是68行而不是170多行。

测试

在与客户端不同的目录中运行服务器至关重要,否则您可能会截断文件。但是,当我使用包含文件junk的子目录animals19.c并在该目录中运行客户端时,当服务器在父目录中运行时,我得到了输出:

服务器窗口

$ ./fcserver
Welcome to fcserver!
Waiting to recieve file from client...
server waiting...
File name: [animals19.c]
read a total of 512 bytes
read a total of 292 bytes
there were a total of 804 bytes written
$

客户端窗口

$ ../fcclient
Welcome to fcclient!
Please enter in the filename: animals19.c
Currently connecting to server... 
$ ls -l animals19.c ../animals19.c
-rw-r--r--  1 jleffler  staff  804 Dec 13 00:42 ../animals19.c
-rw-r--r--  1 jleffler  staff  804 Dec  3 21:54 animals19.c
$ diff animals19.c ../animals19.c
$

哦,在某些时候,你应该注意“我在e之前除了c之后”(所以它是receive而不是recieve)。您还应注意perror()打印错误;它没有退出。使用perror()后继续通常是错误的。