Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/34: Рейтинг темы: голосов - 34, средняя оценка - 4.88
57 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 235
1

Размер и выделение памяти под открытие файла.

09.09.2011, 10:36. Показов 6491. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.
Уважаемые знатоки, вопрос в следующем)

Значит задача такая, есть некий файл бинарный.
Размер не известный (компилятору). Я его открываю, читаю все что там есть и вывожу на экран.
Подскажите как определить размер этого файла и запихать все что там есть в буфер, который как раз будет динамическим (расширяемым в зависимости от размера файла)?
Ну а затем вывести все это на экран.
Привожу свой код ниже (буфер определяю статическим). Мне это не нужно.
P.S. В перспективе данные файла будут подаваться в реалтайме, поэтому по этому вопросу буду рад выслушать на будущее советы.
Пишу на C++, работаю с потоками поэтому fopen, seeks и т.д мне тоже не нужно.

Код.

Код
#include <fstream>
#include <iostream>

using namespace std;

const unsigned int buf_size = 0x4000; //вот тут задаю сам буфер

int main()
    {
		char *buffer;

        ifstream f_op("text", ios::binary);
        if (!f_op)
            cerr<<"Error file open";
        else
            cout<<"File open!!! Text this file:\n";

		buffer=new char(buf_size);

        while (!f_op.eof())
            {
            f_op.read((char *)buffer, 1); //читаю по одному байту, тоже плохо какие идеи? В идеале мне читать надо блочно по 4 байта например, для скорости обработки текста.
            cout<<*buffer;
            }
        f_op.close();

		delete buffer;
    }
Добавлено через 3 часа 22 минуты
Неужели нет никаких идей ни у кого?((
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.09.2011, 10:36
Ответы с готовыми решениями:

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

Оптимальное выделение памяти под считанные из файла строки
Пусть, например, у вас есть прикладная программа, которая считывает 1000 строк из файла и...

Выделение памяти под указатель
Нужно с помощью указателя изменить значение переменной в функции. Но под один из них не выделяется...

Выделение памяти под структуру
Доброго дня, товарисчи. В общем, возникла проблема при выделении памяти для структуры. Подскажите,...

16
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
09.09.2011, 10:44 2
Подскажите как определить размер этого файла
можно воспользоваться функцией stat() (объявлена в sys/stat.h). При вызове функции заполняется структура, которая содержит поле st_size - размер фаила в байтах.
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 10:59 3
C++
1
2
3
4
5
6
7
8
  ifstream in;
  in.open ("name.txt", ios::binary );
  
  in.seekg (0, ios::end); // Позиционируемся в конец файла
  size_t length = in.tellg(); // Узнаём позицию (= длина файла)
  in.seekg (0, ios::beg); // Позиционируемся обратно в начало
 
  buffer = new char [length];
0
Заблокирован
Автор FAQ
09.09.2011, 11:03 4
Цитата Сообщение от KorPaEv Посмотреть сообщение
Неужели нет никаких идей ни у кого?((
C++
1
2
3
4
5
6
7
8
9
ifstream f_op("text", ios::binary);
f_op.seekg(0,ios::end);//курсор вконец
long fLen = f_op.tellg();//получили позицию курсора, она равна длинне файла
f_op.seekg(0,ios::beg);//курсор вначало
 
char * str = new char[fLen + 1];//Буфер в размер файла
f_op.read(str,fLen);//Прочли весь файл в буфер
f_op.close()
str[fLen] = '\0';//Вконце строк всегда идёт мусор, отбрасываем его
Далее делай с str всё что хочешь...

Добавлено через 41 секунду
Блин опоздал...
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 11:07 5
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Блин опоздал...
А ещё и с потенциальной ошибкой. Файл может быть больше 4Гигабайт.
Впрочем и у меня с ошибкой. Я наивно предположил, что sizeof(size_t) == sizeof(pos_type).
1
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.09.2011, 12:36 6
KorPaEv, если файл over 4Gb, то у вас будут проблемы с выделением такого буфера. На 32-х системах это в принципе невозможно, на 64-х ещё такую память достать надо. Читайте порционно в небольшой буфер (4 Кб, например).

Добавлено через 5 минут
Не знаю на счёт pos_type, но старый добрый сишный fpos_t может учитывать огромные файлы (у меня определён как long long). Получается через ftell( FILE*, fpos_t* ). Но это ТСу, к сожалению, не подойдёт.
1
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 12:41 7
Цитата Сообщение от talis Посмотреть сообщение
Не знаю на счёт pos_type
С pos_type проблемы нет. Проблема есть с size_t, которую я использовал.

Цитата Сообщение от talis Посмотреть сообщение
Читайте порционно в небольшой буфер (4 Кб, например)
100% поддерживаю. Только буфер 64К, это минимальный считываемый блок с HDD, если я ничего не путаю.
0
57 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 235
09.09.2011, 12:42  [ТС] 8
ВСЕМ СПАСИБО ЗА ОТВЕТЫ! Не успел пораньше заглянуть и закончил сам))), все сделал так же...
Код
#include <fstream> //подключаем заголовок для работы с потоками ввода вывода
#include <iostream>

using namespace std;

int main()
    {
        //резервируем место под буфер
		char *buffer;
		//длинна файла
        int len_file;

        //поток на чтение из файла с параметром бинарника
        ifstream f_op;

        //открываем файл данных для чтения и проверяем открылся ли он
        f_op.open("text", ios::binary);
        if (!f_op)
            cerr<<"Error file open";
        else
            cout<<"File open!!! Text this file:\n";

        //ставлю курсор на конец файла без смещение (0)
        f_op.seekg(0, ios::end);
        //вычисляю кол-во байт до установленного курсора
        len_file=f_op.tellg();
        //помещаю курсор вначало файла
        f_op.seekg(0, ios::beg);

        //заводим массив вычисленной длинны файла
        buffer=new char [len_file];

        //читаю из буфера всю длинну файла
        f_op.read(buffer, len_file);
        //вывожу на экран буфер
        cout<<buffer;

        //закрываю файл
        f_op.close();

        //чистим память
		delete [] buffer;
		return 0;
    }
А по поводу чтения по 4 байта блочно не совсем еще понял, можно поподробнее?
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.09.2011, 12:45 9
KorPaEv, вы в игры играете? На жёстком есть образ DVD хотя бы одной игры (желательно больше 2 Gb)? Хотя в вашем случае с int и образа mini-CD хватит, упокой Господь их души. Попробуйте прочитать такой здоровый файл вашей прогой.
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 12:46 10
Цитата Сообщение от KorPaEv Посмотреть сообщение
А по поводу чтения по 4 байта блочно не совсем еще понял, можно поподробнее?
Ты не можешь создать массив размером более, чем есть свободной памяти (на самом деле, она ещё должна быть непрерывной, поэтому всё ещё хуже).
Можешь попробовать считать какой-нибудь большой файл (видео, например) и программа упадёт из-за невозможности выделить столько памяти.
Поэтому нужно считывать файл по частям и обрабатывать его содержимое последовательно, блоками.
0
57 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 235
09.09.2011, 12:50  [ТС] 11
Цитата Сообщение от talis Посмотреть сообщение
KorPaEv, вы в игры играете? На жёстком есть образ DVD хотя бы одной игры (желательно больше 2 Gb)? Хотя в вашем случае с int и образа mini-CD хватит, упокой Господь их души. Попробуйте прочитать такой здоровый файл вашей прогой.
Поправьте, если ошибаюсь. Читать надо блочно? Создаю константу буфера фиксированного размера - 4 байта и соответственно в цикле прогоняю все 2 Gb, по 4 байта в буфер? согласен повиснем надолго...

Тогда как поступить? Или я не понимаю чего то?
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 12:52 12
Цитата Сообщение от KorPaEv Посмотреть сообщение
по 4 байта в буфер?
Килобайта.))))

В буфер такого размера, на который точно хватит памяти. Мегабайт, десять, пятдесят. Но не стопицот.
0
57 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 235
09.09.2011, 12:56  [ТС] 13
Цитата Сообщение от Deviaphan Посмотреть сообщение
Ты не можешь создать массив размером более, чем есть свободной памяти (на самом деле, она ещё должна быть непрерывной, поэтому всё ещё хуже).
Можешь попробовать считать какой-нибудь большой файл (видео, например) и программа упадёт из-за невозможности выделить столько памяти.
Поэтому нужно считывать файл по частям и обрабатывать его содержимое последовательно, блоками.
Продублирую пост. Создаю константу буффер фиксированного размера 4 байта. В нее помечаю считанное. Тогда один момент не понятен, где будет храниться все данные файла? если мне нужно получить доступ скажем к средней его части? циклом считывать слишком медленно. Сам уже запутался короче(

Добавлено через 1 минуту
Цитата Сообщение от Deviaphan Посмотреть сообщение
Килобайта.))))

