输入和输出 文件读写 知识点总结 C++程序设计与算法笔记总结(六) 北京大学 郭炜

简介: 输入和输出 文件读写 知识点总结 C++程序设计与算法笔记总结(六) 北京大学 郭炜

输入和输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i5atxAWq-1687266529764)(2023-06-20-20-53-48.png)]

输入输出流操作相关的类有很多,以下是一些常见的:

  1. std::ifstream / std::ofstream:用于读取和写入文件。
  2. std::stringstream / std::ostringstream:用于将字符串作为流来处理。
  3. std::cin / std::cout:用于输入和输出标准输入输出流。
  4. std::wifstream / std::wofstream:用于读取和写入宽字符文件。
  5. std::istringstream / std::ostringstream:用于将字符串流化为输入输出流。
  6. std::wstringstream / std::wostringstream:用于将 wchar_t 类型字符串转化为输入输出流。

以上这些类都是基于标准输入输出流 std::stream 的派生类,使用这些类的时候需要包含 头文件。在使用这些类时,通常需要注意打开和关闭文件、读写字符或字符串的方式等操作。同时,需要注意数据的编码方式,例如 ASCII 码和 Unicode 码等,以确保数据的正确读写和传输。

标准流对象

标准流对象是指在 C++ 标准库中预定义好的输入输出流对象,包括三个标准流对象:cin、cout、cerr 和 clog。

  1. cin:用于标准输入(通常是终端或命令行窗口),可以使用流提取运算符(>>)读取数据。
  2. cout:用于标准输出(通常是终端或命令行窗口),可以使用流插入运算符(<<)输出数据。
  3. cerr 和 clog:用于输出错误信息和日志信息,与 cout 不同的是,cerr 和 clog 通常不会被重定向。cerr 是标准错误流,通常用于输出错误信息;clog 是标准日志流,通常用于输出日志信息。
    这些标准流对象都是全局对象,可以在任何地方访问它们。在使用标准流对象时,需要包含 头文件。
    例如,可以使用 cin 和 cout 来实现从标准输入读取数据并输出到标准输出:
#include <iostream>
int main() {
    int num;
    std::cout << "Please enter a number: ";
    std::cin >> num;
    std::cout << "The number you entered is: " << num << std::endl;
    return 0;
}

在上述代码中,使用 std::cout 来输出提示信息,然后使用 std::cin 来读取一个整数,最后再使用 std::cout 输出读取到的整数。

需要注意的是,标准流对象是缓冲流,缓冲区的大小可以通过调用 std::ios_base::sync_with_stdio 函数来设置。同时,可以通过调用 std::cin.clear() 和 std::cin.ignore() 函数来清空 cin 输入缓冲区和忽略输入缓冲区中的指定字符。

cin对应于标准输入流,用于从键盘读取数据,也可以被重定向

为从文件中读取数据。

 cout对应于标准输出流,用于向屏幕输出数据,也可以被重定

向为向文件写入数据。

 cerr对应于标准错误输出流,用于向屏幕输出出错信息,

 clog对应于标准错误输出流,用于向屏幕输出出错信息,

 cerr和clog的区别在于cerr不使用缓冲区,直接向显示器输出信息;而输出到clog中的信息先会被存放在

缓冲区,缓冲区满或者刷新时才输出到屏幕。

判断输入流结束

可以用如下方法判输入流结束:

int x;
while(cin>>x){
…..
}
return 0;
 如果是从文件输入,比如前面有
freopen(“some.txt”,”r”,stdin);

那么,读到文件尾部,输入流就算结束

 如果从键盘输入,则在单独一行输入Ctrl+Z代表输入流结束

istream 是 C++ 中用于输入流的基类,它提供了一些用于输入流操作的成员函数,以下是一些常用的成员函数:

  1. getline():从输入流中读取一行数据。可以指定分隔符,例如:
std::string line;
std::getline(std::cin, line); // 从标准输入中读取一行数据
  1. ignore():忽略输入流中的指定字符或一定数量的字符。可以指定忽略的字符数或忽略到某个分隔符为止,例如:
std::cin.ignore(100, '\n'); // 忽略输入流中的 100 个字符或遇到换行符为止
  1. peek():查看输入流中下一个字符但不移动输入流的指针位置,例如:
char ch = std::cin.peek(); // 查看输入流中下一个字符
  1. putback():将一个字符放回输入流中,例如:
