Примеры работы с файлами на С, С++
Определение: Файл - это именованный блок информации, расположенный на носителе информации.
Любой файл обладает следующим рядом особенностей:
- Файл не может располагаться на диске непрерывно, однако пользователю файл предоставляется цельным блоком последовательной байтовой информации.
- Название файла не может содержать символы: < > : " / \ |.
- Большинство файлов обладает расширением - сочетанием символов, с помощью которых операционная система определяет тип файла. Расширение - необязательная часть.
- У каждого файла есть, так называемые атрибуты, которые, например, определяют уровни доступа к нему. Используя атрибуты, операционная система узнает, как нужно и, главное, можно, работать с данным файлом.
Термины:
- Дескриптор файла - уникальный номер, который операционная система присваивает любому открытому файлу, что бы отличать его от других. Когда файл закрывается, система "отбирает" у него дескриптор. Именно это уникальное число мы будем использовать для работы с конкретным файлом в наших программах.
- Файловый указатель - специальная переменная, которая автоматически присваивается открытому файлу и хранит текущую позицию в файле. Она перемещается по файлу в момент процессов записи и чтения. Для большего понимания, вы можете представить данную переменную в виде курсора в любом текстовом редакторе.
Существует несколько разновидностей файлов. В Windows таких разновидностей две: текстовый файл и бинарный (двоичный) файл.
Функции для работы с содержимым файла библиотеки языка C
Функции библиотеки stdio.h
fopen
FILE *fopen(const char *filename, const char *mode)
Функция открывает файл.
filename - путь к файлу
mode - тип доступа
r - чтение, если файла нет, то данная функция генерирует ошибку (возвращает 0) w - запись, если файла нет, то файл создаётся, если есть исходное содержимое удаляется a - добавление в конец, если файла нет, то он создаётся r+ чтение и запись (файл должен существовать) w+ - чтение и запись (принцип работы как у w) a+ - добавление и чтение (принцип работы как у a)
Если функция отработала успешно, из неё возвращается указатель на открытый файл, в противном случае - нуль.
fclose
int fclose( FILE *stream )
Функция закрывает файл.
stream - указатель на закрываемый файл.
Если всё проходит успешно, то данная функция возвращает 0, или EOF в случае ошибки.
char *fgets( char *string, int n, FILE *stream )
Считывает строку начиная с текущей позиции.
Считывание останавливается:
…если был найден символ перехода на новую строчку ( он помещается в строку ) …если достигнут конец файла …если считано n-1 символов. string - cтрока, в которую попадают считанные данные
n - количество элементов в string
stream - указатель на открытый файл
Если всё прошло успешно функция возвращает считанную строку, если произошла ошибка или достигнут конец файла возвращается 0.
int fputs( const char *string, FILE *stream )
Записывает строку в файл, начиная с текущей позиции.
string - строка для записи
stream - указатель на открытый файл, куда производиться запись
Если функция отрабатывает успешно из неё возвращается неотрицательное значение. При ошибке возвращается EOF.
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
Функция считывает данные из файла в буфер.
buffer - адрес массива, куда запишутся данные
size - размер элемента массива в байтах
count - максимальное количество элементов для считывания
stream - указатель на открытый файл.
Функция возвращает количество считанных байт.
Примечание: Тип данных size_t определен в библиотеке stdio.h следующим образом: typedef unsigned int size_t;. Другими словами, это обычный беззнаковый int.
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
Функция записывает массив данных в файл.
buffer - адрес массива, где содержатся данные
size - размер элемента массива в байтах
count - максимальное количество элементов для записи в файл
stream - указатель на открытый файл.
Функция возвращает количество записанных байт.
int feof( FILE *stream )
Функция проверяет достигнут ли конец файла.
stream - указатель на открытый файл
Функция возвращает ненулевое значение, если достигнут конец файла, нуль возвращается в противном случае.
int _fileno( FILE *stream )
Данная функция возвращает дескриптор файла.
stream - указатель на открытый файл.
int fseek ( FILE *stream, int offset [, int whence] )
Устанавливает смещение в файле
stream - указатель на открытый файл
offset - смещение, измеряемое в байтах от начала файла
whence - точка, от которой производится смещение
SEEK_SET (0) - начало файла SEEK_CUR (1) - позиция текущего указателя файла SEEK_END (2) - конец файла (EOF) Функция возвращает значение 0, если указатель файла успешно перемещен, и ненулевое значение в случае неудачного завершения.
Функции библиотеки io.h
_access
int _access( const char *path, int mode ) Функция определяет разрешения файла или директории.
- path - путь к файлу или директории
- mode - флаги для проверки
00 - проверка на существование 02 - проверка на разрешение на запись 04 - проверка на разрешение на чтение 06 - проверка на чтение и запись
Если разрешение есть, функция возвращает ноль, в случае отсутствия -1.
//проверить существует объект или нет? Если нет выйти из программы.
if (_access(str, 00)!=0){
cout<<"Object \""<<str<<"\" does not exist."<<"\n";
exit;
}
_filelength
long _filelength( int handle )
Возвращает размер файла в байтах.
handle - дескриптор файла.
В случае ошибки функция возвращает -1.
int _locking( int handle, int mode, long nbytes )
Блокирует или разблокирует байты файла начиная с текущей позиции в файле.
handle - дескриптор файла
mode - тип блокировки
_LK_LOCK - блокирует байты, если заблокировать байты не получается попытка повторяется через 1 секунду.Если после 10 попыток байты не заблокируются функция генерирует ошибку и возвращает -1 _LK_NBLCK - блокирует байты, если заблокировать байты не получается функция генерирует ошибку и возвращает -1 _LK_NBRLCK - то же самое, что и _LK_NBLCK _LK_RLCK - то же самое, что и _LK_LOCK _LK_UNLCK - разблокировка байт, которые были до этого заблокированы nbytes - количество байт для блокировки
Функция locking возвращает -1, если происходит ошибка и 0 в случае успеха.
Функции для работы с файлами и директориям
stdio.h - переименование и удаление файлов.
rename
rename (char * oldname, char * newname)
Переименовывает файл.
oldname - путь и текущее имя файла newname - путь и новое имя файла
Функция возвращает 0, если имя файла было успешно изменено, и ненулевое значение, если замена не произошла.
remove
int remove(const char * filename) Удаляет файл.
filename - путь и имя файла
Функция возвращает 0, если имя файл был успешно удален, и ненулевое значение, если удаление не произошло.
_chmod
Установка прав на файл.
#include <sys/stat.h> #include <io.h> _chmod( "test.txt", _S_IREAD ); // установить атрибут только для чтения на файл test.txt
_findfirst _findnext
- _findfirst(char * path, _finddata_t * fileinfo)
io.h - поиск файлов. Находит файлы по указанному пути, соответствующие маске.
Маска - строка, критерий поиска, содержащая символы * (любая последовательность любых символов) и ? (любой один символ) path - строка, в которой содержится комбинация пути и маски.
fileinfo - указатель на объект структуры , в который запишется информация о найденном файле. Структура _finddata_t содержит следующие поля:
unsigned attrib - содержит информацию об атрибутах файла. _A_NORMAL - Обычный файл без запретов на чтение или запись. _A_RDONLY - Файл только для чтения. _A_HIDDEN - Скрытый файл. _A_SYSTEM - Системный файл. _A_SUBDIR - Директория. _A_ARCH - Архивный файл. time_t time_create - время/дата создания файла (равно -1 для FAT систем). time_t time_access - время/дата последнего открытия файла (равно -1 для FAT систем). time_t time_write - время/дата последнего редактирования файла _fsize_t size - размер файла char name[260] - имя файла
Если всё пройдет успешно, информация о первом найденном файле запишется в объект структуры _finddata_t. При этом в оперативной памяти сформируется "список", обладающий внутренним указателем, который изначально будет установлен на первом найденном файле. В этом случае функция вернет уникальный номер, связанный с полученной группой файлов. Если поиск завершится неудачей, функция вернет -1.
- _findnext(long done, _finddata_t * fileinfo) Функция осуществляет переход на следующий найденный файл в группе.
done - уникальный номер группы файлов в памяти. fileinfo - указатель на объект структуры, в который запишется информация о следующем найденном файле. Если достигнут конец списка файлов, функция вернет -1.
- _findclose(long done) Функция очищает память от группы найденных файлов. done - уникальный номер группы файлов в памяти.
Как удалить файл?
- Если важна переносимость можно использовать класс boost/filesystem/operations.hpp
namespace boost
{
namespace filesystem
{
bool remove( const path & ph );
unsigned long remove_all( const path & ph );
}
}
BOOL DeleteFile(LPCTSTR lpFileName); CFile::Remove(LPCTSTR lpFileName);//Просто вызывает DeleteFile()
- Мне остается только назвать неназванный способ:
WINSHELLAPI int WINAPI SHFileOperation(LPSHFILEOPSTRUCT lpFileOp)
Для этого надо заполнить основные поля структуры SHFILEOPSTRUCT:
HWND hwnd; — родительское окно UINT wFunc; — в твоем случае FO_DELETE LPCSTR pFrom; — путь удаляемго файла (можно использовать маски!) FILEOP_FLAGS fFlags; — флаги; например OF_FILESONLY (мучить только файлы), OF_SILENT (не выводить индикатор) и др.
Там есть еще некоторые другие поля, разберешься. Подробнее читай Программист №1_2001 (http://www.programme.ru)
В чем преимущество этого способа: 1. Индикатор удаления. Если файлов много юзер сможет наблюдать виндосное окошко 2. Можно использовать маски в именах файлов
int _unlink( const char *filename );
Вывести атрибуты файла, директории
Программа выводит атрибуты файла или директории, переданные через командную строку.
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <io.h>
#include <ctime>
using namespace std;
int main(int argc, char** argv) {
if(argc==1) exit(1);
struct _finddata_t fileinfo;
char str[200];
strcpy(str,argv[1]);
long done = _findfirst(str, &fileinfo);
char szBuffer[30];
//Преобразование времени
ctime_s ( szBuffer, _countof (szBuffer),&fileinfo.time_write);
printf ( " %-24s %.24s %9ld ", fileinfo.name, szBuffer, fileinfo.size);
cout<<"\n";
printf( ( fileinfo.attrib & _A_SUBDIR ) ? "d" : "-" );
printf( ( fileinfo.attrib & _A_RDONLY ) ? "r" : "-" );
printf( ( fileinfo.attrib & _A_HIDDEN ) ? "h" : "-" );
printf( ( fileinfo.attrib & _A_SYSTEM ) ? "s" : "-" );
printf( ( fileinfo.attrib & _A_ARCH ) ? "a" : "-" );
printf( ( fileinfo.attrib & _A_NORMAL ) ? "n" : "-" );
cout<<"\n";
_findclose(done);
}
Пример программы на работу с файлами
// Здесь находятся функции переименования и удаления
#include <stdio.h>
// Здесь находятся функции для поиска файлов
#include <io.h>
#include <string.h>
#include <iostream>
using namespace std;
// для функции AnsiToOem
#include <windows.h>
// Переименовать существующий файл
void RenameFile();
// Удалить существующий файл
void RemoveFile();
// Поиск файлов в каталоге
void Dir();
void main()
{
// предлагаем выбрать пункт меню для выполнения
cout << "Please, select preffer number...\n";
//выбор пользователя
char ch;
do{
// Переименовать
cout << "\n1 - Rename\n";
// Удалить
cout << "2 - Remove\n";
// Просмотреть некоторую папку(каталог)
cout << "3 - View some folder\n";
// Выход
cout << "0 - Exit\n\n";
cin >> ch;
// анализируем и вызываем
// соответствующую функцию
switch(ch)
{
case '1':
RenameFile();
break;
case '2':
RemoveFile();
break;
case '3':
Dir();
break;
}
} while(ch != '0'); // Выход из программы
}
// Переименовать существующий файл
void RenameFile()
{
char oldName[50], newName[50];
// В одной переменной запомним существующее имя (oldName),
cout << "Enter old name:";
cin >> oldName;
// А в другой новое имя(newName)
cout << "Enter new name:";
cin >> newName;
// Произведем переименование и проверку результата
if (rename(oldName, newName) != 0)
cout << "Error!\n Couldn't rename file. Check old and new filename...\n\n";
else
cout << "Ok...\n\n";
}
// Удалить существующий файл
void RemoveFile()
{
char Name[50];
// Получаем имя и путь к удаляемому файлу
cout << "Enter name:";
cin >> Name;
//Удаляем файл и проверяем результат
if (remove(Name) != 0)
cout << "Error!\n Couldn't remove file. Check filename...\n";
else
cout << "Ok...\n" ;
}
// Поиск файлов в каталоге
void Dir()
{
// Запросим ПУТЬ (например, папка Temp на диске C, запишется
// таким вот образом: c:\temp\)
char path[70];
cout << "\nEnter full path (for example, C:\\):";
cin >> path;
// Запросим маску файлов
char mask[15];
cout << "\nEnter mask (for example, *.* or *.txt):";
cin >> mask;
// Соединив две строки, мы получим результат
// т.е. что хочет найти пользователь и где
strcat(path, mask);
// Объявление указателя fileinfo на структуру _finddata_t
// и создание динамического объекта структуры _finddata_t
_finddata_t *fileinfo=new _finddata_t;
// Начинаем поиск
long done = _findfirst(path,fileinfo);
// если done будет равняться -1,
// то поиск вести бесмысленно
int MayWeWork = done;
// Счетчик, содержит информацию о количестве найденых файлов.
int count = 0;
while (MayWeWork!=-1)
{
count++;
// перекодировали имя найденного файла
// на случай, если оно кириллическое
AnsiToOem(fileinfo->name,fileinfo->name);
// Распечатали имя найденного файла
cout << fileinfo->name << "\n\n";
// Пытаемся найти следующий файл из группы
MayWeWork = _findnext(done, fileinfo);
}
// Вывод сообщения о количестве найденных файлов.
cout << "\nInformation: was found " << count;
cout << " file(s) in folder..." << path << "\n\n";
// Очистка памяти
_findclose(done);
delete fileinfo;
}
Операции по работе с директориями
Библиотека direct.h
- int _mkdir( const char *dirname )
Создает директорию по указанному пути.
dirname - Путь и имя для создаваемой директории. В одно и то же время может быть создан только одна директория.
- int _rmdir( const char *dirname )
Удаляет директорию по указанному пути.
dirname - Путь и имя для удаляемой директории.
Обе функции возвращают -1 в случае ошибки.
Удалить и переименовать можно только пустую директорию!!!
Пример на работу с директориями.
#include <iostream>
#include <direct.h>
#include <stdio.h>
using namespace std;
// Переименовать существующую директорию
void RenameDirectory();
// Удалить существующую директорию
void RemoveDirectory();
// создать директорию
void CreateDirectory();
void main()
{
// предлагаем выбрать пункт меню для выполнения
cout << "Please, select preffer number...\n";
//выбор пользователя
char ch;
do{
// Переименовать
cout << "\n1 - Rename\n";
// Удалить
cout << "2 - Remove\n";
// Создать
cout << "3 - Create\n";
// Выход
cout << "0 - Exit\n\n";
cin >> ch;
// анализируем и вызываем
// соответствующую функцию
switch(ch)
{
case '1':
RenameDirectory();
break;
case '2':
RemoveDirectory();
break;
case '3':
CreateDirectory();
break;
}
} while(ch != '0'); // Выход из программы
}
// Переименовать существующую директорию
void RenameDirectory()
{
char oldName[50], newName[50];
// В одной переменной запомним существующее имя (oldName),
cout << "Enter old name:";
cin >> oldName;
// А в другой новое имя(newName)
cout << "Enter new name:";
cin >> newName;
// Произведем переименование и проверку результата
if (rename(oldName, newName) != 0)
cout << "Error!\n Couldn't rename directory.\n\n";
else
cout << "Ok...\n\n";
}
// Удалить существующую директорию
void RemoveDirectory()
{
char Name[50];
// Получаем имя и путь к удаляемой директории
cout << "Enter name:";
cin >> Name;
//Удаляем директорию и проверяем результат
if (_rmdir(Name) == -1)
cout << "Error!\n Couldn't remove directory.\n";
else
cout << "Ok...\n" ;
}
// Создать директорию
void CreateDirectory()
{
char Name[50];
// Получаем имя и путь к создаваемой директории
cout << "Enter name:";
cin >> Name;
//Создаем директорию и проверяем результат
if (_mkdir(Name) == -1)
cout << "Error!\n Couldn't create directory.\n";
else
cout << "Ok...\n" ;
}
Практический пример. Показ содержимого директории.
Пример программы осуществляющей показ содержимого директории. Программа при запуске показывает содержимое текущей директории, а затем дает пользователю возможность выбора. Ввести можно будет следующие команды:
cd Путь - переход в другую директорию.
cd .. - показ содержимого родительского каталога и переход. cd или cd . - показ содержимого текущего каталога. exit - выход из программы. root - переход в корневой каталог.
#include <iostream>
#include <windows.h>
#include <io.h>
#include <stdio.h>
using namespace std;
const int size=255;
// Функция, которая убирает лишние слеши и пробелы справа
void RemoveRSpacesAndRSlashes(char *str){
int index=strlen(str)-1;
while(str[index]=='\\'||str[index]==' '){
index--;
}
strncpy(str,str,index);
str[index+1]='\0';
}
// Функция для показа текущей директории
void ShowCurrentDir(char path[],char temp[]){
CharToOem(path,temp);
printf("%s>",temp);
}
// Функция перевода из кодировки
// Windows в кодировку DOS
// Для корректного отображения
// кирилицы
void RussianMessage(char path[]){
CharToOem(path,path);
}
// Показ на экран содержимого папки
bool ShowDir(char path[]){
// Показ содержимого текущей директории
_finddata_t find;
char pathfind[MAX_PATH];
strcpy(pathfind,path);
strcat(pathfind,"\\*.*");
char info[MAX_PATH];
// Начало Поиска
int result=_findfirst(pathfind,&find);
// Очистка экрана
system("cls");
int flag=result;
if (flag==-1) {
strcpy(info,"Такой Директории Нет");
RussianMessage(info);
printf("%s\n",info);
return false;
}
while(flag!=-1){
if(strcmp(find.name,".")&&strcmp(find.name,"..")){
// Проверяем Директория или Нет
find.attrib&_A_SUBDIR?strcpy(info," Каталог "):strcpy(info," Файл ");
RussianMessage(info);
RussianMessage(find.name);
printf("%30s %10s\n",find.name,info);
}
// Продолжаем Поиск
flag=_findnext(result,&find);
}
ShowCurrentDir(path,info);
// Очищаем ресурсы, выделенные под поиск
_findclose(result);
return true;
}
void main(){
// В данной переменной будет храниться путь к Директории
char path[MAX_PATH];
// В данной переменной будет команда, введенная пользователем
char action[size];
// Временная переменная
char temp[MAX_PATH];
// Получаем Путь к текущей Директории
GetCurrentDirectory(sizeof(path),path);
bool flag=true;
// Показ содержимого текущей директории
ShowDir(path);
do{
// Ввод команды пользователя
cin.getline(action,size);
// Убираем пробелы и слэши справа
RemoveRSpacesAndRSlashes(action);
// Переход в корневой каталог
if(!strcmpi(action,"root")){
path[2]='\0';
ShowDir(path);
}
// Проверка на желание пользователя выйти
else if(!strcmpi(action,"exit")){
flag=false;
}
// Проверка на команду cd
else if(!strnicmp(action,"cd",2)){
// Показ содержимого текущей директории
if((!strcmpi(action,"cd"))){
// Показ Директории
ShowDir(path);
}
// Команда cd была дана с параметрами
else if(!strnicmp(action,"cd ",3)){
// Находим индекс параметра
int index=strspn(action+2," ");
if(index){
// Проверка на полный путь к Директории
if(strchr(action+index+2,':')){
// Попытка отобразить содержимое Директории
if(ShowDir(action+index+2)){
strcpy(path,action+index+2);
}
else{
// Произошла Ошибка
ShowCurrentDir(path,temp);
}
}
// Поднимаемся в родительский каталог
else if(!strcmp(action+index+2,"..")){
char *result=strrchr(path,'\\');
if(result){
int delta=result-path;
strncpy(temp,path,delta);
temp[delta]='\0';
}
else{
strcpy(temp,path);
}
if(ShowDir(temp)){
strcpy(path,temp);
}
else{
// Произошла Ошибка
ShowCurrentDir(path,temp);
}
}
// Показ Директории
else if(!strcmp(action+index+2,".")){
ShowDir(path);
}
else if(!strcmp(action+index+2,"/")){
ShowDir(path);
}
else{
// Был Дан неполный путь
strcpy(temp,path);
strcat(temp,"\\");
strcat(temp,action+index+2);
// Попытка отобразить содержимое Директории
if(ShowDir(temp)){
strcpy(path,temp);
}
else{
// Произошла Ошибка
ShowCurrentDir(path,temp);
}
}
}
else{
// Показ Директории
ShowDir(path);
}
}
else{
// Показ Директории
ShowDir(path);
}
}
else{
// Показ Директории
ShowDir(path);
}
}while(flag);
}
📌 Удобный подбор VPS по параметрам доступен на DIEGfinder.com - официальном инструменте проекта DIEG. Это часть единой экосистемы, созданной для того, чтобы помочь быстро найти подходящий VPS/VDS сервер для любых задач хостинга.
📌 Для тестирования скриптов, установщиков VPN и Python-ботов рекомендуем использовать надежные VPS на короткий срок. Подробнее о быстрой аренде VPS для экспериментов - читайте здесь.
💥 Подпишись в Телеграм 💥 и задай вопрос по сайтам и хостингам бесплатно!7 Самых Популярных Статей
- Как запустить скрипты и веб-приложения на Python
- Что такое страны TIER 1,2,3
- 7 способов сравнения файлов по содержимому в Windows или Linux
- Установка и тестирование веб-панели HestiaCP
- Nginx простые примеры конфигурации
- top, htop, atop определение загрузки ОС (Load average, LA)
- Использование rsync в примерах
7 Самых Популярных Обзоров
- Хостинг для Python-скриптов и приложений
- ТОП 4 лучших антидетект браузеров (Бесплатные & Платные)
- Подборка купонов (промокоды) на хостинг, антидетект браузеры
- Обзор THE.Hosting (PQ Hosting): надежный хостинг с профессиональной поддержкой
- Хостинг в России
- Хостинг в Европе
- Обзор браузера Dolphin {anty} для мультиаккаунтинга