В буфер такого размера, на который точно хватит памяти. Мегабайт, десять, пятдесят. Но не стопицот.
Да)) деревянный еще, туплю)
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.09.2011, 13:00 14
Цитата Сообщение от KorPaEv Посмотреть сообщение
если мне нужно получить доступ скажем к средней его части?
загружаете среднюю часть в буфер

Добавлено через 10 секунд
ifstream::seekg()

Добавлено через 1 минуту
вообще, если вы решите, что вам нужно получить доступ к данным по определённому адресу в файле, значит, у вас есть некие данные, которые говорят, что вон по тому адресу лежит то, что тебе нужно. читаете подобную информацию в структуры
0
Заблокирован
Автор FAQ
09.09.2011, 16:15 15
Цитата Сообщение от KorPaEv Посмотреть сообщение
ВСЕМ СПАСИБО ЗА ОТВЕТЫ! Не успел пораньше заглянуть и закончил сам))), все сделал так же...

А по поводу чтения по 4 байта блочно не совсем еще понял, можно поподробнее?
Если данных у тебя много в консоль их сразу cout не выведешь, делай постепенный вывод
аля

C++
1
2
3
4
5
6
7
for(int i = 0,j; i < len_file;i += 4096)
{
   for(j = 0; j < 4096; j++)
        cout<<buffer[j];
   cout<<"\r\n";
   buffer += 4096;//Сдвигаем указатель на 4096
}
- как раз по 4кБ выводить будешь

f_op.read(buffer, len_file);
В buffer - не забывай ноль вконце buffer[ len_file] = '\0';
И закрывай поток сразу
f_op.close();
А потом уж выводи

Касательно размера файла - если ОЗУ хватает, то читай образ в оперативу а не ломай мозг постоянным считыванием из файла, время которое уйдёт на первоначальное время чтения 2 Гб с лихвой покроется постоянным почитыванием 4 кБ как тут "гуру" предлагают...Впрочем решать тебе, копошиться в файле с блошиным чтением или быстро обрабатывать данные из оперативной памяти!

Цитата Сообщение от talis Посмотреть сообщение
На жёстком есть образ DVD хотя бы одной игры (желательно больше 2 Gb)
- касательно этого вместо этого
//длинна файла
int len_file;
запиши
unsigned long len_file - как раз на 4096 Мб хватит
0
57 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 235
09.09.2011, 17:32  [ТС] 16
Спасибо еще раз всем за участие))) буду дерзать далее.
0
174 / 170 / 19
Регистрация: 31.08.2010
Сообщений: 573
10.09.2011, 15:46 17
На мой вгляд, Вам нужно посмотреть в сторону "Проецируемыемых в память файлов". Этот метод позволит не заморачиваться с выделением буферов, тем более, что система не даст выделить буфер размером 2 ГБ и более.

Более подробно можете почитать в книге "Джеффри Рихтер, Кристоф Назар - Windows via C/C++. Программирование на языке Visual C++" Глава 17. Проецируемые в память файлы
1
10.09.2011, 15:46
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.09.2011, 15:46
Помогаю со студенческими работами здесь

Выделение памяти под массивы
int **mas1 = new int*; for (int e = 0; e &lt; q; e++) mas1 = new int; int **mas2 = new...

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

Выделение памяти под картинку
Здравствуйте. Кто-нибудь знает как организовать копирование и вставку рисунка с экрана? Но без...

Выделение памяти под структуры
Компилятор выдает ошибку error: expected ‘{’ before ‘)’ token в выделенной строке ...

Выделение памяти под структуру
Как известно компилятор применяет выравнивание данных для структуры. Мне интересно, в том случае,...

Выделение памяти под структуру
#define SIZE 45 #include&lt;stdio.h&gt; struct film{ char title; int rating; };


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru