Как посчитать байты в файле

Обновлено: 07.07.2024

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

Стандарт POSIX имеет свой собственный метод для получения размера файла.
Включите заголовок sys/stat.h для использования функции.

конспект

  • Получить статистику файла, используя stat(3) .
  • Получите свойство st_size .

Примеры

Примечание. Размер ограничен 4GB . Если не Fat32 система Fat32 тогда используйте 64-битную версию!

ANSI C не предоставляет прямой способ определения длины файла.
Нам придется использовать наш разум. Сейчас мы будем использовать подход поиска!

конспект

  • Найдите файл до конца, используя fseek(3) .
  • Получить текущую позицию, используя ftell(3) .

пример

Если файл stdin или труба. POSIX, ANSI C не будет работать.
Будет возвращаться 0 если файл представляет собой канал или стандартный stdin .

Мнение: Вы должны вместо этого использовать стандарт POSIX. Потому что он имеет поддержку 64 бит.

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

Здесь простая и понятная функция, которая возвращает размер файла.

Ответ 12

Для этого мы будем использовать fseek(3) , ftell(3) / ftello(3) которые определены в <stdio.h> .
Этот метод работает как в Linux, так и в Windows!

32- битный метод может рассчитывать до 4GB размера файла, также как ограничение размера файла Fat32.
Примечание: если ввод stdin /pipe, метод не будет работать.

Ответ 13

У меня есть функция, которая хорошо работает только с stdio.h . Мне это очень нравится, оно работает очень хорошо и довольно лаконично:

Ответ 14

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

Ответ 15

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

Ответ 16

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

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

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

Как считать один байт из файла? Следующий код работает, но некоторые байты пропускаются ( 0x09, 0x0a, 0x0b, 0x0c, 0x0d ) и считывается следующий за ними байт.

Пытался еще сделать вот так,

но uint8_t* не кастится к char* . Использую именно uint8_t потому, что насколько я знаю стандартом размер char-а не регламентирован.

Я бы использовал char (чтоб он был не байтом - это надо потрудиться такое найти. ) Тогда

Ну, а если строго uint8_t (который, готов спорить, у вас он просто unsigned char . если нет - то даже интересно, с чем вы таким имеете дело) - то


182k 13 13 золотых знаков 102 102 серебряных знака 208 208 бронзовых знаков Насколько вообще безопасно использовать reinterpret_cast? Просто хочется написать переносимую программу. А почему через перегруженный оператор некоторые байты не считываются не знаете? Файл в бинарном режиме открыт ведь.
  • 0x09 - горизонтальная табуляция ( \t )
  • 0x0a - перевод строки ( \n )
  • 0x0b - вертикальная табуляция
  • 0x0c - «прогон страницы», новая страница - команда для принтера начать печать с новой страницы
  • 0x0d - возврат каретки ( \r )

Выглядит так, как-будто вы читаете всё таки текстовый файл как текст, может быть оставить в конструкторе только std::ifstream::binary ?

В крайнем случае всегда есть сишный fread() .

Для чтения файлов байтами есть специально для этого предназначенная функция fread(). Используйте ее.

Это все-таки наследие С, я думал в stream-ах есть замена для нее.

В C++ очень много умных функций форматированного ввода, таких-как >>. Не пачкайтесь, а пользуйся std::basic_istream::read.


12.4k 1 1 золотой знак 6 6 серебряных знаков 25 25 бронзовых знаков Ваш read наглухо зависнет в ожидании, если попытается прочитать больше, чем есть в файле. Нужен именно readsome() .

Согласно стандарту ISO/IEC 14882, <cstdio> такая же часть С++, как и <iostream> . Поэтому никто не мешает его использовать там, где это удобно. Ведь никто не переживает насчет такого "наследия с", как операции += , %= Никто и не помышляет убрать из С++ "наследие С", наоборот, на повестке дня добавление в стандарт С++ разного рода удобных инициализаций, которые появились в C11. Кстати, у <iostream> нет никаких преимуществ перед <cstdio> .

Объем текстового файла

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

КОИ-8: 1 символ - 1 байт = 8 бит

UNICODE : 1 символ - 2 байта = 16 бит

ЗАДАЧА 3. Определить информационный объем книги (в Мбайтах) подготовленной на компьютере, состоящей из 150 страниц (каждая страница содержит 40 строк, 60 символов в каждой строке).

1) Подсчитаем количество символов в книге 40 * 60 * 150 = 360 000

