Разделение файла на блоки по N-байт

Есть текстовый файл размера N байт. Его нужно разделить на блоки по M байт. Каждый отдельный блок является новым текстовым файлом, в котором будет записано M байт от исходного файла.

Проблема: на выходе я постоянно получаю пустой файл размером 0 байт. Использование других функций для чтения/записи файлов тоже ничего не дает. Во всех случаях получается пустой текстовый файл.

    // Чтение файла с сообщением

    FILE* messageFile;
    fopen_s(&messageFile, "./Alice/message.txt", "rb");

    if (messageFile == NULL)
    {
        printf("Не удается открыть файл.\n");
        return 0;
    }

    // Вычисляем размер файла с сообщением

    fseek(messageFile, 0, SEEK_END);
    size_t fileSize = ftell(messageFile);
    fseek(messageFile, 0, SEEK_SET);

    // Количество целых байт на один блок сообщения
    
    size_t bytesPerBlock = 7;
    
    // Количество новых файлов (блоков)

    size_t amountBlocks = fileSize / bytesPerBlock;
     
    // Создание массива файлов

    FILE *messageBlocks;
    messageBlocks = (FILE *)malloc(amountBlocks * sizeof(FILE));
    fopen_s(&messageBlocks[0], "./block.txt", "wb");
     
    // Буфер для чтения из исходного файла

    char *buffer;
    buffer = (char *)malloc(bytesPerBlock * sizeof(char));
     
    // Чтение некоторого кол-ва байт исходного файла в буфер

    printf("Прочитано %zd символов\n", fread(buffer, sizeof(char), bytesPerBlock, 
    messageFile));

    // Запись данных из буфера в новый файл (блок)

    printf("Записано %zd символов", fwrite(buffer, sizeof(char), bytesPerBlock, 
    &messageBlocks[0]));

    fclose(messageFile);
    fclose(&messageBlocks[0]);

Ответы (2 шт):

Автор решения: Harry

Не будем о самом подходе (я бы так не делал), и без того у вас масса неприятностей, связанных с указателями.

FILE *messageBlocks;
messageBlocks = (FILE *)malloc(amountBlocks * sizeof(FILE));
fopen_s(&messageBlocks[0], "./block.txt", "wb");

Смотрите, у вас по сути создается массив элементов FILE, и функции вы передаете не адрес переменной типа FILE*, как положено, и как делаете выше для исходного файла, а адрес переменной типа FILE, что неверно!

Как минимум исправьте на

FILE **messageBlocks;
messageBlocks = (FILE **)malloc(amountBlocks * sizeof(FILE));
fopen_s(&messageBlocks[0], "./block.txt", "wb");

Точно так же вы неверно пишете — надо не

fwrite(buffer, sizeof(char), bytesPerBlock, &messageBlocks[0]));

а

fwrite(buffer, sizeof(char), bytesPerBlock, messageBlocks[0]));

Да и закрывать файл надо как fclose(messageBlocks[0]);...

Попробуйте изменить свой код, внеся указанные исправления. Кстати, вы совсем не обращаете внимания на предупреждения компилятора? Это вы напрасно...

Да, в C все эти приведения типов возле malloc не нужны. А вы действительно компилируете файл как С, а не С++, так как иначе он бы просто не скомпилировался...

→ Ссылка
Автор решения: Mikhailo

Файлов может быть очень много, и все их открыть окажется невозможно. Вот вариант, когда открытых файлов только два.

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

int main() {
    // Чтение файла с сообщением
    FILE* messageFile;
    fopen_s(&messageFile, "message.txt", "rb");

    if (messageFile == NULL) {
        printf("Не удается открыть файл.\n");
        return 0;
        }

    const size_t bytesPerBlock = 7;
    char* buf = malloc(bytesPerBlock);

    for (int i = 0;; ++i) {
        char name[20];
        snprintf(name, 20, "block%d.txt", i);
        FILE* messageBlock;
        fopen_s(&messageBlock, name, "wb");

        if (messageBlock == NULL) break;

        size_t readed = fread(buf, sizeof(char), bytesPerBlock, messageFile);

        if (readed) fwrite(buf, sizeof(char), readed,  messageBlock);

        fclose(messageBlock);

        if (readed != bytesPerBlock) break;
        }

    fclose(messageFile);
    free(buf);
    }

Ещё здесь последний файл не обязательно содержит полное количество байт - N может не делиться на M нацело.

→ Ссылка