std::cin.putback('x'); // 将字符 'x' 放回输入流中
  1. read():从输入流中读取指定数量的字节到指定的内存位置,例如:
char buf[100];
std::cin.read(buf, 100); // 从输入流中读取 100 个字节到 buf 中
  1. seekg() / tellg():用于移动输入流的指针位置和获取当前指针位置的函数。seekg() 可以将指针移动到指定位置,tellg() 可以获取当前指针的位置,例如:
std::cin.seekg(10); // 将输入流的指针位置移动到第 10 个字符处
std::streampos pos = std::cin.tellg(); // 获取当前输入流的指针位置

需要注意的是,以上成员函数是从 istream 类继承来的,也可以在派生类中使用。同时,需要注意输入流的状态,例如输入流是否已经到达文件结尾或输入流是否存在错误等。可以使用 eof()、fail()、bad() 和 good() 成员函数来获取输入流的状态。

istream类的成员函数

istream 是 C++ 中用于输入流的基类,它提供了一些用于输入流操作的成员函数,以下是一些常用的成员函数:

  1. getline():从输入流中读取一行数据。可以指定分隔符,例如:
std::string line;
std::getline(std::cin, line); // 从标准输入中读取一行数据
  1. ignore():忽略输入流中的指定字符或一定数量的字符。可以指定忽略的字符数或忽略到某个分隔符为止,例如:
std::cin.ignore(100, '\n'); // 忽略输入流中的 100 个字符或遇到换行符为止
• 1
  1. peek():查看输入流中下一个字符但不移动输入流的指针位置,例如:
char ch = std::cin.peek(); // 查看输入流中下一个字符
  1. putback():将一个字符放回输入流中,例如:
std::cin.putback('x'); // 将字符 'x' 放回输入流中
  1. read():从输入流中读取指定数量的字节到指定的内存位置,例如:
char buf[100];
std::cin.read(buf, 100); // 从输入流中读取 100 个字节到 buf 中
  1. seekg() / tellg():用于移动输入流的指针位置和获取当前指针位置的函数。seekg() 可以将指针移动到指定位置,tellg() 可以获取当前指针的位置,例如:
std::cin.seekg(10); // 将输入流的指针位置移动到第 10 个字符处
std::streampos pos = std::cin.tellg(); // 获取当前输入流的指针位置

需要注意的是,以上成员函数是从 istream 类继承来的,也可以在派生类中使用。同时,需要注意输入流的状态,例如输入流是否已经到达文件结尾或输入流是否存在错误等。可以使用 eof()、fail()、bad() 和 good() 成员函数来获取输入流的状态。

C++文件读写

C++ 文件读写通常使用标准库中的 ifstream 和 ofstream 类来实现,这两个类都继承自 istream 和 ostream 类,提供了丰富的文件读写方法。

文件读取可以使用 ifstream 类,例如:

#include <iostream>
#include <fstream>
#include <string>
int main() {
    std::ifstream infile("filename.txt");
    std::string line;
    while (std::getline(infile, line)) {
        std::cout << line << std::endl;
    }
    infile.close();
    return 0;
}

在上述代码中,使用 ifstream 类打开名为 filename.txt 的文件,然后使用 getline() 函数读取文件中的每一行数据,并输出到标准输出流中。最后调用 close() 函数关闭文件。

文件写入可以使用 ofstream 类,例如:

#include <fstream>
#include <string>
int main() {
    std::ofstream outfile("filename.txt");
    outfile << "Hello, World!" << std::endl;
    outfile.close();
    return 0;
}

在上述代码中,使用 ofstream 类打开名为 filename.txt 的文件,然后使用流插入运算符(<<)将字符串 “Hello, World!” 写入文件中。最后调用 close() 函数关闭文件。

需要注意的是,文件读写操作可能会抛出异常,因此需要使用 try-catch 块来捕获异常并进行处理。同时,需要确保使用文件流之前先打开文件,使用之后再关闭文件,以保证操作的正确性和文件C++ 文件读写通常使用流操作,主要包括以下几个步骤:

  1. 打开文件:使用 std::ofstream 或 std::ifstream 类型的对象打开文件,可以指定打开方式和文件名等信息。
std::ofstream outfile("example.txt"); // 以写入方式打开文件
std::ifstream infile("example.txt"); // 以读取方式打开文件
  1. 写文件:通过流插入运算符(<<)写入数据到文件中。
