Примеры работы с файлами на С, С++
Определение: Файл - это именованный блок информации, расположенный на носителе информации.
Любой файл обладает следующим рядом особенностей:
- Файл не может располагаться на диске непрерывно, однако пользователю файл предоставляется цельным блоком последовательной байтовой информации.
- Название файла не может содержать символы: < > : " / \ |.
- Большинство файлов обладает расширением - сочетанием символов, с помощью которых операционная система определяет тип файла. Расширение - необязательная часть.
- У каждого файла есть, так называемые атрибуты, которые, например, определяют уровни доступа к нему. Используя атрибуты, операционная система узнает, как нужно и, главное, можно, работать с данным файлом.
Термины:
- Дескриптор файла - уникальный номер, который операционная система присваивает любому открытому файлу, что бы отличать его от других. Когда файл закрывается, система "отбирает" у него дескриптор. Именно это уникальное число мы будем использовать для работы с конкретным файлом в наших программах.
- Файловый указатель - специальная переменная, которая автоматически присваивается открытому файлу и хранит текущую позицию в файле. Она перемещается по файлу в момент процессов записи и чтения. Для большего понимания, вы можете представить данную переменную в виде курсора в любом текстовом редакторе.
Существует несколько разновидностей файлов. В 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); }
📌 Для тестирования скриптов, установщиков VPN, Python ботов рекомендуем использовать надежные VPS на короткий срок. Если вам нужна помощь с более сложными задачами, вы можете найти фрилансера, который поможет с настройкой. Узнайте больше о быстрой аренде VPS для экспериментов и о фриланс-бирже для настройки VPS, WordPress. 📌
💥 Подпишись в Телеграм 💥 и задай вопрос по сайтам и хостингам бесплатно!
7 Самых Популярных Статей
- Как запустить скрипты и веб-приложения на Python
- Что такое страны TIER 1,2,3
- 7 способов сравнения файлов по содержимому в Windows или Linux
- Установка и тестирование веб-панели HestiaCP
- Китайский VPN Shadowsocks простая установка и настройка
- top, htop, atop определение загрузки ОС (Load average, LA)
- Использование rsync в примерах