• C++
  • C++ 文件重定向与文件读写操作

  • @ 2024-7-24 22:58:12

C++ 文件重定向与文件读写操作教程 在C++中,文件重定向和文件读写操作是处理数据持久化和输入输出流的重要部分。以下将详细介绍这两个方面的基本概念、步骤和示例代码。

一、文件重定向 文件重定向是指将标准输入输出(stdin、stdout、stderr)重定向到文件或其他设备的过程。在C++中,这通常通过修改流的缓冲区(buffer)来实现。

  1. 使用rdbuf()方法 在C++中,cin、cout、cerr等流对象都提供了rdbuf()成员函数,用于获取或设置流的缓冲区。通过替换这些流的缓冲区,我们可以实现重定向。

cpp

#include <iostream>  
#include <fstream>  
  
int main() {  
    std::ifstream fin("input.txt");  
    std::ofstream fout("output.txt");  
  
    // 重定向cin和cout  
    std::streambuf* cinbuf = std::cin.rdbuf(fin.rdbuf());  
    std::streambuf* coutbuf = std::cout.rdbuf(fout.rdbuf());  
  
    // 现在,cin从input.txt读取,cout向output.txt写入  
    std::string line;  
    std::getline(std::cin, line); // 从input.txt读取一行  
    std::cout << line << std::endl; // 写入到output.txt  
  
    // 恢复标准输入输出  
    std::cin.rdbuf(cinbuf);  
    std::cout.rdbuf(coutbuf);  
  
    fin.close();  
    fout.close();  
    return 0;  
}
  1. 使用freopen()函数(C语言风格,但C++中也可使用) 虽然freopen()是C语言标准库函数,但在C++中同样可以使用。它允许你重新打开标准文件流,并将其连接到指定的文件。

cpp

#include <cstdio>  
  
int main() {  
    freopen("input.txt", "r", stdin);  
    freopen("output.txt", "w", stdout);  
  
    // 现在,scanf从input.txt读取,printf向output.txt写入  
    int a, b;  
    scanf("%d %d", &a, &b);  
    printf("%d\n", a + b);  
  
    // 恢复标准输入输出(在Windows上可能是freopen("CON", "r", stdin); freopen("CON", "w", stdout);)  
    fclose(stdin);  
    fclose(stdout);  
  
    return 0;  
}

注意:使用freopen()后,原来的stdin和stdout流会被关闭,因此在恢复时需要小心处理。

二、文件读写操作 在C++中,文件读写操作通常通过库中的ifstream(用于读文件)、ofstream(用于写文件)和fstream(同时支持读写)类来实现。

  1. 写文件 cpp
#include <fstream>  
#include <iostream>  
  
int main() {  
    std::ofstream ofs("example.txt");  
    if (!ofs.is_open()) {  
        std::cerr << "无法打开文件" << std::endl;  
        return 1;  
    }  
    ofs << "Hello, World!" << std::endl;  
    ofs.close();  
    return 0;  
}
  1. 读文件 cpp
#include <fstream>  
#include <iostream>  
#include <string>  
  
int main() {  
    std::ifstream ifs("example.txt");  
    if (!ifs.is_open()) {  
        std::cerr << "无法打开文件" << std::endl;  
        return 1;  
    }  
    std::string line;  
    while (getline(ifs, line)) {  
        std::cout << line << std::endl;  
    }  
    ifs.close();  
    return 0;  
}
  1. 二进制文件读写 对于二进制文件,需要指定ios::binary打开模式。

cpp

// 写二进制文件  
#include <fstream>  
#include <vector>  
  
class Data {  
public:  
    int id;  
    char name[100];  
};  
  
int main() {  
    std::ofstream ofs("data.bin", std::ios::out | std::ios::binary);  
    Data d = {1, "Example"};  
    ofs.write(reinterpret_cast<const char*>(&d), sizeof(d));  
    ofs.close();  
    return 0;  
}  

// 读二进制文件

#include <fstream>  
#include <iostream>  
  
int main() {  
    Data d;  
    std::ifstream ifs("data.bin", std::ios::in | std::ios::binary);  
    if (ifs.read(reinterpret_cast<char*>(&d), sizeof(d))) {  
        std::cout << "ID: " << d.id << ", Name: " << d.name << std::endl;  
    }  
    ifs.close();  
    return 0;  
}

总结 文件重定向和文件读写操作是C++编程中处理输入输出流和数据持久化的基本技能。通过合理使用库中的类和方法,以及理解标准输入输出流的重定向机制,可以高效地实现复杂的数据处理任务。