2) Информационный объем книги составит 360 000 * 1 байт = 360 байт

3) Переведем в заданные единицы 360 000 байт / 1024 = 351,5625 Кбайт / 1024 = 0,34332275 Мбайт

Длина фразы составляет примерно 40 символов. Следователь но, ее объем можно приблизительно оценить в 40 х 2 = 80 байт. Такого варианта ответа нет, попробуем перевести результат в би ты: 80 байт х 8 = 640 бит. Наиболее близкое значение из пред ложенных — 592 бита. Заметим, что разница между 640 и 592 составляет всего 48/16 = 3 символа в заданной кодировке и его можно считать несущественным по сравнению с длиной строки.

З амечание: Подсчетом символов в строке можно убедиться, что их ровно 37 (включая точку и пробелы), поэтому оценка 592 бита = 74 байта, что соответствует ровно 37 символам в двухбайтовой кодировке, является точной.

Алфавит – это набор букв, символов препинания, цифр, пробел и т.п.

Полное число символов в алфавите называют мощностью алфавита

ЗАДАЧА 4. Два текста содержат одинаковое количество символов. Первый текст составлен в алфавите мощностью 16 символов. Второй текст в алфавите мощностью 256 символов. Во сколько раз количество информации во втором тексте больше, чем в первом?

РЕШЕНИЕ: Если первый текст составлен в алфавите мощностью (К) 16 символов, то количество информации, которое несет 1 символ (1) в этом тексте, можно определить из соотношения: N = 2', таким образом, из 16 = 2' получим 1 = 4 бита. Мощность второго алфавита - 256 символов, из 256 = 2' получим 1 = 8 бит. Т.к. оба текста содержат одинаковое количество символов, количество информации во втором тексте больше, чем в первом, в 2 раза.

Скорость передачи информации

Скорость передачи данных по каналам связи ограничена пропускной способностью канала. Пропускная способность канала связи изменяется как и скорость передачи данных в бит/сек (или кратностью этой величины Кбит/с, Мбит/с, байт/с, Кбайт/с, Мбайт/с).
Для вычислении объема информации V переданной по каналу связи с пропускной способностью а за время t используют формулу:

ЗАДАЧА 1. Через ADSL - соединение файл размером 1000 Кбайт передавался 32 с. Сколько секунд потребуется для передачи файла размером 625 Кбайт.

РЕШЕНИЕ: Найдем скорость ADSL соединения: 1000 Кбайт / 32 с. = 8000 Кбит / 32 с. = 250 Кбит/с.
Найдем время для передачи файла объемом 625 Кбайт: 625 Кбайт / 250 Кбит/с = 5000 Кбит / 250 Кбит/с. = 20 секунд.

При решении задач на определении скорости и времени передачи данных возникает трудность с большими числами (пример 3 Мб/с = 25 165 824 бит/с), поэтому проще работать со степенями двойки (пример 3 Мб/с = 3 * 2 10 * 2 10 * 2 3 = 3 * 2 23 бита/с).

ЗАДАЧА 2 . Скорость передачи данных через ADSL─соединение равна 512 000 бит/c. Передача файла через это соединение заняла 1 минуту. Определить размер файла в килобайтах.

РЕШЕНИЕ: Время передачи файла: 1 мин = 60 с = 4 * 15 с = 2 2 * 15 с
Скорость передачи файла: 512000 бит/c = 512 * 1000 бит/с = 2 9 * 125 * 8 бит/с (1 байт = 8 бит)

2 9 * 125 байт/с = 2 9 * 125 бит/с / 2 10 = 125 / 2 Кб/с

Чтобы найти время объем файла, нужно умножить время передачи на скорость передачи:

Как оказалось, узнать размер файла в языке C - совсем нетривиальная задача. В процессе её решения как минимум вы обязательно столкнетесь с переполнением целочисленного типа данных. В данной статье я приведу 4 способа получения размера файла с использованием функций из стандартной библиотеки C, функций из библиотеки POSIX и функций из библиотек Windows.
Способ 1: решение "в лоб" (скомпилируется везде, но работает очень долго)
Мы просто откроем файл в бинарном режиме и в цикле считаем из него байт за байтом.

Очевидным недостатком способа является скорость работы. Если у нас файл будет на много гигабайт, то только размер файла будет считаться относительно долго (это сколько байт то надо считать?), а надо же еще остальную программу выполнять.
Достоинство такого способа - работать должен на любой платформе. Ну и конечно можно ускорить процесс за счет считывания бОльшего количества байт.

