У меня есть несколько файлов на диске, которые я хочу прочитать и объединить. Я не хочу создавать новый временный файл на диске. Поэтому я решил использовать fmemopen
для чтения/записи в память и доступа к ней с помощью API-интерфейсов FILE (я уже написал другой код, который работал только с одним файлом).
Исключая проверку ошибок, по существу у меня есть:
#define MODE_APPEND "a"
int main(int argc, char *argv[]) {
off_t concatenated_file_size = 0;
for (int i = 1; i < argc; i++) {
concatenated_file_size += get_file_size(argv[i]);
}
char *buf = nullptr;
FILE *concatenated_file = fmemopen(buf, concatenated_file_size, MODE_APPEND);
for (int i = 1; i < argc; i++) {
FILE *file_to_concat = open_file(argv[i]);
int c;
while ((c = fgetc(file_to_concat)) != EOF) {
fputc(c, concatenated_file);
}
}
rewind(concatenated_file);
int prevchar = fgetc(concatenated_file);
}
get_file_size
просто использует stat
, а open_file
— это просто fopen
с проверкой ошибок — оба работают корректно, как показало мое тестирование.
Однако prevchar всегда является EOF — почему-то ничего не записывается в FILE*
, возвращаемый fmemopen
. Вот как должен работать этот API? Я делаю что-то неправильно?
Я посмотрел на это, но согласно stackoverflow.com/a/30642781/6185049 мы не можем использовать API-интерфейсы FILE для чтения из него, и вместо этого нам приходится читать из буфера в памяти.
Что такое MODE_APPEND
? И почему вы запутываете строки стандартного режима?
Извините, у меня просто были константы для них. Это просто «а».
Вы не можете читать из файлового потока, доступного только для записи (добавления). Использование "a"
позволяет только добавлять данные, а не читать из потока. Вместо этого используйте "a+"
или "w+"
— возможно, "w+"
.
Если вы предоставили буфер (а не нулевой указатель), предположительно, вы можете получить доступ к содержимому напрямую, скопировав его из буфера. Вы можете использовать это, чтобы увидеть, содержит ли буфер то, что вы ожидаете. При автоматически выделяемом буфере (вы указываете нулевой указатель на fmemopen()
) такой возможности у вас нет.
... предположительно вам разрешено читать непосредственно из буфера. Не для char *buf = nullptr;: «Если в качестве аргумента buf
указан нулевой указатель, fmemopen()
должен выделить size байтов памяти, как если бы это был вызов malloc()
. Этот буфер должен автоматически освобождаться при закрытии потока. Поскольку эта функция полезна только тогда, когда поток открыт для обновления (поскольку нет возможности получить указатель на буфер), вызов fmemopen()
может завершиться неудачей, если аргумент режима не содержит «+».
@AndrewHenle: Я не особо всматривался в код — проблема "a"
vs "a+"
была моей главной темой. Я изменил этот абзац. Спасибо!
Я никогда не видел, чтобы fmemopen()
использовался с таким указателем NULL
- изначально я предполагал, что передача указателя NULL
является ошибкой, и на самом деле пошел читать документацию - представьте себе это. IME open_memstream()
используется, когда к данным необходимо получить доступ после их записи.
С fmemopen есть странность, я не могу вспомнить подробностей, но мне в голову приходит то, что на самом деле вам нужен open_memstream.