Как взять информацию из файла, поместить ее в массив и получить размер массива? [Дубликат]

С ответом ECMAScript 6 StoBor можно сделать еще более кратким:

homes.sort((a, b) => a.price - b.price)
119
задан hippietrail 5 April 2011 в 01:08
поделиться

13 ответов

На основе кода NilObject:

#include <sys/stat.h>
#include <sys/types.h>

off_t fsize(const char *filename) {
    struct stat st; 

    if (stat(filename, &st) == 0)
        return st.st_size;

    return -1; 
}

Изменения:

  • Сделал аргумент имени файла a const char.
  • Исправлено struct stat, в котором отсутствовало имя переменной.
  • Возвращает -1 при ошибке вместо 0, что было бы неоднозначным для пустого файла. off_t является подписанным типом, поэтому это возможно.

Если вы хотите fsize() распечатать сообщение об ошибке, вы можете использовать это:

#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

off_t fsize(const char *filename) {
    struct stat st;

    if (stat(filename, &st) == 0)
        return st.st_size;

    fprintf(stderr, "Cannot determine size of %s: %s\n",
            filename, strerror(errno));

    return -1;
}

В 32-битных системах вы должны скомпилировать это с помощью опции -D_FILE_OFFSET_BITS=64, иначе off_t будет содержать только значения до 2 ГБ. Подробнее см. Раздел «Использование LFS» в Поддержка больших файлов в Linux .

124
ответ дан Jonathan Stone 21 August 2018 в 20:49
поделиться
  • 1
    Это конкретный Linux / Unix - возможно, стоит отметить, что вопрос не задал ОС. – Drew Hall 2 August 2010 в 22:54
  • 2
    Вероятно, вы можете изменить тип возврата на ssize_t и без каких-либо проблем отбросить размер с off_t. Казалось бы, имеет смысл использовать ssize_t :-) (Не путать с size_t, который без знака и не может использоваться для указания ошибки.) – Ted Percival 6 August 2010 в 18:03
  • 3
    Для более портативного кода используйте fseek + ftell, как предложено Дереком. – Ciro Santilli 新疆改造中心 六四事件 法轮功 2 March 2015 в 08:57
  • 4
    Для более портативного кода используйте fseek + ftell, как предложено Дереком. Нет. В стандарте C указано, что fseek() - SEEK_END на двоичном file - неопределенное поведение. 7.19.9.2 Функция fseek ... Бинарный поток не нуждается в значимой поддержке fseek вызовов с значением whence SEEK_END , и, как отмечено ниже, который из примечания 234 на с. 267 связанного C-стандарта и который специально маркирует fseek - SEEK_END в двоичном потоке как неопределенное поведение. , – Andrew Henle 6 April 2016 в 10:54

** Не делайте этого ( почему? ):

Цитирование стандартного документа C99, который я нашел в Интернете: «Установка индикатора положения файла для завершения -файла, как и в файле fseek (файл, 0, SEEK_END), имеет неопределенное поведение для двоичного потока (из-за возможных завершающих нулевых символов) или для любого потока с зависящей от состояния кодировкой, которая не обязательно заканчивается в начальном состоянии сдвига . **

Измените определение на int, чтобы сообщения об ошибках могли быть переданы, а затем используйте fseek () и ftell () для определения размера файла.

int fsize(char* file) {
  int size;
  FILE* fh;

  fh = fopen(file, "rb"); //binary mode
  if(fh != NULL){
    if( fseek(fh, 0, SEEK_END) ){
      fclose(fh);
      return -1;
    }

    size = ftell(fh);
    fclose(fh);
    return size;
  }

  return -1; //error
}
12
ответ дан 8 revs, 5 users 88% 21 August 2018 в 20:49
поделиться
  • 1
    @mezhaka: Этот отчет CERT просто ошибочен. fseeko и ftello (или fseek и ftell, если вы застряли без прежнего и довольны ограничениями размеров файлов, с которыми вы можете работать) являются правильным способом определения длины файла. stat -направленные решения не работают во многих «файлах» (например, блочные устройства) и не переносятся в системы, отличные от POSIX. – R.. 24 October 2010 в 05:30
  • 2
    Это единственный способ получить размер файла во многих системах, не соответствующих требованиям совместимости (например, моя минималистичная mbed) – Earlz 3 March 2012 в 01:36

Глядя на вопрос, ftell может легко получить количество байтов.

  long size ;
  size = ftell(FILENAME);
  printf("total size is %ld bytes",size);
1
ответ дан Adam Tyszecki 21 August 2018 в 20:49
поделиться
  • 1
    ftell ожидает дескриптор файла, а не имя файла, в качестве аргумента. – Barmar 30 September 2016 в 14:57
  • 2
    Вам не нужно закрывать файл? – Jerry Jeremiah 2 February 2017 в 01:53

Попробуйте это -

fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);

Что это значит, сначала, найдите конец файла; затем сообщите, где находится указатель файла. Наконец (это необязательно) он перематывается обратно в начало файла. Обратите внимание, что fp должен быть двоичным потоком.

file_size содержит количество байтов, содержащихся в файле. Обратите внимание, что поскольку (согласно climits.h) беззнаковый длинный тип ограничен 4294967295 байтами (4 гигабайта), вам нужно будет найти другой тип переменной, если вы, вероятно, будете иметь дело с файлами, большими, чем это.

1
ответ дан Adrian Zhang 21 August 2018 в 20:49
поделиться
  • 1
    Как это отличается от ответа Дерека от 8 лет назад? – P.P. 29 December 2016 в 22:51
  • 2
    Это неопределенное поведение для двоичного потока, а для текстового потока ftell не возвращается значение, представляющее количество байтов, которое может быть прочитано из файла. – Andrew Henle 30 December 2016 в 02:58

Вам понадобится использовать библиотечную функцию для получения сведений о файле. Поскольку C полностью независим от платформы, вам нужно сообщить нам, какую платформу / операционную систему вы разрабатываете!

-1
ответ дан Chris Roberts 21 August 2018 в 20:49
поделиться

Решение Мэтта должно работать, за исключением того, что это C ++ вместо C, и исходный запрос не нужен.

unsigned long fsize(char* file)
{
    FILE * f = fopen(file, "r");
    fseek(f, 0, SEEK_END);
    unsigned long len = (unsigned long)ftell(f);
    fclose(f);
    return len;
}

Исправлена ​​ваша скобка для вас. ;)

Обновление: на самом деле это не лучшее решение. Он ограничен файлами размером 4 ГБ в Windows, и, скорее всего, он медленнее, чем просто использование определенного для платформы вызова, например GetFileSizeEx или stat64.

26
ответ дан Derek Park 21 August 2018 в 20:49
поделиться
  • 1
    Да, ты должен. Тем не менее, если нет действительно убедительной причины не писать специфичные для платформы, тем не менее, вы, вероятно, должны просто использовать вызов для конкретной платформы, а не шаблон open / seek-end / tell / close. – Derek Park 18 April 2012 в 05:10
  • 2
    Извините за поздний ответ, но у меня есть серьезная проблема. Это приводит к зависанию приложения при доступе к ограниченным файлам (например, к защищенным паролем или системным файлам). Есть ли способ запросить у пользователя пароль при необходимости? – Justin 29 March 2013 в 05:34
  • 3
    @Justin, вам, вероятно, следует открыть новый вопрос конкретно о проблеме, с которой вы работаете, и предоставить подробную информацию о платформе, на которой вы находитесь, о том, как вы обращаетесь к файлам и каково поведение. – Derek Park 2 April 2013 в 16:04
  • 4
    Оба C99 и C11 возвращают long int из ftell(). (unsigned long) литье не улучшает диапазон, который уже ограничен функцией. ftell() возвращать -1 при ошибке, и они становятся запутаны при передаче. Предложить fsize() вернуть тот же тип, что и ftell(). – chux 13 January 2014 в 00:03
  • 5
    Согласен. Приведение должно соответствовать оригинальному прототипу в вопросе. Я не могу вспомнить, почему я превратил его в unsigned long вместо unsigned int. – Derek Park 28 January 2014 в 00:09

Быстрый поиск в Google нашел метод с использованием fseek и ftell и поток с этим вопросом с ответами, что это невозможно сделать только с помощью C по-другому.

Вы можете использовать библиотеку переносимости, такую ​​как NSPR (библиотека, которая активирует Firefox) или проверить ее реализацию (довольно волосатый).

3
ответ дан MPelletier 21 August 2018 в 20:49
поделиться

Не используйте int. Файлы размером более 2 гигабайт обычно являются грязными в настоящее время

Не используйте unsigned int. Файлы размером более 4 гигабайт являются общими, поскольку некоторые немного менее распространенные загрязнения

. IIRC стандартная библиотека определяет off_t как неподписанное 64-битное целое число, что и должно использовать каждый. Мы можем переопределить это до 128 бит за несколько лет, когда мы начнем работать с 16 файлами exabyte.

Если вы находитесь в окнах, вы должны использовать GetFileSizeEx - это на самом деле использует подписанное 64-битное целое число, поэтому они начнут сталкиваться с проблемами с 8 файлами exabyte. Глупый Microsoft! : -)

68
ответ дан Orion Edwards 21 August 2018 в 20:49
поделиться
  • 1
    Я использовал компиляторы, где off_t - 32 бита. Конечно, это на встроенных системах, где файлы размером 4 ГБ менее распространены. В любом случае, POSIX также определяет off64_t и соответствующие методы, чтобы добавить к путанице. – Aaron Campbell 7 July 2016 в 20:12

Вы можете открыть файл, перейти к 0 смещению относительно нижней части файла с помощью

#define SEEKBOTTOM   2

fseek(handle, 0, SEEKBOTTOM)  

, значение, возвращаемое из файла fseek, - это размер файла.

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

-3
ответ дан PabloG 21 August 2018 в 20:49
поделиться
  • 1
    Вы не должны определять что-то вроде SEEKBOTTOM. #include & lt; stdio.h & gt; fseek (дескриптор, 0, SEEK_END); – sigjuice 26 March 2009 в 06:33

Если вам хорошо с помощью библиотеки std c:

#include <sys/stat.h>
off_t fsize(char *file) {
    struct stat filestat;
    if (stat(file, &filestat) == 0) {
        return filestat.st_size;
    }
    return 0;
}
5
ответ дан pmttavara 21 August 2018 в 20:49
поделиться
  • 1
    Это не стандарт C. Это часть стандарта POSIX, но не стандарт C. – Derek Park 11 August 2008 в 22:32

Я использовал этот набор кода для поиска длины файла.

//opens a file with a file descriptor
FILE * i_file;
i_file = fopen(source, "r");

//gets a long from the file descriptor for fstat
long f_d = fileno(i_file);
struct stat buffer;
fstat(f_d, &buffer);

//stores file size
long file_length = buffer.st_size;
fclose(i_file);
1
ответ дан rco16 21 August 2018 в 20:49
поделиться

И если вы создаете приложение Windows, используйте API GetFileSizeEx , поскольку ввод / вывод файлов CRT бесполезен, особенно для определения длины файла из-за особенностей представления файлов в разных системах;)

4
ответ дан user 21 August 2018 в 20:49
поделиться
1
ответ дан Adam Tyszecki 4 November 2018 в 17:55
поделиться
Другие вопросы по тегам:

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