Способ 2: с использованием функций fseek и ftell (ограничен для объемных файлов и работает не всегда верно)

Данный способ основан на использовании функций стандартной библиотеки C: fseek и ftell. Что происходит - открываем файл в бинарном режиме, перемещаем внутренний указатель положения в файле сразу в конец с помощью fseek, получаем номер последнего байта с помощью ftell.

Проблем у данного способа несколько.
Первое - это возвращаемый тип функции ftell. У разных компиляторов на разных платформах по разному. Если у вас 32х битная система, то данный способ будет работать только для файлов, размером меньше 2048 Мб, поскольку максимальное значение для возвращаемого функцией типа long там будет 2147483647. На системах с большей разрядностью будет работать лучше, из-за большего значения максимума для long. Но подобная нестабильность будет мешать. Хотя у меня на 64х битой системе на компиляторе gcc данный способ для файлов больше 8 Гб выводил некорректные значения.
Второе - гарантированность работы fseek и ftell. Коротко говоря, на разных платформах работает по-разному. Где то будет точно возвращать значение положения последнего байта, где то будет возвращать неверное значение. То есть точность данного способа негарантированна.

Плюсом является то, что эти функции из стандартной библиотеки - скомпилируется почти везде.

Стоит сказать, что хитрые инженеры из Microsoft придумали функции _fseeki64 и _ftelli64, которые, как понятно из их названия, работают с int64, что решает проблему с размером файла в MSVC под Windows.

Способ 3: (под Linux (POSIX))

Данный способ основан на использовании системном вызове fstat с использованием специальной структуры struct stat. Как работает: открываем файл через open() или fopen(), вызываем fstat для дескриптора файла (если открыли через fopen, то в fstat надо положить результат fileno от указателя потока FILE), указав на буферную структуру для результатов, и получаем значения поля буферной структуры st_size.

В 18 уровне начались первые задачи побайтного чтения файлов: прочитать файл, далее найти минимальные/максимальные байты или вывести в упорядоченном виде и т.п.

Побайтовая работа с файлами - 1

  • Ввести с консоли имя файла
  • Считать все байты из файла.
  • Не учитывая повторений - отсортировать их по байт-коду в убывающем порядке.
  • Вывести на экран
  • Закрыть поток ввода-вывода

Решаем в лоб:

Решает все замечательно! Тест (если бы был — прошелся бы на ура). Но в жизни мало файлов содержащих только строчку "Мама мыла раму". Давайте скормим нашей программе файл в 46Мб (по нынешним меркам вроде и не особо много). Что такое, программа выполняется 220 секунд. Попытка скормить с вечера 1Gb файл (размер MPEG4 фильма не в самом лучшем качестве) не увенчалась успехом. Программа утром все еще читала - а мне идти на работу уже. В чем проблема? Наверное в использовании ArrayList<Integer> у которого внутри 1 миллиард элементов. Каждый элемент его занимает 16 байт минимум (Заголовок: 8 байт + Поле int: 4 байта + Выравнивание для кратности 8: 4 байта). Итого мы добровольно загоняем в память 16 Gb данных при размере оперативы в 8. Будем делать лучше. Нырнем в коллекции глубже. И ура, нашлось то, что нам нужно.

Встречаем TreeSet

  • не допускает хранение двух одинаковых элементов (а значит мы будем хранить в памяти все 255 элементов, вместо миллиарда!)
  • при манипуляциях со своими элементами автоматом упорядочивает (само сортирует - вот он, верх совершенства!)

Массив — побайтно

Имеем на выходе: 46Мб файл 158 секунд. 1Gb файл - 2 часа 55 минут. Опять улучшение, но небольшое. И мы сделали все простыми инструментами. Не использовали микроскоп для забивания гвоздей. Теперь лирическое отступление. Вспомним устройство компьютера. Память ОЗУ (DRAM) где обычно выполняется программа и хранятся переменные имеет высокую скорость доступа, но небольшой размер. Память на жестком/flash диске (HDD или Flash-накопители) где обычно хранятся файлы, наоборот имеет низкую скорость доступа, но большой размер. Так что когда мы побайтно читаем 1Gb файл (то есть миллиард раз обращаемся к HDD) - мы тратим много времени на работу с низкоскоростным устройством (по песчинке перекладываем песок с кузова КамАЗа в песочницу). Попробуем еще улучшить.

Читайте также: