Неверные результаты fprintf - PullRequest
0 голосов
/ 29 мая 2018

В приведенном ниже коде я пытаюсь read из сокета и сохранить результаты в файле.

Что действительно происходит, так это то, что мой клиент отправляет запрос GET на мой сервер для file.html.Мой сервер находит файл и записывает его содержимое в сокет.Наконец, мой клиент читает содержимое из thread_fd и воссоздает файл.

По какой-то причине воссозданный файл имеет меньше содержимого, чем оригинал.Я обнаружил, что проблема в том, что некоторые строки в конце отсутствуют.Когда я использую printf("%s", buffer) внутри цикла while, все выглядит нормально в STDOUT, но мой fprintf пропускает несколько 3000 байт для файла размером 81 000 байт.

#define MAXSIZE 1000

int bytes_read, thread_fd;
char buffer[MAXSIZE];
FILE* new_file;

memset(buffer, 0, MAXSIZE);
if((new_file = fopen(path, "wb+")) == NULL)
{
    printf("can not open file \n");
    exit(EXIT_FAILURE);
}
while ((bytes_read = read(thread_fd, buffer, MAXSIZE)) > 0)
{

    fprintf(new_file, "%s", buffer);
    if(bytes_read < MAXSIZE)
        break;
    memset(buffer, 0, MAXSIZE);
}

Ответы [ 4 ]

0 голосов
/ 29 мая 2018

Это сработало!

ps: я не знаю, стоит ли мне это делать, поскольку я здесь новичок, но на самом деле нет причин для негатива.Любой вопрос хороший вопрос.Просто ответь, если знаешь.Не суди об этом.

#define MAXSIZE 1000

int bytes_read, thread_fd, new_file;
char buffer[MAXSIZE];

memset(buffer, 0, MAXSIZE);

if((new_file = open(path, O_RDONLY | O_WRONLY | O_CREAT)) < 0)
{
    printf("can not open file \n");
    exit(EXIT_FAILURE);
}
while ((bytes_read = read(thread_fd, buffer, MAXSIZE)) > 0)
    write(new_file, buffer, bytes_read);
close(new_file);
0 голосов
/ 29 мая 2018

Вы читаете двоичные данные из сокета, которые могут содержать или не содержать байт \ 0.Когда вы затем fprintf эти данные, fprintf остановится на первом \ 0, который он встречает.В вашем случае это 3000 байтов меньше полного файла.Если ваш файл не содержит байта \ 0, fprintf просто продолжит печатать содержимое оперативной памяти до тех пор, пока он не выйдет из строя.

Используйте write (), чтобы записать данные обратно в файл и проверить наличие ошибок.Не забудьте закрыть () файл и проверить его на наличие ошибок.

0 голосов
/ 29 мая 2018

Есть несколько проблем с вашим кодом, которые могут вызвать это.

Наиболее вероятная причина заключается в следующем:

if(bytes_read < MAXSIZE)
    break;

Это завершает цикл, когда read возвращает меньше запрашиваемого количества байтов.Это, однако, совершенно нормальное поведение, и может произойти, например.когда во время вызова read доступно недостаточно байтов (в конце концов, это чтение из сетевого сокета).Просто позвольте циклу продолжаться до тех пор, пока read вернет значение> 0 (при условии, что сокет является блокирующим сокетом - если нет, вам также придется проверить на EAGAIN и EWOULDBLOCK).

Кроме того, если файл, который вы получаете, содержит двоичные данные, то не рекомендуется использовать fprintf с "%s" для записи в целевой файл.Это прекратит запись, как только найдет байт '\0' (что не редкость в двоичных данных).Вместо этого используйте fwrite.

Даже если вы получаете текст (предложенный расширением html-файла), все равно не стоит использовать fprintf с "%s",поскольку полученные данные не будут '\0' прекращены.

0 голосов
/ 29 мая 2018

Ваш код должен выглядеть следующим образом:

int readfile(int thread_fd, char *path)
{
    unsigned int bytes_read;
    char buffer[MAXSIZE];
    int new_file;

    if ((new_file = open(path, _O_CREAT|_O_BINARY,_S_IWRITE)) == -1) return -1;

    while ((bytes_read = read(thread_fd, buffer, MAXSIZE)) > 0)
    {
        if (write(new_file, buffer, bytes_read)!= bytes_read) {
            close(new_file);
            return -2;
        }
    }
    close(new_file);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...