Введение
В этой лабораторной работе вы научитесь выполнять различные операции с файлами в C++. Лабораторная работа охватывает открытие файлов для чтения и записи, запись текстовых данных в файлы, чтение данных из текстовых файлов, проверку статуса открытия файла, обработку ошибок чтения/записи файлов, работу с бинарными файлами, позиционирование указателя файла и закрытие файлов для освобождения ресурсов. Вы получите практический опыт использования основных классов файловых потоков ofstream и ifstream из стандартной библиотеки C++ для взаимодействия с файлами. К концу этой лабораторной работы у вас будет прочное понимание обработки файлов в программировании на C++.
Открытие файлов с использованием ofstream и ifstream
На этом шаге вы узнаете, как открывать файлы в C++ с использованием двух основных классов файловых потоков: ofstream для записи в файлы и ifstream для чтения из файлов. Эти классы являются частью стандартной библиотеки C++ и предоставляют основные возможности для работы с файлами.
Сначала перейдите в каталог проекта в терминале WebIDE:
cd ~/project
Создайте новый C++ файл с именем file_operations.cpp:
touch file_operations.cpp
Добавьте следующий код в файл file_operations.cpp:
#include <iostream>
#include <fstream> // Подключение заголовочного файла файловых потоков
int main() {
// Открытие файла для записи с использованием ofstream
std::ofstream outputFile("example.txt");
// Проверка успешности открытия файла
if (outputFile.is_open()) {
std::cout << "File opened for writing successfully!" << std::endl;
outputFile.close(); // Закрытие файла
} else {
std::cout << "Unable to open file for writing." << std::endl;
}
// Открытие файла для чтения с использованием ifstream
std::ifstream inputFile("example.txt");
// Проверка успешности открытия файла
if (inputFile.is_open()) {
std::cout << "File opened for reading successfully!" << std::endl;
inputFile.close(); // Закрытие файла
} else {
std::cout << "Unable to open file for reading." << std::endl;
}
return 0;
}
Разберем ключевые концепции:
#include <fstream>: Подключает библиотеку файловых потоковstd::ofstream: Поток вывода в файл (Output File Stream) для записи в файлыstd::ifstream: Поток ввода из файла (Input File Stream) для чтения из файловis_open(): Проверяет, был ли файл успешно открытclose(): Закрывает файл после завершения операций
Скомпилируйте программу:
g++ file_operations.cpp -o file_operations
Запустите исполняемый файл:
./file_operations
Пример вывода:
File opened for writing successfully!
File opened for reading successfully!
Некоторые важные моменты о файловых потоках:
- Всегда проверяйте, успешно ли открыт файл, прежде чем выполнять операции
- Не забывайте закрывать файлы после того, как закончили их использование
ofstreamиспользуется для записи в файлыifstreamиспользуется для чтения из файлов- Оба класса являются частью заголовочного файла
<fstream>
Вы можете представить файловые потоки как открытие и закрытие дверей в файлы. ofstream позволяет вам писать в комнату, в то время как ifstream позволяет вам читать то, что находится внутри.
Запись текстовых данных в файлы
На этом шаге вы узнаете, как записывать текстовые данные в файлы с использованием класса ofstream в C++. Развивая материал предыдущего шага, вы изучите различные способы записи строк, чисел и нескольких строк в файлы.
Создайте новый C++ файл с именем write_files.cpp:
touch ~/project/write_files.cpp
Добавьте следующий код в файл write_files.cpp:
#include <iostream>
#include <fstream>
#include <string>
int main() {
// Открытие файла для записи
std::ofstream outputFile("student_data.txt");
// Проверка успешности открытия файла
if (outputFile.is_open()) {
// Запись одной строки
outputFile << "John Doe" << std::endl;
// Запись нескольких фрагментов данных
std::string name = "Alice Smith";
int age = 22;
double gpa = 3.75;
outputFile << name << ", " << age << " years old, GPA: " << gpa << std::endl;
// Запись нескольких строк
outputFile << "Computer Science Student" << std::endl;
outputFile << "University of Programming" << std::endl;
// Закрытие файла
outputFile.close();
std::cout << "Data written to file successfully!" << std::endl;
} else {
std::cout << "Unable to open file for writing." << std::endl;
}
return 0;
}
Скомпилируйте программу:
g++ write_files.cpp -o write_files
Запустите исполняемый файл:
./write_files
Пример вывода:
Data written to file successfully!
Проверьте содержимое файла:
cat student_data.txt
Пример содержимого файла:
John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming
Ключевые моменты о записи в файлы:
- Используйте оператор
<<для записи данных в файлы std::endlдобавляет новую строку- Можно записывать строки, числа и переменные
- Всегда проверяйте, открыт ли файл, перед записью
- Закрывайте файл после операций записи
Вы можете представить запись в файлы как ведение записей в блокноте. ofstream — это ваша ручка, а файл — это страница, на которой вы фиксируете информацию.
Чтение данных из текстовых файлов
На этом шаге вы узнаете, как читать данные из текстовых файлов с использованием класса ifstream в C++. Развивая материал предыдущих шагов, вы изучите различные методы для чтения строк, слов и содержимого целых файлов.
Создайте новый C++ файл с именем read_files.cpp:
touch ~/project/read_files.cpp
Добавьте следующий код в файл read_files.cpp:
#include <iostream>
#include <fstream>
#include <string>
int main() {
// Открытие файла, созданного на предыдущем шаге
std::ifstream inputFile("student_data.txt");
// Проверка успешности открытия файла
if (inputFile.is_open()) {
// Чтение целой строки
std::string line;
std::cout << "Reading entire lines:" << std::endl;
while (std::getline(inputFile, line)) {
std::cout << line << std::endl;
}
// Сброс указателя файла в начало
inputFile.clear();
inputFile.seekg(0, std::ios::beg);
// Чтение отдельных слов
std::cout << "\nReading individual words:" << std::endl;
std::string word;
while (inputFile >> word) {
std::cout << word << " ";
}
std::cout << std::endl;
// Закрытие файла
inputFile.close();
} else {
std::cout << "Unable to open file for reading." << std::endl;
}
return 0;
}
Скомпилируйте программу:
g++ read_files.cpp -o read_files
Запустите исполняемый файл:
./read_files
Пример вывода:
Reading entire lines:
John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming
Reading individual words:
John Doe Alice Smith, 22 years old, GPA: 3.75 Computer Science Student University of Programming
Ключевые моменты о чтении файлов:
- Используйте
std::getline()для чтения целых строк - Используйте оператор
>>для чтения отдельных слов clear()иseekg()сбрасывают указатель файла- Всегда проверяйте, открыт ли файл, перед чтением
- Закрывайте файл после операций чтения
Вы можете представить чтение файлов как извлечение информации из книги. ifstream — это ваша закладка, помогающая ориентироваться в тексте.
Проверка статуса открытия файла
На этом шаге вы узнаете, как проверять состояние файловых операций в C++ с использованием различных методов для подтверждения того, что файлы успешно открыты и готовы к чтению или записи.
Создайте новый C++ файл с именем file_status.cpp:
touch ~/project/file_status.cpp
Добавьте следующий код в файл file_status.cpp:
#include <iostream>
#include <fstream>
#include <string>
int main() {
// Попытка открыть существующий файл для чтения
std::ifstream inputFile("student_data.txt");
// Метод 1: Использование is_open() для проверки состояния файла
if (inputFile.is_open()) {
std::cout << "File opened successfully for reading." << std::endl;
// Выполнение операций чтения
std::string line;
while (std::getline(inputFile, line)) {
std::cout << "Read line: " << line << std::endl;
}
inputFile.close();
} else {
std::cout << "Failed to open file for reading." << std::endl;
}
// Метод 2: Использование good() для проверки состояния файла
std::ofstream outputFile("test_status.txt");
if (outputFile.good()) {
std::cout << "File opened successfully for writing." << std::endl;
outputFile << "Testing file status" << std::endl;
// Дополнительные проверки состояния
if (outputFile) {
std::cout << "File is in a good state for writing." << std::endl;
}
outputFile.close();
} else {
std::cout << "Failed to open file for writing." << std::endl;
}
// Метод 3: Несколько методов проверки состояния
std::ifstream checkFile("non_existent_file.txt");
std::cout << "File status checks:" << std::endl;
std::cout << "is_open(): " << (checkFile.is_open() ? "True" : "False") << std::endl;
std::cout << "good(): " << (checkFile.good() ? "True" : "False") << std::endl;
std::cout << "fail(): " << (checkFile.fail() ? "True" : "False") << std::endl;
return 0;
}
Скомпилируйте программу:
g++ file_status.cpp -o file_status
Запустите исполняемый файл:
./file_status
Пример вывода:
File opened successfully for reading.
Read line: John Doe
Read line: Alice Smith, 22 years old, GPA: 3.75
Read line: Computer Science Student
Read line: University of Programming
File opened successfully for writing.
File is in a good state for writing.
File status checks:
is_open(): False
good(): False
fail(): True
Ключевые моменты о проверке состояния файла:
is_open(): Проверяет, был ли файл успешно открытgood(): Проверяет, не возникло ли ошибокfail(): Проверяет, возникла ли ошибка- Всегда проверяйте состояние файла перед выполнением операций
- Различные методы предоставляют разные способы проверки состояния файла
Вы можете рассматривать проверки состояния файла как инспекцию безопасности перед поездкой. Эти методы помогают убедиться, что ваши файловые операции безопасны и успешны.
Обработка ошибок чтения/записи файлов
На этом шаге вы узнаете, как обрабатывать потенциальные ошибки, которые могут возникнуть при операциях чтения и записи файлов в C++. Понимание обработки ошибок имеет решающее значение для создания надежных программ для работы с файлами.
Создайте новый C++ файл с именем file_error_handling.cpp:
touch ~/project/file_error_handling.cpp
Добавьте следующий код в файл file_error_handling.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
void writeToFile(const std::string& filename) {
std::ofstream outputFile(filename);
// Проверка открытия файла
if (!outputFile) {
// Выброс исключения, если файл не удалось открыть
throw std::runtime_error("Unable to open file for writing: " + filename);
}
try {
// Попытка записи данных
outputFile << "Hello, Error Handling!" << std::endl;
outputFile << "This is a sample text." << std::endl;
// Симуляция ошибки записи (намеренно не рекомендуется)
if (outputFile.bad()) {
throw std::runtime_error("Write operation failed");
}
}
catch (const std::exception& e) {
std::cerr << "Error during writing: " << e.what() << std::endl;
}
outputFile.close();
}
void readFromFile(const std::string& filename) {
std::ifstream inputFile(filename);
std::string line;
// Проверка открытия файла
if (!inputFile) {
// Выброс исключения, если файл не удалось открыть
throw std::runtime_error("Unable to open file for reading: " + filename);
}
try {
// Чтение и вывод содержимого файла
std::cout << "File contents:" << std::endl;
while (std::getline(inputFile, line)) {
std::cout << line << std::endl;
}
// Проверка на ошибки чтения
if (inputFile.bad()) {
throw std::runtime_error("Read operation encountered an error");
}
}
catch (const std::exception& e) {
std::cerr << "Error during reading: " << e.what() << std::endl;
}
inputFile.close();
}
int main() {
try {
// Запись в файл
writeToFile("error_handling_example.txt");
// Чтение из файла
readFromFile("error_handling_example.txt");
// Попытка чтения из несуществующего файла
readFromFile("non_existent_file.txt");
}
catch (const std::exception& e) {
std::cerr << "Main error: " << e.what() << std::endl;
return 1;
}
return 0;
}
Скомпилируйте программу:
g++ file_error_handling.cpp -o file_error_handling
Запустите исполняемый файл:
./file_error_handling
Пример вывода:
File contents:
Hello, Error Handling!
This is a sample text.
Error during reading: Unable to open file for reading: non_existent_file.txt
Ключевые моменты об обработке ошибок файлов:
- Используйте блоки
try-catchдля обработки потенциальных исключений - Проверяйте состояние файлового потока до и после операций
- Используйте
std::runtime_errorдля выдачи значимых сообщений об ошибках - Обрабатывайте различные типы ошибок, связанных с файлами
- Предоставляйте информативные сообщения об ошибках
Вы можете рассматривать обработку ошибок как страховочную сетку. Она перехватывает потенциальные проблемы и предотвращает неожиданный сбой вашей программы.
Работа с бинарными файлами с использованием fstream
На этом шаге вы узнаете, как работать с бинарными файлами с использованием класса fstream в C++. Бинарные файлы хранят данные в их необработанном двоичном формате, что отличается от текстовых файлов и полезно для эффективного хранения структурированных данных.
Создайте новый C++ файл с именем binary_files.cpp:
touch ~/project/binary_files.cpp
Добавьте следующий код в файл binary_files.cpp:
#include <iostream>
#include <fstream>
#include <string>
// Простая структура для демонстрации записи в бинарный файл
struct Student {
int id;
char name[50];
double gpa;
};
void writeBinaryFile() {
std::fstream binaryFile("students.bin", std::ios::out | std::ios::binary);
if (!binaryFile) {
std::cerr << "Error opening file for writing!" << std::endl;
return;
}
// Создание нескольких записей о студентах
Student students[3] = {
{1, "John Doe", 3.5},
{2, "Alice Smith", 3.8},
{3, "Bob Johnson", 3.2}
};
// Запись всей структуры в бинарный файл
binaryFile.write(reinterpret_cast<char*>(students), sizeof(students));
binaryFile.close();
std::cout << "Binary file written successfully!" << std::endl;
}
void readBinaryFile() {
std::fstream binaryFile("students.bin", std::ios::in | std::ios::binary);
if (!binaryFile) {
std::cerr << "Error opening file for reading!" << std::endl;
return;
}
Student students[3];
// Чтение всей структуры из бинарного файла
binaryFile.read(reinterpret_cast<char*>(students), sizeof(students));
std::cout << "Student Records:" << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << "ID: " << students[i].id
<< ", Name: " << students[i].name
<< ", GPA: " << students[i].gpa << std::endl;
}
binaryFile.close();
}
int main() {
// Запись бинарного файла
writeBinaryFile();
// Чтение бинарного файла
readBinaryFile();
return 0;
}
Скомпилируйте программу:
g++ binary_files.cpp -o binary_files
Запустите исполняемый файл:
./binary_files
Пример вывода:
Binary file written successfully!
Student Records:
ID: 1, Name: John Doe, GPA: 3.5
ID: 2, Name: Alice Smith, GPA: 3.8
ID: 3, Name: Bob Johnson, GPA: 3.2
Ключевые моменты о бинарных файлах:
- Используйте флаг
std::ios::binaryдля бинарного режима - Методы
write()иread()для бинарных данных reinterpret_castиспользуется для преобразования между типами- Полезно для эффективного хранения структурированных данных
- Сохраняет точное бинарное представление данных
Вы можете думать о бинарных файлах как о точном чертеже. Они хранят данные точно так, как они существуют в памяти, без какого-либо текстового преобразования.
Позиционирование указателя файла с помощью seekg/seekp
На этом шаге вы узнаете, как манипулировать файловыми указателями, используя seekg() для чтения и seekp() для записи в C++. Эти методы позволяют перемещаться и изменять определенные позиции внутри файла.
Создайте новый C++ файл с именем file_pointer.cpp:
touch ~/project/file_pointer.cpp
Добавьте следующий код в файл file_pointer.cpp:
#include <iostream>
#include <fstream>
#include <string>
void createSampleFile() {
std::ofstream file("numbers.txt");
for (int i = 1; i <= 10; ++i) {
file << i << " ";
}
file.close();
}
void demonstrateSeekOperations() {
// Открытие файла в режиме чтения и записи
std::fstream file("numbers.txt", std::ios::in | std::ios::out);
if (!file) {
std::cerr << "Error opening file!" << std::endl;
return;
}
// Операции чтения
std::cout << "Reading operations:" << std::endl;
// Перемещение к 5-му байту (позиция символа)
file.seekg(5);
int value;
file >> value;
std::cout << "Value at 5th byte: " << value << std::endl;
// Перемещение в начало файла
file.seekg(0);
file >> value;
std::cout << "First value: " << value << std::endl;
// Операции записи в определенных позициях
std::cout << "\nWriting operations:" << std::endl;
// Перемещение в определенную позицию и запись
file.seekp(0);
file << "100 ";
// Сброс указателя чтения и чтение для проверки
file.seekg(0);
file >> value;
std::cout << "Modified first value: " << value << std::endl;
file.close();
}
int main() {
// Создание образца файла с числами
createSampleFile();
// Демонстрация операций seek
demonstrateSeekOperations();
return 0;
}
Скомпилируйте программу:
g++ file_pointer.cpp -o file_pointer
Запустите исполняемый файл:
./file_pointer
Пример вывода:
Reading operations:
Value at 5th byte: 4
First value: 1
Writing operations:
Modified first value: 100
Ключевые моменты о файловых указателях:
seekg(): Перемещает указатель чтения (get pointer)seekp(): Перемещает указатель записи (put pointer)- Первый аргумент — позиция в байтах
- Полезно для произвольного доступа в файлах
- Позволяет перемещаться к определенным местам
Вы можете думать о файловых указателях как о курсоре в текстовом редакторе. seekg() и seekp() помогают вам точно переместить этот курсор туда, куда вам нужно.
Закрытие файлов и освобождение ресурсов
На этом шаге вы узнаете о важности правильного закрытия файлов и управления ресурсами в C++ для предотвращения утечек памяти и обеспечения эффективной работы с файлами. Вы рассмотрите различные методы закрытия файлов и использования принципов RAII (Resource Acquisition Is Initialization — Получение ресурса есть инициализация).
Создайте новый C++ файл с именем file_resources.cpp:
touch ~/project/file_resources.cpp
Добавьте следующий код в файл file_resources.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <memory>
// Ручное закрытие файла
void manualFileHandling() {
std::ofstream outputFile("manual_file.txt");
if (outputFile.is_open()) {
outputFile << "Manually managed file resource" << std::endl;
// Явное закрытие файла
outputFile.close();
std::cout << "File closed manually." << std::endl;
}
}
// Управление файлом на основе RAII с использованием unique_ptr
void raii_fileHandling() {
try {
// Использование unique_ptr для управления файловым ресурсом
std::unique_ptr<std::ofstream> file(new std::ofstream("raii_file.txt"));
if (file && file->is_open()) {
*file << "RAII-managed file resource" << std::endl;
std::cout << "RAII file handling successful." << std::endl;
}
// Файл автоматически закрывается, когда unique_ptr выходит из области видимости
}
catch (const std::exception& e) {
std::cerr << "Error in RAII file handling: " << e.what() << std::endl;
}
}
// Управление файлом на основе области видимости
void scopeBasedFileHandling() {
{
// Файл будет автоматически закрыт, когда выйдет из области видимости
std::ofstream scopedFile("scoped_file.txt");
if (scopedFile.is_open()) {
scopedFile << "Scope-based file resource management" << std::endl;
std::cout << "Scoped file handling successful." << std::endl;
}
} // Файл автоматически закрывается здесь
}
int main() {
// Демонстрация различных методов управления файловыми ресурсами
manualFileHandling();
raii_fileHandling();
scopeBasedFileHandling();
return 0;
}
Скомпилируйте программу:
g++ file_resources.cpp -o file_resources
Запустите исполняемый файл:
./file_resources
Пример вывода:
File closed manually.
RAII file handling successful.
Scoped file handling successful.
Ключевые моменты о закрытии файлов и управлении ресурсами:
- Всегда закрывайте файлы после использования
- Используйте метод
close()для ручного закрытия - Используйте принципы RAII
- Используйте управление ресурсами на основе области видимости
- Предотвращайте утечки ресурсов
- Обрабатывайте исключения во время файловых операций
Вы можете думать о файловых ресурсах как о взятии книги в библиотеке. Всегда возвращайте книгу (закрывайте файл), когда закончите, чтобы библиотека (системные ресурсы) оставалась организованной.
Резюме
В этой лабораторной работе вы узнали, как открывать файлы в C++ с использованием классов ofstream и ifstream из стандартной библиотеки. Вы изучили процесс проверки статуса открытия файла, записи текстовых данных в файлы и чтения данных из текстовых файлов. Кроме того, вы получили представление об обработке ошибок чтения/записи файлов, работе с бинарными файлами с помощью fstream, позиционировании файлового указателя с помощью seekg/seekp и правильном закрытии файлов и освобождении ресурсов. Эти основные файловые операции необходимы для управления хранением и извлечением данных в приложениях C++.



