Вопрос по fread, c – C fread не получает весь файл

2

Я пытаюсь читать двоичные файлы и сохраняю содержимое в массив символов. Эта функция отлично работает для текстовых файлов, но для нетекстовых файлов (например, PNG-файлов) она не работает должным образом. Ниже приведен код, за которым следуют результаты. Что случилось?

Код:

#include 
#include 
#include 
#include 

unsigned int readFile(const char *fileName, char **contents);

int main(int argc, char *argv[])
{
    char *contents = 0;
    unsigned int length = readFile(argv[1], &contents);

    fprintf(stderr, "File length: %d\r\n", length);
    fprintf(stderr, "File contents:\r\n%s\r\n", contents);

    exit(0);
}

unsigned int readFile(const char *fileName, char **contents)
{
    struct stat stbuf;
    unsigned int length = 0;

    // Open a file descriptor
    int fd = open(fileName, O_RDONLY);

    // Check that file descriptor was opened
    if (fd == -1) {
        fprintf(stderr, "Fatal Error: Failed to open the file for fstat (file: %s)!\r\n", fileName);
        exit(-1);
    }

    // Get information from fstat
    if (fstat(fd, &stbuf) == -1) {
        fprintf(stderr, "Fatal Error: Failed to find file length (file: %s)!\r\n", fileName);
        exit(-1);
    }

    // Store the file length
    length = stbuf.st_size;

    // Close file descriptor
    if (close(fd) == -1) {
        fprintf(stderr, "Fatal Error: Failed to close file descriptor (file: %s)!\r\n", fileName);
        exit(-1);
    }

    // Check if the file contains data
    if (length > 0) {
        // Open the file for reading
        FILE *file = fopen(fileName, "rb");

        // Check that the file was opened
        if (file != NULL) {
            freopen(fileName, "rb", file);
            // Prepare the contents variable
            *contents = 0;
            *contents = (char*)calloc(length + 1, sizeof(char));

            // Read the file and put it in the contents variable
            int lengthRead = fread(*contents, length, 1, file);

            // Check for file read error
            if (ferror(file)) {
                fprintf(stderr, "Fatal Error: Failed to read file (file: %s)!\r\n", fileName);
                exit(-1);
            }
            else if (lengthRead != 1 || strlen(*contents) < length) {
                fprintf(stderr, "Fatal Error: File read error (file: %s)!\r\n", fileName);
                fprintf(stderr, "Characters expected: %d, Characters read: %d\r\n", length, strlen(*contents));
                fprintf(stderr, "Content read:\r\n%s\r\n", *contents);
                fprintf(stderr, "Aborting!\r\n", fileName);

                // Close file and exit
                fclose(file);
                exit(-1);
            }

            // Close binary file
            fclose(file);
        }
        else {
            fprintf(stderr, "Fatal Error: Failed to open the file: %s!\r\n", fileName);
            exit(-1);
        }
    }
    else {
        fprintf(stderr, "Fatal Error: File was empty (file: %s)!\r\n", fileName);
        exit(-1);
    }

    return length;
}

Результаты:

[email protected]:~/Workspace/test$ ls                                                                                                                                                                                                                                   
test  test.c  test.png  test.txt
[email protected]:~/Workspace/test$ ./test test.txt 
File length: 43
File contents:
This is a test file!

With multiple lines!

[email protected]:~/Workspace/test$ ./test test.png 
Fatal Error: File read error (file: test.png)!
Characters expected: 50243, Characters read: 8
Content read:
?PNG
¦

Aborting!

Я ожидал бы этих результатов, если бы я открыл файл в текстовом режиме, но, поскольку он открывается в двоичном режиме, я не понимаю, почему это происходит.

Файл содержит двоичные значения, такие как\ 0' , Ваш strlen () считается до первого NUL. wildplasser
Хорошо, это имеет смысл. Я буду читать больше о том, как читать / записывать двоичные данные. Благодарю. Devious
wildplasser прав. Вы пытаетесь читать в двоичном файле, как этоs ascii и распечатай какs ascii. Вы можете'сделать это. Вам нужно посмотреть, как читать двоичные файлы, а затем как кодировать двоичные файлы для распечатки. Codeguy007

Ваш Ответ

1   ответ
2

strlen Функция предназначена исключительно для использования в строках в стиле C. Невозможно определить длину произвольных двоичных данных, просматривая их содержимое. У вас есть длина в.lengthRead

            fprintf(stderr, "Content read:\r\n%s\r\n", *contents);

Та же проблема здесь.%s спецификатор формата для строк в стиле C, а не произвольных двоичных данных. Вы'Вам нужно написать свою собственную функцию для печати данных в каком-то подходящем формате.

Хорошо, я вижу, что мне понадобятся изменения. Спасибо, что указал мне правильное направление. Devious

Похожие вопросы