outfile << "This is a line of text" << std::endl;
  1. 读文件:通过流提取运算符(>>)读取文件中的数据。
std::string line;
while (std::getline(infile, line)) {
    std::cout << line << std::endl;
}
  1. 关闭文件:使用 std::ofstream 或 std::ifstream 类型的对象关闭文件。
outfile.close();
infile.close();

需要注意的是,文件读写操作可能会出现错误,例如文件不存在、文件无法打开、文件权限不足等。可以使用流状态函数(eof()、fail()、bad() 和 good())或异常机制来处理这些错误。

完整的文件读写示例代码如下:

#include <iostream>
#include <fstream>
#include <string>
int main() {
    std::ofstream outfile("example.txt"); // 以写入方式打开文件
    if (!outfile.is_open()) {
        std::cerr << "Failed to open file" << std::endl;
        return -1;
    }
    outfile << "This is a line of text" << std::endl;
    outfile.close(); // 关闭文件
    std::ifstream infile("example.txt"); // 以读取方式打开文件
    if (!infile.is_open()) {
        std::cerr << "Failed to open file" << std::endl;
        return -1;
    }
    std::string line;
    while (std::getline(infile, line)) { // 逐行读取文件中的内容
        std::cout << line << std::endl;
    }
    infile.close(); // 关闭文件
    return 0;
}

以上代码先使用 std::ofstream 打开文件并写入一行文本,然后关闭文件,接着使用 std::ifstream 打开同一个文件并逐行读取其内容,并在标准输出中输出每行文本。需要注意的是,可以通过检查文件是否成功打开来判断文件是否存在或是否有读写权限。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mAUReiSS-1687266529765)(2023-06-20-21-02-28.png)]

除了使用 ofstream 和 ifstream 类,还可以使用 fstream 类来实现文件读写,它同时继承了 istream 和 ostream 类,可以用于读写文件。以下是一个使用 fstream 类读写文件的示例:

#include <iostream>
#include <fstream>
#include <string>
int main() {
    std::fstream file("example.txt", std::ios::in | std::ios::out | std::ios::trunc);
    if (!file.is_open()) {
        std::cerr << "Failed to open file" << std::endl;
        return -1;
    }
    file << "This is a line of text" << std::endl;
    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << std::endl;
    }
    file.close();
    return 0;
}

在上述代码中,使用 fstream 类打开名为 example.txt 的文件,同时指定了打开方式为输入输出和截断文件。然后将一行文本写入文件中,接着使用 getline() 函数读取文件中的每一行数据,并输出到标准输出流中。最后调用 close() 函数关闭文件。

需要注意的是,在使用 fstream 类进行文件读写时,需要指定文件的打开方式。常用的文件打开方式包括:

  1. ios::in:以读取方式打开文件。
  2. ios::out:以写入方式打开文件。
  3. ios::app:在文件末尾追加内容。
  4. ios::trunc:打开文件并截断文件,即删除文件中的所有内容。
    同时,还可以使用按位或操作符将多个打开方式组合起来。例如,可以使用以下方式打开文件:
std::fstream file("example.txt", std::ios::in | std::ios::out | std::ios::app);

在上述代码中,打开文件的方式包括输入输出和在文件末尾追加内容。

需要注意的是,当打开文件时指定了 ios::trunc 标志时,文件的所有内容将被删除。因此,在使用此方式打开文件时,需要谨慎操作。

文件的读写指针

 对于输入文件,有一个读指针;

 对于输出文件,有一个写指针;

 对于输入输出文件,有一个读写指针;

 标识文件操作的当前位置, 该指针在哪里,读写操作就在哪里进行。

=文件的读写指针是非常重要的概念,它标识了文件操作的当前位置。

对于输入文件,读指针指示了当前读取位置在文件中的位置。当我们打开一个文件进行读取操作时,文件读指针默认位于文件的开头,每次读取操作后,文件读指针会自动向后移动,指向下一个要读取的位置。

对于输出文件,写指针指示了当前写入位置在文件中的位置。当我们打开一个文件进行写入操作时,文件写指针默认位于文件的开头,每次写入操作后,文件写指针会自动向后移动,指向下一个要写入的位置。

对于输入输出文件,读写指针可以同时进行读取和写入操作。在打开文件时,我们可以指定文件的读写指针初始位置,也可以使用 fseek() 函数移动文件的读写指针。

在进行文件读写操作时,我们需要非常注意文件读写指针的位置,以保证文件读写操作的正确性和安全性。如果读写指针的位置不正确,可能会导致数据的丢失或者文件内容的不一致。因此,在进行文件读写操作时,需要严格遵守文件读写指针的规则和约定。

二进制文件读写

二进制文件是一种以二进制编码形式存储数据的文件,与文本文件不同,二进制文件不以字符为单位进行存储,而是以二进制数据块为单位进行存储。在 C++ 中,可以使用二进制方式进行文件读写,实现对二进制文件的读写操作。

二进制文件的读写与文本文件的读写不同,主要体现在以下两个方面:

  1. 打开文件时需要使用二进制方式进行打开,即指定文件打开方式为 std::ios::binary。
  2. 读写操作时需要以二进制数据块为单位进行读写,而不是以字符为单位进行读写。
    以下是一个使用二进制方式读写二进制文件的示例:
#include <iostream>
#include <fstream>
struct Person {
    char name[20];
    int age;
    double height;
};
int main() {
    std::ofstream outfile("example.bin", std::ios::binary);
    if (!outfile) {
        std::cerr << "Failed to open file for writing" << std::endl;
        return -1;
    }
    Person person = {"Alice", 28, 1.65};
    outfile.write((const char*)&person, sizeof(person));
    outfile.close();
    std::ifstream infile("example.bin", std::ios::binary);
    if (!infile) {
        std::cerr << "Failed to open file for reading" << std::endl;
        return -1;
    }
    Person read_person;
    infile.read((char*)&read_person, sizeof(read_person));
    std::cout << "Name: " << read_person.name << std::endl;
    std::cout << "Age: " << read_person.age << std::endl;
    std::cout << "Height: " << read_person.height << std::endl;
    infile.close();
    return 0;
}

在上述代码中,首先使用 ofstream 类以二进制方式打开文件,并将一个 Person 结构体对象写入文件中。然后使用 ifstream 类以二进制方式打开文件,并读取文件中的二进制数据块,将其解析为一个 Person 结构体对象,并输出其成员变量的值。

需要注意的是,在进行二进制文件读写操作时,需要注意文件读写指针的位置,以保证二进制数据块的正确读写。另外,在进行文件读写操作时,应当确保写入和读取的二进制数据块的大小相同,否则可能会导致数据的丢失或者文件内容的不一致。

文件拷贝程序mycopy 示例

/*用法示例:
mycopy src.dat dest.dat 
即将 src.dat 拷贝到 dest.dat 如果 dest.dat 原来就有,则原来的文件会被覆
盖 */
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char * argv[])
{
if( argc != 3 ) {
cout << "File name missing!" << endl;
return 0;
}
ifstream inFile(argv[1],ios::binary|ios::in); //打开文件用
于读
if( ! inFile ) {
cout << "Source file open error." << endl;
return 0;
}
ofstream outFile(argv[2],ios::binary|ios::out); //打开文
件用于写
if( !outFile) {
cout << "New file open error." << endl;
inFile.close(); //打开的文件一定要关闭
return 0;
}
char c;
while( inFile.get(c)) //每次读取一个字符
outFile.put(c); //每次写入一个字符
outFile.close(); 
inFile.close();
return 0;
}

二进制文件和文本文件的区别

Linux,Unix下的换行符号:‘\n’ (ASCII码: 0x0a)

Windows 下的换行符号:‘\r\n’ (ASCII码: 0x0d0a) endl 就是 ‘\n’

Mac OS下的换行符号: ‘\r’ (ASCII码:0x0d)

导致 Linux, Mac OS 文本文件在Windows 记事本中打开时不换行二进制文件和文本文件的区别

 Unix/Linux下打开文件,用不用 ios::binary 没区别

 Windows下打开文件,如果不用 ios::binary,

则:读取文件时,所有的 ‘\r\n’会被当做一个字符’\n’处理,即少读了一个字

符’\r’。

写入文件时,写入单独的’\n’时,系统自动在前面加一个’\r’,即多写了一

个’\r

目录
相关文章
|
2月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
70 1
|
2月前
|
算法 索引
❤️算法笔记❤️-(每日一刷-141、环形链表)
❤️算法笔记❤️-(每日一刷-141、环形链表)
50 0
|
2月前
|
算法
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
48 0
|
2月前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
72 1
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
73 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
18 1
|
2月前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
140 0
|
2月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
18 0
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
33 0
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
25 0