5 条评论

  • @ 2025-5-18 13:55:18
    #include <fstream>  
    #include <iostream>  
    using namespace std;
    int main() {  
    	ofstream ofs("example.txt");  
    	//if (!ofs.is_open()) {  
    	//	cerr << "无法打开文件" << std::endl;  
    	//	return 1;  
    	//}  
    	ofs << "Hello, World!" << endl;  
    	ofs.close();  
    	return 0;  
    }
    
    
    • @ 2025-5-18 13:48:19
      #include<iostream>
      #include <cstdio> //freopen("input.txt", "r", stdin);  
      using namespace std;
      int main() {
      	freopen("input.txt", "r", stdin);  
      	freopen("output.txt", "w", stdout); 
      	
      	int a,b;
      	cin >> a>>b;
      	cout<<a+b<<endl;
      	
      	// 恢复标准输入输出(在Windows上可能是freopen("CON", "r", stdin); freopen("CON", "w", stdout);)  
      	fclose(stdin);  
      	fclose(stdout);  
      	return 0;
      }
      
      • @ 2025-5-18 13:45:48

        • @ 2025-5-18 13:40:49

          C++ freopen 函数模式教程

          freopen 是C++标准库中的一个函数,用于重新定向一个已打开的文件流到另一个文件或设备。它通常用于重定向标准输入(stdin)、标准输出(stdout)或标准错误(stderr),使程序能够直接与文件交互而无需修改原有的输入/输出代码。

          1. freopen 函数基本语法

          #include <cstdio>
          
          FILE* freopen(const char* filename, const char* mode, FILE* stream);
          
          • 参数

            • filename:要打开的文件路径(如果为NULL,则会尝试关闭当前流)。
            • mode:文件打开模式,指定如何访问文件(如"r"、"w"等)。
            • stream:要重新定向的流(通常是stdinstdoutstderr)。
          • 返回值

            • 成功时返回指向stream的指针。
            • 失败时返回NULL

          2. 文件打开模式参数

          freopenmode参数与标准C++文件操作的模式类似,但有一些细微差别。以下是常见的模式选项:

          模式 描述
          "r" 以只读方式打开文件。文件必须存在。
          "w" 以写入方式打开文件。如果文件存在,则清空内容;如果不存在,则创建新文件。
          "a" 以追加方式打开文件。如果文件不存在,则创建新文件。所有写入操作都追加到文件末尾。
          "r+" 以读写方式打开文件。文件必须存在。读取和写入操作可以交叉进行。
          "w+" 以读写方式打开文件。如果文件存在,则清空内容;如果不存在,则创建新文件。
          "a+" 以读写方式打开文件。如果文件不存在,则创建新文件。读取操作可以在任何位置进行,但写入操作会追加到文件末尾。

          二进制模式: 在模式字符串中添加'b'(如"rb"、"wb")可以以二进制模式打开文件,避免文本模式下的换行符转换等特殊处理。

          3. 标准流重定向示例

          示例1:重定向标准输出到文件
          #include <cstdio>
          
          int main() {
              // 将标准输出重定向到 output.txt
              if (freopen("output.txt", "w", stdout) == NULL) {
                  perror("无法打开文件");
                  return 1;
              }
              
              // 所有 printf 和 cout 输出将写入文件
              printf("这是写入文件的内容\n");
              
              // 恢复标准输出
              if (freopen("/dev/stdout", "w", stdout) == NULL) {
                  perror("无法恢复标准输出");
                  return 1;
              }
              
              printf("这是输出到控制台的内容\n");
              
              return 0;
          }
          
          示例2:重定向标准输入从文件读取
          #include <cstdio>
          
          int main() {
              // 将标准输入重定向到 input.txt
              if (freopen("input.txt", "r", stdin) == NULL) {
                  perror("无法打开文件");
                  return 1;
              }
              
              int num;
              scanf("%d", &num);  // 从文件读取数据
              printf("从文件读取的数字: %d\n", num);
              
              // 恢复标准输入
              if (freopen("/dev/stdin", "r", stdin) == NULL) {
                  perror("无法恢复标准输入");
                  return 1;
              }
              
              printf("请输入一个数字: ");
              scanf("%d", &num);  // 从键盘读取数据
              printf("从键盘读取的数字: %d\n", num);
              
              return 0;
          }
          

          4. 高级用法:临时重定向

          在某些情况下,你可能需要临时重定向流,然后恢复原状。可以使用以下技巧:

          #include <cstdio>
          
          int main() {
              FILE* original_stdout = stdout;  // 保存原始标准输出
              
              // 临时重定向到文件
              if (freopen("temp.txt", "w", stdout) == NULL) {
                  perror("无法打开文件");
                  return 1;
              }
              
              printf("这是写入 temp.txt 的内容\n");
              
              // 恢复标准输出
              fflush(stdout);  // 确保所有输出都写入文件
              stdout = original_stdout;  // 恢复指针
              
              printf("这是输出到控制台的内容\n");
              
              return 0;
          }
          

          5. 注意事项

          1. 文件路径

            • 相对路径:相对于程序运行目录。
            • 绝对路径:如"/home/user/data.txt"(Linux/Mac)或"C:\\data.txt"(Windows)。
          2. 错误处理

            • 始终检查freopen的返回值,确保重定向成功。
            • 使用perrorerrno获取详细错误信息。
          3. 流缓冲

            • 使用fflush(stream)确保所有缓冲数据写入文件后再重定向或关闭流。
          4. 平台差异

            • Windows系统可能需要在模式中添加'b'以二进制模式打开文件,避免换行符转换问题。
            • Linux/Mac系统通常不需要特殊处理。

          6. 应用场景

          • 日志记录:将标准输出重定向到日志文件。
          • 自动化测试:通过文件输入模拟用户输入,捕获程序输出进行验证。
          • 数据导入/导出:简化与文件的数据交互,无需修改现有输入/输出代码。

          7. 替代方案

          对于更现代的C++编程,可以考虑使用<fstream>头文件中的类(如ifstreamofstream)代替freopen,提供更安全、面向对象的文件操作方式。

          #include <fstream>
          #include <iostream>
          
          int main() {
              std::ofstream file("output.txt");
              if (file.is_open()) {
                  file << "这是写入文件的内容" << std::endl;
                  file.close();
              }
              
              return 0;
          }
          

          通过freopen函数,你可以灵活地重定向标准流,使程序能够方便地与文件交互,而无需大幅修改原有代码。合理使用不同的打开模式,可以满足各种读写需求。

          • @ 2025-5-18 13:39:49

            在C++中进行文件操作,主要通过<fstream>头文件提供的类来实现,包括ifstream(用于读取文件)、ofstream(用于写入文件)和fstream(用于读写文件) 。而文件的打开模式决定了对文件的操作方式,以下是详细介绍:

            一、文件打开模式的种类及含义

            1. ios::in
              • 含义:以读模式打开文件,用于从文件中读取数据。文件指针指向文件开头。如果文件不存在,后续的读取操作会失败。
              • 示例
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ifstream inFile("test.txt", std::ios::in);
                if (inFile.is_open()) {
                    std::string line;
                    while (std::getline(inFile, line)) {
                        std::cout << line << std::endl;
                    }
                    inFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            上述代码尝试以读模式打开test.txt文件,若成功打开,逐行读取文件内容并输出到控制台。

            1. ios::out
              • 含义:以写模式打开文件。如果文件不存在,会创建新文件;如果文件已存在,会截断(清空)文件原有内容,然后开始写入新数据。文件指针指向文件开头。
              • 示例
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ofstream outFile("test.txt", std::ios::out);
                if (outFile.is_open()) {
                    outFile << "这是写入文件的内容" << std::endl;
                    outFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            此代码以写模式打开test.txt,向文件中写入一行文本。

            1. ios::app
              • 含义:以追加模式打开文件。用于向文件末尾添加数据。如果文件不存在,会创建新文件。文件指针指向文件末尾。
              • 示例
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ofstream outFile("test.txt", std::ios::app);
                if (outFile.is_open()) {
                    outFile << "这是追加到文件末尾的内容" << std::endl;
                    outFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            运行这段代码,会在test.txt文件的末尾追加一行内容。

            1. ios::trunc
              • 含义:如果文件已存在,在打开文件时会先删除文件原有内容,再重新创建文件。通常需要与ios::out等模式配合使用。单独使用ios::trunc没有实际意义,因为它必须依赖于其他打开模式来确定后续操作是读还是写。比如ios::out | ios::trunc等同于单纯的ios::out效果(都会清空文件原有内容再写入 )。
              • 示例
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ofstream outFile("test.txt", std::ios::out | std::ios::trunc);
                if (outFile.is_open()) {
                    outFile << "使用了trunc模式清空并写入新内容" << std::endl;
                    outFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            这里以ios::out | ios::trunc模式打开文件,会先清空test.txt原有内容,再写入新内容。

            1. ios::binary
              • 含义:以二进制模式打开文件。适用于操作二进制文件,如图片、音频、视频等非文本文件,也可用于文本文件。在二进制模式下,不会对文件内容进行字符转换等特殊处理,按字节原样读写。 通常与ios::inios::out等模式组合使用,如ios::binary | ios::in用于以二进制读模式打开文件,ios::binary | ios::out用于以二进制写模式打开文件。
              • 示例(二进制写文件)
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ofstream outFile("test.bin", std::ios::binary | std::ios::out);
                if (outFile.is_open()) {
                    char buffer[] = {1, 2, 3, 4, 5};
                    outFile.write(buffer, sizeof(buffer));
                    outFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            上述代码以二进制写模式打开test.bin文件,并向其中写入一段二进制数据。 - 示例(二进制读文件)

            #include <fstream>
            #include <iostream>
            
            int main() {
                std::ifstream inFile("test.bin", std::ios::binary | std::ios::in);
                if (inFile.is_open()) {
                    char buffer[5];
                    inFile.read(buffer, sizeof(buffer));
                    for (int i = 0; i < sizeof(buffer); ++i) {
                        std::cout << (int)buffer[i] << " ";
                    }
                    inFile.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            此代码以二进制读模式打开test.bin文件,读取其中的二进制数据并输出。

            1. ios::ate
              • 含义:打开文件时,文件指针指向文件末尾。但与ios::app不同的是,它只是将指针定位到末尾,后续可以通过文件指针移动操作(如seekgseekp )在文件的任意位置进行读写操作;而ios::app始终是在文件末尾追加内容。
              • 示例
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::fstream file("test.txt", std::ios::ate | std::ios::in | std::ios::out);
                if (file.is_open()) {
                    // 将文件指针移到文件开头
                    file.seekg(0, std::ios::beg); 
                    std::string line;
                    std::getline(file, line);
                    std::cout << "文件开头内容: " << line << std::endl;
                    file.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            该代码以ios::ate | ios::in | ios::out模式打开test.txt文件,先将指针定位到末尾,然后又移到开头读取内容。

            二、文件打开模式的组合使用

            可以使用|操作符将多个打开模式组合起来,以满足更复杂的文件操作需求。例如:

            • ios::in | ios::out:以读写模式打开文件。文件必须存在,文件指针指向文件开头。可以先读数据,也可以先写数据。
            #include <fstream>
            #include <iostream>
            
            int main() {
                std::fstream file("test.txt", std::ios::in | std::ios::out);
                if (file.is_open()) {
                    std::string originalContent;
                    std::getline(file, originalContent);
                    std::cout << "原始内容: " << originalContent << std::endl;
            
                    file.seekp(0, std::ios::beg);  // 将文件指针移到开头准备写入
                    file << "修改后的内容";
                    file.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            这段代码先以读写模式打开test.txt,读取文件原有内容,然后将文件指针移到开头,写入新的内容。

            • ios::binary | ios::in | ios::out:以二进制读写模式打开文件,适用于对二进制文件进行读写操作,具备随机读写二进制数据的能力。
            #include <fstream>
            #include <iostream>
            
            struct Data {
                int num;
                char ch;
            };
            
            int main() {
                std::fstream file("data.bin", std::ios::binary | std::ios::in | std::ios::out);
                if (file.is_open()) {
                    Data dataToWrite = {10, 'a'};
                    file.write((char*)&dataToWrite, sizeof(Data));  // 写入二进制数据
            
                    file.seekg(0, std::ios::beg);  // 将文件指针移到开头
                    Data dataRead;
                    file.read((char*)&dataRead, sizeof(Data));
                    std::cout << "读取的数字: " << dataRead.num << ", 字符: " << dataRead.ch << std::endl;
                    file.close();
                } else {
                    std::cerr << "无法打开文件" << std::endl;
                }
                return 0;
            }
            

            此代码以二进制读写模式打开data.bin文件,先写入一段自定义结构的二进制数据,然后再读取出来并输出。

            三、文件操作时的注意事项

            1. 检查文件是否成功打开:在进行文件读写操作前,务必使用is_open()方法检查文件是否成功打开。如果文件打开失败,后续操作可能会导致程序崩溃或出现未定义行为。
            std::ifstream inFile("nonexistent.txt", std::ios::in);
            if (!inFile.is_open()) {
                std::cerr << "文件打开失败" << std::endl;
                return 1;
            }
            
            1. 关闭文件:在文件操作完成后,及时调用close()方法关闭文件,以释放系统资源。虽然程序结束时系统会自动回收资源,但良好的编程习惯是手动关闭不再使用的文件。
            std::ofstream outFile("test.txt", std::ios::out);
            // 进行文件写入操作
            outFile.close();
            
            1. 异常处理:文件操作过程中可能会遇到各种错误,如文件不存在、磁盘空间不足等。可以使用try-catch块来捕获并处理这些异常,增强程序的健壮性。
            #include <fstream>
            #include <iostream>
            
            int main() {
                try {
                    std::ifstream inFile("test.txt", std::ios::in);
                    if (!inFile.is_open()) {
                        throw std::runtime_error("无法打开文件");
                    }
                    // 进行文件读取操作
                    inFile.close();
                } catch (const std::exception& e) {
                    std::cerr << "异常: " << e.what() << std::endl;
                }
                return 0;
            }
            

            通过合理选择和组合文件打开模式,能在C++中灵活高效地进行各种文件操作。

            • 1