Зачем закрывать файл c
Я изучаю некоторые файловые функции и, следовательно, сомневаюсь.
Мне любопытно, почему необходимо вызывать close() , чтобы закрыть файл? Что может случиться, если я не позвоню close() после чтения / записи файла? И если я позвонил close() , могу ли я использовать файловый дескриптор?
Если файл имеет какую-либо буферизацию, и вы не вызываете close, вы потенциально можете потерять данные.
Если ОС имеет ограниченные ресурсы (например, количество открытых файлов), то, не закрывая файлы, вы тратите системные ресурсы впустую.
Использование дескриптора после закрытия файла в лучшем случае бессмысленно, в худшем - массивная ошибка (немного похоже на использование памяти после ее освобождения)
- Когда вы записываете в файл, который сначала записываете в буфер, некоторые функции вызывают сброс, и данные записываются в файл, а другие просто записывают в буфер. Когда буфер заполнен, он сбрасывается в файл без прямого вызова сброса. Вы также можете промыть, когда захотите, если хотите быть уверенным.
- И вы больше не можете использовать дескриптор файла после его закрытия.
Закрытие файла: после завершения работы с файлом его необходимо закрыть с помощью функции fclose ().
Закрытие файла очень важно, особенно для выходных файлов. Причина в том, что вывод часто буферизуется. Это означает, что когда вы говорите C что-то записать, например,
Он не обязательно сразу записывается на диск, но может оказаться в буфере в памяти. Этот выходной буфер будет временно хранить текст:
Пример буфера вывода:
(Несмотря на этот рисунок, буфер действительно одномерный.)
Когда буфер заполняется (или когда файл закрывается), данные, наконец, записываются на диск.
Когда вы записываете в файл с помощью системного вызова write (), запись в файл выполняется не сразу. Итак, после ваших операций вы должны вызвать close (), чтобы буфер был сброшен в файл и изменения сохранялись. После вызова close () вы не можете использовать дескриптор файла.
Если вы не закроете файл, открытый для чтения, он может быть заблокирован для одновременной записи. Если вы не закроете файл, открытый для записи, вы можете потерять часть последних записанных данных, которые ОС хранит в буфере.
И никогда не используйте дескриптор уже закрытого файла. В этом нет смысла.
Функция close () закрывает соединение между программой и открытым файлом, идентифицированным дескриптором. Все незаписанные системные буферы сбрасываются на диск, а системные ресурсы, используемые файлом, освобождаются .
Выделенная жирным шрифтом часть - основная причина, по которой файл должен быть закрыт.
Закрытие файла имеет следующие последствия:
1) Дескриптор файла освобожден.
2) Все блокировки записи, принадлежащие процессу в файле, разблокированы.
3) Когда все файловые дескрипторы, связанные с конвейером или FIFO, закрыты, все непрочитанные данные отбрасываются.
Зачем закрывать поток при записи в файл?
Надеюсь, я правильно задал вопрос темы. Просто плохо в этом разбираюсь. Задавал разные вопросы.
Зачем биты нужны это меньше байтов но int 32 бита но я не допер зачем это нужно это 4 байта то есть int не может больше 4 байт весить?
Вот еще один вопрос зачем биты нужны это меньше байтов но int 32 бита но я не допер зачем это.
Что такое h -файл и obj-файл?Зачем они нужны?
1.Что такое h -файл и obj-файл?Зачем они нужны?
4 Общий совет
Общий совет заключается в том, что не надо смешивать техники для работы с файлами.
Например, не надо в одной и той же программе использовать функции из стандартной библиотеки C ( fread / fwrite ) и классы-потоки из языка C++ ( istream / ostream ).
Если закомментить закрытие потока, то данные выведены не будут. Почему? Ведь поток же открыт напрямую в файл и выводит туда в реальном времени.
Зачем закрывать поток? (FileStream)
using System; using System.IO; class filestreamtest < static void Main(string args) .
Нужно записать файл в поток так, чтобы файл из потока можно было передать по TCP
Нужно записать файл в поток так, чтобы файл из потока можно было передать по TCP и открыть на.
StreamReader: когда закрывать поток и нужно ли это делать
Нужно ли закрывать постоянно? sr = new StreamReader("123.txt"); string a = sr.ReadToEnd();.
Записать данные в файл и просмотреть данные из файла
Протабулировать функцию y=sin(x + x2 ) для -2pi<=x<=2pi с шагом pi/10. Записать данные в файл и.
Работа с жестким диском — очень медленная операция, так как доступ к его памяти — механический, исчисляется миллисекундами.
Для того, чтобы на диск записывать по-реже, но по-больше за раз, данные сначала пишутся в буфер оперативной памяти, а когда буфер заполняется, все это разом сливается уже на диск.
Закрытие потока гарантирует, что любые данные, находящиеся в буфере и еще не записанные на диск, будут туда записаны.
Де? Недавно вот у Шилдта в той же главе читал, что метод Close() также запускает Flush().
Добавлено через 3 минуты
Работа с жестким диском — очень медленная операция, так как доступ к его памяти — механический, исчисляется миллисекундами.
Для того, чтобы на диск записывать по-реже, но по-больше за раз, данные сначала пишутся в буфер оперативной памяти, а когда буфер заполняется, все это разом сливается уже на диск.
Закрытие потока гарантирует, что любые данные, находящиеся в буфере и еще не записанные на диск, будут туда записаны.
Спасибо, так и думал.
Да, автор упоминал об этих моментах, однако очень уж вскользь и без пояснения на примере, и не говорил, что если не закрыть поток, то вообще никакие данные записаны не будут, говорил что могут не все.
Зачем нам закрывать открытый файл? Я знаю такие проблемы, как: другой процесс не может получить к нему доступ, если текущий процесс не закрывает его. Но почему в конце выполнения процесса ОС проверяет, закрыт ли он, и закрывает его, если открывается. Должна быть причина для этого.
Когда вы закрываете файл, буфер сбрасывается, и все, что вы в нем написали, сохраняется в файле. Если вы внезапно выйдете из программы, не сбросив (или не закрыв) свой FILE * stream , вы, вероятно, потеряете свои данные.
При записи в выходной файл информация хранится в буфере, и закрытие файла - это способ убедиться, что все отправлено в файл.
Таким образом, это просто хорошая практика. Вы не обязаны закрывать файлы в конце.
Вы что-то имеете против (или боитесь) закрытия файлов?
Конечно, к файлу может получить доступ другой процесс, пока он открыт одним. Некоторая семантика зависит от операционной системы. Например, в Unix два или более процесса могут одновременно открывать файл для записи. Почти все системы разрешают доступ только для чтения к нескольким процессам.
Вы открываете файл, чтобы подключить поток байтов к процессу. Вы закрываете файл, чтобы отключить их. Когда вы пишете в файл, он может не сразу измениться из-за буферизации. Это означает, что буфер памяти файла изменяется, но это изменение не сразу отражается в файле на диске. ОС будет отражать изменения на диске, когда на нем будет достаточно данных по соображениям производительности. Когда вы закроете файл, ОС сбросит изменения в файл на диске.
Два слова: истощение ресурсов. Дескрипторы файлов, независимо от платформы, - ограниченный ресурс. Если процесс просто открывает файл и никогда не закрывает его, у него скоро закончатся дескрипторы файлов.
Если вы «получили» ресурс, рекомендуется выпустить его, когда вы закончите.
Я думаю, что не стоит доверять тому, что O.S. будет делать, когда процесс закончится: он может освободить ресурсы или нет. Общие O.S. делает это: они закрывают файлы, освобождают выделенную память,
Но если это не является частью стандарта используемого вами языка (например, если он реализует сборщики мусора), вам не следует полагаться на это обычное поведение.
В противном случае существует риск того, что ваше приложение заблокирует / съест ресурсы в некоторых системах, даже если оно завершится.
2.3 Win32 API: FileCreate, FileRead , etc.
При работе с файлами в ОС Windows можно использовать все те функции, которые были описаны выше. В ОС Windows есть своя большая стандартная библиотека Win32 API . В этой библиотеке также есть функции для работы с файлами: например, функции FileCreate(. ) или FileOpen(. ) . Они по своей работе похожи на функции из стандартной библиотеки C, но отличия также присутствуют. Они заключаются в параметрах этих функций и небольших "хитростях", которые мы здесь опустим.
Если вы программируете под ОС Windows и пишите программу для работы в ОС Windows, то стоит пользоваться библиотекой Win32 API для работы с файлами.
2.2 Memory mapping. Что делает mmap
Следующий способ работы с файлами удобен в тех случаях, когда приходится читать файл нелинейно: надо "ходить" вперед и назад. В предыдущих подходах такие ситуации оказывались неудобными с точки зрения программирования: получился бы громоздкий код.
В языке C был придуман удобный способ работы в таких ситуациях, который называется memory mapping. Соответствующая функция:
Работает эта функция примерно так. Мы указываем этой функции файл на диске, и она "отображает" этот файл в такую-то область в памяти. В результате работы функции мы получаем указатель на начало файла. И потом мы можем работать с этим файлом как с обычным указателем на какую-то область памяти: можем "ходить" вперед и назад по этому файлу.
Можно "отобразить" не весь файл целиком, а, например, отдельную часть файла: с 3-его килобайта по 4-ый килобайт.
3.1 Глобальные переменные std::cout, std::cin, std::cerr
В header'е
В этом классе есть перегруженный оператор
В данном случае на экран будет выведена единица.
Еще в header'е объявлены переменные std::cin и std::cerr для стандартного потока ввода и потока ошибок соответственно. Они являются объектами классов std::istream и std::ostream соотсветственно.
Аналогично тому, как stderr отличается от stdin , в языке C++ std::cerr отличается от std::cout отсутствием буферизации.
В классе std::istream есть перегруженный оператор >>. Можно считывать информацию из стандартного потока ввода (с клавиатуры).
1.1 Чтение и запись: printf и scanf
Всем хорошо известная функция printf :
printf("Hello!") -- печать текста на экран;
printf("N = %d", N) -- форматированный вывод на экран: вывести число N в десятичной записи;
printf("N = %x", N) -- форматированный вывод на экран: вывести число N в шестнадцатеричной записи;
Аналогично парная функция scanf :
char *ptr = new char[10];
scanf("%s", ptr); -- считывание с клавиатуры строки в массив *ptr
char *ptr = new char[10];
scanf("%s", ptr);
Тут налицо потенциальная проблема переполнения буфера (в данном примере в буфере всего 10 байт).
Никогда не следует пользоваться scanf 'ом для чтения строк.
1 Ввод и вывод, язык C, структура FILE
3.4 Работа с файлами
Классами для работы с файлами в языке C++ являются ifstream, ofstream и fstream .
Код для открытия файла и его чтения выглядит примерно так:
ifstream ifs;
ifs.open("file1.txt");
// далее с помощью оператора >> можно читать из файла, если он успешно открылся;
Аналогично можно использовать конструктор с параметром: ifs("file1.txt"); после чего создается объект и открывается по возможности файл.
В классе istream есть метод close() , который закрывает файл (на подобие работы с файлами в языке C). Однако вызывать этот метод необязательно. Дело в том, что в деструкторе класса этот метод вызовется автоматически.
Работа с объектами классов ofstream и ofstream и fstream осуществляется по аналогичному сценарию.
Решение
А вспомни Win 3.11 и 95.
там под оконные переменные (внутренние, не только дескрипторы) было 64к всего.
так что экономить надо.
как то препод показывал программу, которая размером в 270 байт спутником управляла.
А сейчас что? :)
По теме:
Закрывают файл для того, чтобы освободить к нему доступ, записать несохраненные изменения. Просто после окончания его использования.
Если про конец программы. А если ты не освободишь файл, а потом программу дописывать будешь? вот тебе и утечка ресурсов в общем виде.
SatanaXIII, нормальное правило, у меня был случай падения проекта(запущенного в работу)из-за забытого закрытия файла
ну я в работе с файлами не очень шарю. Но если например программа постоянно работает, и открывает файлы чтото там делает. Не закрывая файл после накапливается в памяти все открытие файлы и будет все висеть или вообще вылетит. Мое предположение
Бред. Запись в файловый поток - это запись именно в долговременную память и никаким переполнением оперативной она не воняет. Просто эта запись кешируется в буфере, физически расположенном в оперативе, но всё, что в этот буфер не влезает, сохраняется на диск. Открыть же новый файл под старым потоком, не закрыв ранее открытый и при это ещё и сохранив в оперативе кеш старого файла невозможно. Закрытие же файла - это всего лишь явное указание выполнить фактическую запись в долговременную память последней порции информации из буфера.
Интуитивное определение файла звучит примерно так. Файл -- именованная область на жестком диске. На самом деле с точки зрения ОС UNIX это совсем не так. В ОС UNIX файл -- очень удобная абстракция. С точки зрения UNIX файлом называется "что-нибудь", из чего можно считывать информацию или во что можно записывать информацию. Файлы это:
- Файлы в обычном смысле: файлы, которые хранятся на жестком диске (можно считывать из них и запиcывать в них информацию);
- Экран монитора: файл, в который можно выводить информацию (отобразится на экране монитора);
- Клавиатура: файл, из которого можно считывать информацию;
- Принтер: файл, в который можно выводить информацию (печать текста);
- Модем: файл, из которого можно считывать информацию и в который можно записывать информацию (обмен информации по сети);
3.6 Иерархия классов
0.2 Разделение понятий файла и названия
Неправильно думать, что между сущностями "файл" и "название файла" есть взаимно однозначное соответствие.
Можно привести аналогию из жизни: если представить, что файл -- это банка с некоторым содержимым, то название файла -- это этикетка на этой банке. Логично предположить, что у банки может быть несколько этикеток.
С точки зрения UNIX:
Правильно говорить, что у названия есть файл. И наоборот: неправильно говорить, что у файла есть название. Никакого эффективного способа узнать имя файла не существует (но можно перебрать все файлы файловой системы).
1.2 Чтение и запись файлов: FILE* , fopen , fprintf , fscanf
Есть несколько способов работы с файлами c использованием языков C и C++.
Самый распространенный связан со структурой FILE (это не класс, потому что сущность языка C). Эта структура определена в заголовочном файле стандартной библиотеки . Размер этой структуры и ее поля зависят от ОС и от версии компилятора. Поэтому никто не пользуется структурой FILE . Обычно пользуются указателем на эту структуру: FILE* . Например:
FILE *f = fopen("file1.txt", "r");
- не существует файла;
- у программы недостаточно прав доступа для работы с файлом;
Для дальнейшей корректной работы следует писать примерно такой код:
if (f == NULL) // файл не удалось открыть
>
else // Работа с файлом
>
Допустим, что нам удалось открыть файл, т.е. f != NULL . Тогда для того, чтобы считывать файл, можно использовать функцию:
Эта функция работает аналогично функции scanf . Поэтому использовать эту функцию небезопасно! Все проблемы, перечисленные для scanf 'а, имеют место и при работе с fscanf 'ом.
Если мы хотим записать в файл что-то, то мы должны сначала открыть его на запись:
FILE *f = fopen("file2.html", "w");
Тут "w" означает, что мы открываем файл на запись (от write). Если файл не существовал, то он создастся и откроется на запись, а если он существовал, то он сначала будет уничтожен, а затем создан заново, и потом файл будет открыт на запись.
Еще один способ открыть файл -- это открыть его на дозапись. Это можно сделать с помощью параметра "a" (от append). Если файл не существовал, то он создастся и откроется на запись, а если он существовал, то он откроется на запись, и запись будет производится в конец файла.
Затем можно использовать функцию fprintf(f, . )
1.2.1 Зачем нужно закрывать файлы
- Зададимся вопросом: "Что надо сделать после того, как мы поработали с файлом?"
Формальный ответ: "Закрыть файл." Это можно сделать с помощью функции:
fclose(f);
Но зачем это делать?
Ввиду механического устройства жесткого диска, данные в файл попадают не сразу. Сначала данные записываются в так называемый буфер (область оперативной памяти), и когда он переполнится, то данные из буфера будут записаны в файл. Такая схема придумана для ускорения работы с файлами. На самом деле, буфер -- это поле структуры FILE : указатель на массив char 'ов.
1.2.2 Важность буфера при работе с файлами
- Рассмотрим следующую ситуацию. Программа пишет протокол своих действий в файл (например, с помощью функции fprintf ). Допустим, что программа сломалась. Понятно, что скорее всего получится так, что в файл последний fprintf (последний протокол действий) не запишется. Причина тому -- это буфер.
Чтобы "протолкнуть" буфер в файл, используется функция
В коде это выглядит примерно так:
Решение
Unifan, А почему бы и нет? Несмотря на то, что в деструкторе он все равно закроется, можно закрыть и явно.
Например дабы переоткрыть с другим файлом, либо же сохранить изменения, которые будут читать сразу после закрытия файла, да много вариантов использования.
ну я в работе с файлами не очень шарю. Но если например программа постоянно работает, и открывает файлы чтото там делает. Не закрывая файл после накапливается в памяти все открытие файлы и будет все висеть или вообще вылетит. Мое предположение
если stream это объект fstream/ifstrea/etc то можно и не закрывать, оно закроется в деструкторе. для чего это надо? на каждый открытый файл ОС выделяет дескриптор по которому идентифицируется этот файл в программе и все операции в программе с этим дескриптором производят соответствующие действия с файлом.
дескриптор этот - это просто число, закрытие файла подразумевает завершение всех операций с файлом и возвращение дескриптора обратно ОС чтобы та в свою очередь могла выдать его при следующем открытии файла.
К тому же close() еще проталкивает всю незаписанную информацию из внутренних буферов потоковых объектов в место назначения.
на каждый открытый файл ОС выделяет дескриптор по которому идентифицируется этот файл в программе и все операции в программе с этим дескриптором производят соответствующие действия с файлом.
дескриптор этот - это просто число, закрытие файла подразумевает завершение всех операций с файлом и возвращение дескриптора обратно ОС чтобы та в свою очередь могла выдать его при следующем открытии файла.
0.3 Функции link и unlink
Пусть есть файл file1.txt . Для его удаления используется функция:
int unlink(const char* filename);
Эта функция не всегда удаляет файл (с жесткого диска), а только удаляет "этикетку" этого файла. Если есть другая "этикетка" этого файла, то файл останется на жестком диске; просто у него уже не будет этой "этикетки". Файл знает, сколько у него таких "этикеток" (есть специальный счетчик). И если этот счетчик стал равен нулю, то функция удаляет файл с жесткого диска. В ОС Windows эта функция всегда удаляет файл.
Парная функция к этой функции:
int link(const char* filename1, const char* filename2);
Эта функция создает еще одну "этикетку" для этого файла и прибавляет к значению счетчика "этикеток" единицу.
1.5 Как же читать/писать на самом деле: fgets , fread и fwrite
Использование функций ptintf и scanf для записи и для чтения -- это очень плохая идея. Тогда все-таки как лучше читать и записывать?
Хороший способ чтения из файла дает функция fgets() (от "get string"):
char *fgets(char *buffer, size_t length, FILE *file);
- buffer -- это указатель на буфер, в который мы читаем;
- length -- это размер буфера;
- file -- это файл, из которого мы читаем (если читаем с клавиатуры, то разумно использовать stdin ).
- Функция возвращает строку
Налицо быстрота и безопасность. Главное отличие от scanf 'а заключается в том, что функция перестанет читать в тот момент, когда закончится буфер. Быстрота обусловлена тем, что функция scanf должна в момент выполнения разобрать форматную строку, в то время как fgets просто читает строку.
1.5.1 Как доставать числа? Семейство atoi, sscanf
В то время как фунция fgets читеат обычную строку, функция scanf может читать и различные другие типы (целые, вещественные числа).
В языке C есть семейство функций ~ atoi (a -- ASCII , i -- integer ):
Функция принимает единственный параметр строку и пытается ее привести в типу int . Надо заметить, что функция atoi безопасная, но не очень удобная. Безопасная в том смысле, что не сломается: atoi("25a") == 25 . "Неудобства" заключаются в том, то если мы передаем в качестве параметра строку, в которой есть не только числа, нужно быть очень внимательным и знать, как работает эта функция. Функция atoi никак не проинформирует нас, если преобразование прошло неудачно.
Например, atoi("abc") == 0 , что на самом деле не совсем соостветствует действительности. Использовать функцию atoi нужно лишь в том случае, когда вы уверены, что в строке есть число.
Родственные функции: atol, atoll, atof, strtol .
Им соответствуют функции для преобразования в типы long , long long и float .
Рассмотрим подробнее strtol :
long strtol(char *buffer, char **endPtr, int base);
- buffer -- это указатель на буфер, из которого мы читаем;
- endPtr -- это переменная, которая используется для того, чтобы сообщить нам насколько успешно произошло преобразование;
это указатель на char * , в котором записан первый символ, который не смог проинтерпретироваться с помощью функции strtol ;
Применение выглядит примерно так:
char *end;
char *ptr = "25a";
int N = strtol(ptr, &end, 10);
Теперь end указывает на "a".
if (ptr == end) <
// ничего не получилось прочитать
>
Более мощное средство
Есть более мощное средство, чем нежели fgets + atoi . Речь идет о функции sscanf .
Вместо использования функции fscanf(f, "%d", &N) можно использовать связку:
fgets(ptr, 100, f);
sscanf(ptr, "%d", &N);
В чем преимущество и мощность такого подхода?
- Мы знаем длину того, что мы прочитали;
- Рассмотрим следующую ситуацию: мы хотим прочитать какие-то данные, но не смогли из-за ошибки.
1.5.2 fread и fwrite
На самом деле не все файлы выглядят как текст. Файле могут быть записаны числовые данные.
size_t fread(void *ptr, size_t size, size_t nelts, FILE *f);
- void *ptr -- указатель на ту область памяти, в которую мы читаем;
- size_t size -- размер элемента, который мы читаем;
- size_t nelts -- максимальное количество элементов, которые можно записать;
- FILE *f -- файл, из которого читаем;
- size_t fread() -- сама функция возвращает количество элементов, которые удалось прочитать.
size_t fwrite(const void *ptr, size_t size, size_t nelts, FILE *F);
Аналогично fread эта функция возвращает количество элементов, которые удалось записать.
Тут параметр nelts просто показывает, сколько элементов надо вывести.
3 Ввод и вывод в языке C++, потоки
В языке C++ объекты для работы с файлами называются потоками (streams). В данном случае слово "поток" означает то же самое, что и "файл" в языке C.
Классы для работы с файлами в языке C++ называются std::istream и std::ostream для ввода и вывода соответственно.
3.3 Операторы >
- &os -- поток, в который мы будем выводить;
- N -- переменная, которую мы будем выводить;
- Оператор возвращает ссылку на поток, в результате чего можно писать так: std::cout
В случае оператора >> все аналогично.
Если у нас есть класс комплексных чисел Complex , то вывод этих чисел через оператор
3.5 Класс stringstream
Класс stringstream наследуется от iostream .
Используется этот для класс для следующих целей. Если мы хотим выводить комплексные числа не только на экран или в файл, но и в окно какой-нибудь программы (GUI), то как использовать stringstream ? При этом мы не хотим писать один и тот же код программы.
Можно просто печатать в строку с помощью stringstream .
2 Другие подходы для работы с файлами
1.6 Другие полезные опции: fseek и ftell
Для файлов, которые открыты на чтение есть полезные функции. Одна из них это:
int fseek(FILE *f, long offset, int flag);
- FILE *f -- файл, в котором передвигаемся;
- long offset -- количество байтов для отступа, отступ производится в соответствии с 3-м параметром;
- int flag -- позиция, от которой будет совершен отступ; в стандартной библиотеке C для этого параметра определены 3 константы:
SEEK_SET -- начало файла;
SEEK_CUR -- текущас позиция;
SEEK_END -- конец файла;
long int ftell(FILE *f);
2.1 File descriptors. Open, close, read, write
В языке C есть много способов работы с файлами. Помимо структуры FILE можно использовать так называемые дескрипторы файла (file descriptors). Дескриптор файла -- целое неотрицательное число. Оно обозначает номер открытого файла в таблице открытых файлов операционной системы. Использование дескрипторов файла -- более низкий уровень, чем нежели ипользование струкруты FILE. Структура FILE -- сущность языка C и его стандартной библиотеки, тогда как дескриптор файла -- сущность операционной системы. Например, при работе со структурой FILE автоматически создается буфер, и программист работает с более высокоуровневой абстракцией. А при работе с дескрипторами файла программист должен позаботится о буферизации вручную.
Пример работы с дескрипторами файла довольно прост и почти в точности повторяет процесс работы со структурой FILE:
Сходство работы с дескрипторами файла с работой со структурой FILE заключается в том, что в названии функций отсутствует буква "f" . Иногда параметры функций незначительно отличаются.
Структуру FILE полезно использовать при работе с настоящими "файлами" (которые находятся на жестком диске). Ипользовать дескрипторы файла полезно в случаях работы со специальными "файлами". В этом подходе есть своя специфика работы, но сейчас просто полезно знать, что такой подход существует.
Аналогами stdin, stdout и stderr в дескрипторах файла являются числа 0, 1 и 2 соответственно. Стандарт POSIX.1 обозначил числа 0, 1, 2 символическими константами STDIN_FILENO, STDOUT_FILENO и STDERR_FILENO соответственно.
1.3 Стандартные уже открытые файлы: stdin, stdout, stderr
С точки зрения UNIX клавиатура и экран -- это файлы.
Есть три стандартные константы:
FILE *stdin
FILE *stdout
FILE *stderr
Это три стандартных заранее открытых файла.
stdin -- это стандартный файл (поток) ввода, а stdout -- стандартный файл (поток) вывода. Таким образом:
scanf(. ) в точности эквивалентно fscanf(stdin, . )
printf(. ) в точности эквивалентно fprintf(stdout, . )
Такой гибкостью можно воспользоваться при написании программы для работы с файлами. Например, для отладки программы можно выводить информацию на экран монитора, а не в файл. Для этого в начале работы с файлом пишем две строчки:
//FILE *f = fopen(. );
FILE *f = stdin;
При этом код программы будет содержать такие функции: fscanf(f, . ) или fprintf(f, . ) . А когда отладка законичится, просто снимаем/ставим соответствующие комментарии в двух строчках программы.
stderr -- это стандартный файл (поток) ошибок. По умолчанию выводит данные на экран.
Но существует заметное отличие этого "файла" от stdin и stdout : stderr -- небуферизованный файл (поток). Поэтому в этот файл (поток) все байты уходят без "задержки", которая могла бы возникнуть при буферизированном подходе. Понятно, что польза от этого подхода заключается в том, что вместо кода:
3.2 Форматированный вывод возможен: std::ios::hex
Возможен ли форматированный вывод, которым мы пользовались в языке C фунцией printf() ? Наример, как вывести ту же переменную N в 16-ой записи?
В языке C++ форматированный вывод возможен при помощи вывода на экран специальной управляющей команды:
В точности то же самое выведет команда printf("%x", N);
Чтобы не писать перед кажой переменной ее формат, можно использовать функцию:
Она установит формат вывода в стандартный поток вывода на экран. Этот подход настолько же мощный, как и использование форматной печати с помощью printf .
1.4 Текстовые и бинарные файлы; что меняет опция t/b
fopen(f, "file1.txt", "w");
Почему второй параметр "w" является строкой, а не символом?
На самом деле бывает много способов прочитать/записать файл. Например:
fopen("file1.txt", "wt") -- откроет файл как текстовый файл;
fopen("file1.txt", "wb") -- откроет файл как бинарный файл.
Но в чем отличие?
Разница заключается лишь в том, что символы переноса строк запишутся по разному.
Рассмотрим пример в UNIX и Windows:
Исходная строка кода выглядит так: fprintf("Hello\n");
-
Откроем в Windows файл на запись с параметром "wb" (как бинарный файл). Это означает, что в него запишется в точности то, что мы передали в функции fprintf . Тогда в файл запишутся ровно 6 байт: Hello\10
Читайте также: