c++笔记08---I/O 流,格式化 I/O,非格式化 I/O,随机 I/O,二进制 I/O
来源:互联网 发布:火电厂仿真软件 编辑:程序博客网 时间:2024/05/02 08:24
1. 输入输出 I/O 流
C: fopen/fclose/fread/fwrite/fprintf/fscanf/fseek/ftell/fput/fget...
C++: 对基本的 I/O 操作做了类的封装,其功能没有任何差别,用法也相似;
2. 格式化 I/O 流:<< / >>
#include <iostream>
#include <fstream> // 打开文件
using namespace std;
int main() {
// 写文件:
ofstream ofs("hello.txt"); // 创建文件,类似于 fopen 用 w 模式,只读且清空
// ofs 在 ofstream 的构造函数里面被构造,打开成功返回 ture,失败返回 false,是 bool 型;
if(! ofs) {
perror("error"); // perror 打印出错信息;
return -1;
}
ofs << "hello word!" << endl; // hello word! 被输入文件 hello.txt 里;
ofs.close();
ofs.open("hello.txt", ios::app); // 打开文件,追加内容,类似于 fopen 的 a 模式
if(! ofs) {
perror("error");
return -1;
}
ofs << "another\n";
ofs.close();
// 读文件:
ifstream ifs("hello.txt");
if(! ifs) {
perror("error");
return -1;
}
steing s1, s2;
ifs >> s1 >> s2; // 读入上面输入的两个字符串;以空白字符作为分隔(空格、换行、制表);
return 0;
}
ios::app 以追加的方式打开文件;
ios::ate 文件打开后定位到文件尾;
ios::binary 以二进制方式打开文件;缺省是文本方式;
ios::in 以输入方式打开;
ios::out 以输出方式打开;
ios::nocreate 不建立文件,所以文件不存在时,打开失败;
ios::noreplace 不覆盖文件,所以打开文件时,如果文件存在则失败;
ios::trunc 如果文件存在,把文件长度设为 0;
ios::beg 移动到文件头;
ios::cure 移动到文件当前位置;
ios::end 移动到文件尾;
可以用 或 把以上文件属性连接起来:
3. 非格式化 I/O 流:put/get
#include <iostream>
#include <fstream>
using namespace std;
int mian() {
// 输入
ofstream ofs("putget.txt");
if(! ofs) {
perror("error");
return -1;
}
for(char c = ' '; c <= '~'; ++c) // 把 ASIIC 表里的字符从第一个到最后一个写入;
// 前++返回引用,后++返回副本,所以建议用前++,效率高;
if(! ofs.put(c)) {
preeor("error");
return -1;
}
ofs.close();
// 输出
ifstream ifs("putget.txt");
if(! ifs) {
perror("error");
return -1;
}
char c;
while((c = ifs.get()) != EOF) // 因为 ASIIC 里没有 EOF,所以用 EOF 作判断;
// 无论是读取失败或者读完文件,都返回 EOF,所以下面加 if 语句判断是否出错;
cout << c;
if(ifs.error()) { // error 判断读取是否出错
// 相当于:if(! ifs.eof()) { // eof 判断是否到文件尾;
perror("error");
return -1;
}
ifs.close();
return 0;
}
EOF:成员函数 eof();用来检测是否到达文件尾;
如果到达文件尾,返回非 0;否则返回 0;
4 随机 I/O 流:seekp/seekg, tellp/tellg(文件指针)
#include <iostream>
#include <fstream>
using namespace std;
int mian() {
// 输入
fstream fs("seek.txt", ios::in | ios::out); // 可读可写,相当于:w+
if(! ofs) {
perror("error");
return -1;
}
fs << "0123456789";
cout << fs.tellp() << endl;
cout << fs.tellg() << endl;
fs.seekp(-3, ios::cur); // 当前位置往前挪 3 个位置
fs << "xyz"; // 0123456xyz(文件默认操作只有覆盖,没有插入)
fs.seekg(4, ios::beg); // 从文件头开始挪;
int i;
fs >> i;
cout << i << endl;
cout << fs.tellg() << endl;
cout << fs.tellp() << endl;
fs.seekg(-6, ios::end); // 从文件尾开始
fs << "abc";
return 0;
}
这里只打开一次文件,可以不用 fs.close(),析构函数会自己析构;
但如果向上面的例子,多次打开同一个文件,则必须手动关闭;
seekg () 设置读位置;
seekp () 设置写位置;
tellg () 返回流中 get 指针当前位置;
tellp () 返回流中 put 指针当前位置;
5. 二进制 I/O 流:read/write
read 读取数据,成功返回读取的字节数;出错返回 -1 并设置 error;
如果在调用 read 之前已经到文件尾,则返回 0;
fread 和 read 区别:
1)fread 是 c 语言的库,而 read 是系统调用;
2)read 每次读取的数据是用户要求的大小,fread 为了加快读取速度,会读取一个缓冲区大小,读到的内容放入缓冲区;
在 32 位机器下,一般是 4096 个字节;
write 写入数据,成功返回写入的字节数;出错返回 -1 并设置 error;
实现文件加解密:
原理:运用异或实现加解密
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstdlib>
using namespace std;
#define BUFSIZE (1024*10) // 缓冲区
int _xor(const char* src, const char* dst, unsigned char key) { // 加解密
ifstream ifs(src, ios::binary); // 二进制方式创建,window 有区别,linux 无区别
if(! ifs) {
perror("write error");
return -1;
}
ofstream ofs(dst, ios::binary);
if(! ofs) {
perror("read error");
return -1;
}
char* buf = NULL;
try {
buf = new char[BUFSIZE]; // 放入缓冲区,日后作比较用
}
catch (bad_alloc& ex) {
cout << ex.what() << endl;
return -1;
}
while(ifs.read(buf, BUFSIZE)) {
// BUFSIZE 期望值,如果读到的比期望字节少返回 false,一样返回 ture
for(size_t i = 0; i < BUFSIZE; ++i)
buf[i] ^= key;
ofs.write(buf, BUFSIZE);
if(! ofs.write(uf, BUFSIZE)) {
perror("write error");
return -1;
}
}
if(! ifs.eof()) {(char*)&dog
perror("read error");
return -1;
}
for(size_t i = 0; i < ifs.gcount(); ++i)
buf[i] ^= key;
if(! ofs.write(uf, ifs.gcount()) {
perror("write error");
return -1;
}
}
int enc(const char* plain, const charI cipher) {
srand(time(NULL)); // 随机因子
unsigned char key = rand() % 256; // 取出随机数
if(_xor(plain, cipher,key) == -1)
return -1;
cout << "秘匙 :" << (unsigned int)key << endl;
return 0;
}
int dec(const char* cipher, const char* plain, unsigned char key) {
return _xor(cipher,plain,key);
}
int main(int argc, char* argv[]) {
if(argc < 3) {
cerr << "用法:" << argv[0]
<< "明文文件/密文文件" >> endl;
cerr << "用法:" << argv[0]
<< "密文文件/明文文件/秘匙" >> endl;
return -1;
}
if(argc < 4)
return enc(argv[1], argv[2]);
else
return dec(argv[1], argv[2], atoi[3])
return 0;
}
6. 格式控制 I/O 流
方法一:通过流函数实现;
方法二:流控制符;需要包含头文件 #include <iomanip>
#include <iomanip>
#include <cmath>
cout << sqrt(2); // 输出 2 的平方根;默认输出六位;
cout.precision(10); // 流函数实现输出 10 位有效数字;对下面的所有语句都有作用;
cout << sqrt(3); // 输出 10 位有效数字;
cout << setprecision(5) << sqrt(2); // 改变精度,输出 5 位有效数字;
cout << cout.precision(); // 返回当前精度;输出:5
cout << setprecision(2) << 1.25 << 1.26; // 前者输出:1.2,后者输出:1.3
cout << showbase << hex << 127; // 十六进制
cout << oct << 127; // 八进制
cout << dec << 127; // 十进制
cout << noshowbase << hex << 127 << dec; // 不显示 0x
cout << setw(12) << 127; // 占用12个字符,127靠右显示,空格填充
cout << setw(12) << 127 << 99; // 12799(前面 9 个空格)
cout << setfill('&') << left << setw(12) << 127; // 输出:127&&&&&&&&&
cout << setw(12) << showpos << internal << 4; // 输出:+ 4
cout << setw(12) << showpos << internal << -4; // 输出:- 4
cout.precision(10);
cout.setf(ios::scientific); // 科学计数法
cout << sqrt(2);
cout.setf(ios::fixed); // 普通
cout << sqrt(2);
cout << 12.00; // 输出:12
cout << showpoint << 12.00; // 输出:12.00000000(因为前面设置精度为 10 )
cout << noshowpoint << 12.00; // 输出:12
bool b = 1;
cout << boolalpha << b; // 输出:true
小结:
cout.setw(4); // 对其后所有行都有影响;
cout << set(4) << b; // 对其后一行有影响;
举例:
假设 hello.txt 内容为:a b c
#include <fstream>
ifstream ifs("hello.txt");
char c;
while(ifs >> c) // 用格式化 >> 读取
cout << c; // 输出:abc(中间的空格不见了)
ifs.close();
------------解决办法----------------
#include <fstream>
ifstream ifs("hello.txt");
ifs.unsetf(ios::skipws); // 取消空格、制表符、回车等符号标志
char c;
while(ifs >> c)
cout << c; // 输出:a b c
ifs.clear(); // 清除之前的流状态,否则无法再次读出;
ifs.setf(ios::skipws); // 恢复
ifs.seekg(ios::beg); // 指针移到文件头
while(ifs >> c)
cout << c;
ifs.close();
7. 字符串 I/O 流
#include <sstream>
#include <fstream>
int i = 1234;
double d = 26.45;
string s = "tarena";
ostringstream oss;
oss << i << d << s; // 自动把上面的 i d s 三个变量值装入 oss,保存于内存中;
string str = oss.str();
cout << str;
// 读取字符串
str = "hello 1234";
istringstream iss;
iss.str(str);
iss << s << i; // 把 hello 放入 s,1234 放入 i
cout << s << i; // 输出:hello 1234
举例:输入输出文件对类类型的影响
#include <fstream>
class Dog {
public:
Dog(const string& name = "", int age = 0) : m_name(name), m_age(age) {}
void print() { cout << "hello" << endl; }
private:
string m_name;
int m_age;
};
int main() {
ofstream ofs("dog.dat");
Dog dog("bai", 25);
ofs.write((char*)&dog, sizeof(dog));
// 首先:write 要求传入的是 T* 格式,所以这里强制类型转换为 char*
// 其次:传入的是 dog 地址,也就传入了 m_name 的首地址,而 m_name 的内容没有传入;
ofs.close();
// 读取文件:
ifstream ifs("dog.dat");
Dog dog2;
ifs.read((char*)&dog2, sizeof(dog2)); // 也读取 m_name 首地址;
dog2.print();
ifs.close();
return 0;
}
运行会提示吐核错误(两次释放内存);
-----------------解决办法-----------------------
#include <fstream>
#include <cstring>
class Dog {
public:
Dog(const string& name = "", int age = 0) : m_age(age)
{ strcpy(m_name, name.c_str); } // 利用 strcpy 函数赋值
void print() { cout << "hello" << endl; }
private:
char m_name[128]; // 首先把名字字符串放到数组里
int m_age;
};
int main() {
ofstream ofs("dog.dat");
Dog dog("bai", 25);
ofs.write((char*)&dog, sizeof(dog));
ofs.close();
ifstream ifs("dog.dat");
Dog dog2;
ifs.read((char*)&dog2, sizeof(dog2));
dog2.print();
ifs.close();
return 0;
}
C: fopen/fclose/fread/fwrite/fprintf/fscanf/fseek/ftell/fput/fget...
C++: 对基本的 I/O 操作做了类的封装,其功能没有任何差别,用法也相似;
2. 格式化 I/O 流:<< / >>
#include <iostream>
#include <fstream> // 打开文件
using namespace std;
int main() {
// 写文件:
ofstream ofs("hello.txt"); // 创建文件,类似于 fopen 用 w 模式,只读且清空
// ofs 在 ofstream 的构造函数里面被构造,打开成功返回 ture,失败返回 false,是 bool 型;
if(! ofs) {
perror("error"); // perror 打印出错信息;
return -1;
}
ofs << "hello word!" << endl; // hello word! 被输入文件 hello.txt 里;
ofs.close();
ofs.open("hello.txt", ios::app); // 打开文件,追加内容,类似于 fopen 的 a 模式
if(! ofs) {
perror("error");
return -1;
}
ofs << "another\n";
ofs.close();
// 读文件:
ifstream ifs("hello.txt");
if(! ifs) {
perror("error");
return -1;
}
steing s1, s2;
ifs >> s1 >> s2; // 读入上面输入的两个字符串;以空白字符作为分隔(空格、换行、制表);
return 0;
}
ios::app 以追加的方式打开文件;
ios::ate 文件打开后定位到文件尾;
ios::binary 以二进制方式打开文件;缺省是文本方式;
ios::in 以输入方式打开;
ios::out 以输出方式打开;
ios::nocreate 不建立文件,所以文件不存在时,打开失败;
ios::noreplace 不覆盖文件,所以打开文件时,如果文件存在则失败;
ios::trunc 如果文件存在,把文件长度设为 0;
ios::beg 移动到文件头;
ios::cure 移动到文件当前位置;
ios::end 移动到文件尾;
可以用 或 把以上文件属性连接起来:
3. 非格式化 I/O 流:put/get
#include <iostream>
#include <fstream>
using namespace std;
int mian() {
// 输入
ofstream ofs("putget.txt");
if(! ofs) {
perror("error");
return -1;
}
for(char c = ' '; c <= '~'; ++c) // 把 ASIIC 表里的字符从第一个到最后一个写入;
// 前++返回引用,后++返回副本,所以建议用前++,效率高;
if(! ofs.put(c)) {
preeor("error");
return -1;
}
ofs.close();
// 输出
ifstream ifs("putget.txt");
if(! ifs) {
perror("error");
return -1;
}
char c;
while((c = ifs.get()) != EOF) // 因为 ASIIC 里没有 EOF,所以用 EOF 作判断;
// 无论是读取失败或者读完文件,都返回 EOF,所以下面加 if 语句判断是否出错;
cout << c;
if(ifs.error()) { // error 判断读取是否出错
// 相当于:if(! ifs.eof()) { // eof 判断是否到文件尾;
perror("error");
return -1;
}
ifs.close();
return 0;
}
EOF:成员函数 eof();用来检测是否到达文件尾;
如果到达文件尾,返回非 0;否则返回 0;
4 随机 I/O 流:seekp/seekg, tellp/tellg(文件指针)
#include <iostream>
#include <fstream>
using namespace std;
int mian() {
// 输入
fstream fs("seek.txt", ios::in | ios::out); // 可读可写,相当于:w+
if(! ofs) {
perror("error");
return -1;
}
fs << "0123456789";
cout << fs.tellp() << endl;
cout << fs.tellg() << endl;
fs.seekp(-3, ios::cur); // 当前位置往前挪 3 个位置
fs << "xyz"; // 0123456xyz(文件默认操作只有覆盖,没有插入)
fs.seekg(4, ios::beg); // 从文件头开始挪;
int i;
fs >> i;
cout << i << endl;
cout << fs.tellg() << endl;
cout << fs.tellp() << endl;
fs.seekg(-6, ios::end); // 从文件尾开始
fs << "abc";
return 0;
}
这里只打开一次文件,可以不用 fs.close(),析构函数会自己析构;
但如果向上面的例子,多次打开同一个文件,则必须手动关闭;
seekg () 设置读位置;
seekp () 设置写位置;
tellg () 返回流中 get 指针当前位置;
tellp () 返回流中 put 指针当前位置;
5. 二进制 I/O 流:read/write
read 读取数据,成功返回读取的字节数;出错返回 -1 并设置 error;
如果在调用 read 之前已经到文件尾,则返回 0;
fread 和 read 区别:
1)fread 是 c 语言的库,而 read 是系统调用;
2)read 每次读取的数据是用户要求的大小,fread 为了加快读取速度,会读取一个缓冲区大小,读到的内容放入缓冲区;
在 32 位机器下,一般是 4096 个字节;
write 写入数据,成功返回写入的字节数;出错返回 -1 并设置 error;
实现文件加解密:
原理:运用异或实现加解密
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstdlib>
using namespace std;
#define BUFSIZE (1024*10) // 缓冲区
int _xor(const char* src, const char* dst, unsigned char key) { // 加解密
ifstream ifs(src, ios::binary); // 二进制方式创建,window 有区别,linux 无区别
if(! ifs) {
perror("write error");
return -1;
}
ofstream ofs(dst, ios::binary);
if(! ofs) {
perror("read error");
return -1;
}
char* buf = NULL;
try {
buf = new char[BUFSIZE]; // 放入缓冲区,日后作比较用
}
catch (bad_alloc& ex) {
cout << ex.what() << endl;
return -1;
}
while(ifs.read(buf, BUFSIZE)) {
// BUFSIZE 期望值,如果读到的比期望字节少返回 false,一样返回 ture
for(size_t i = 0; i < BUFSIZE; ++i)
buf[i] ^= key;
ofs.write(buf, BUFSIZE);
if(! ofs.write(uf, BUFSIZE)) {
perror("write error");
return -1;
}
}
if(! ifs.eof()) {(char*)&dog
perror("read error");
return -1;
}
for(size_t i = 0; i < ifs.gcount(); ++i)
buf[i] ^= key;
if(! ofs.write(uf, ifs.gcount()) {
perror("write error");
return -1;
}
}
int enc(const char* plain, const charI cipher) {
srand(time(NULL)); // 随机因子
unsigned char key = rand() % 256; // 取出随机数
if(_xor(plain, cipher,key) == -1)
return -1;
cout << "秘匙 :" << (unsigned int)key << endl;
return 0;
}
int dec(const char* cipher, const char* plain, unsigned char key) {
return _xor(cipher,plain,key);
}
int main(int argc, char* argv[]) {
if(argc < 3) {
cerr << "用法:" << argv[0]
<< "明文文件/密文文件" >> endl;
cerr << "用法:" << argv[0]
<< "密文文件/明文文件/秘匙" >> endl;
return -1;
}
if(argc < 4)
return enc(argv[1], argv[2]);
else
return dec(argv[1], argv[2], atoi[3])
return 0;
}
6. 格式控制 I/O 流
方法一:通过流函数实现;
方法二:流控制符;需要包含头文件 #include <iomanip>
#include <iomanip>
#include <cmath>
cout << sqrt(2); // 输出 2 的平方根;默认输出六位;
cout.precision(10); // 流函数实现输出 10 位有效数字;对下面的所有语句都有作用;
cout << sqrt(3); // 输出 10 位有效数字;
cout << setprecision(5) << sqrt(2); // 改变精度,输出 5 位有效数字;
cout << cout.precision(); // 返回当前精度;输出:5
cout << setprecision(2) << 1.25 << 1.26; // 前者输出:1.2,后者输出:1.3
cout << showbase << hex << 127; // 十六进制
cout << oct << 127; // 八进制
cout << dec << 127; // 十进制
cout << noshowbase << hex << 127 << dec; // 不显示 0x
cout << setw(12) << 127; // 占用12个字符,127靠右显示,空格填充
cout << setw(12) << 127 << 99; // 12799(前面 9 个空格)
cout << setfill('&') << left << setw(12) << 127; // 输出:127&&&&&&&&&
cout << setw(12) << showpos << internal << 4; // 输出:+ 4
cout << setw(12) << showpos << internal << -4; // 输出:- 4
cout.precision(10);
cout.setf(ios::scientific); // 科学计数法
cout << sqrt(2);
cout.setf(ios::fixed); // 普通
cout << sqrt(2);
cout << 12.00; // 输出:12
cout << showpoint << 12.00; // 输出:12.00000000(因为前面设置精度为 10 )
cout << noshowpoint << 12.00; // 输出:12
bool b = 1;
cout << boolalpha << b; // 输出:true
小结:
cout.setw(4); // 对其后所有行都有影响;
cout << set(4) << b; // 对其后一行有影响;
举例:
假设 hello.txt 内容为:a b c
#include <fstream>
ifstream ifs("hello.txt");
char c;
while(ifs >> c) // 用格式化 >> 读取
cout << c; // 输出:abc(中间的空格不见了)
ifs.close();
------------解决办法----------------
#include <fstream>
ifstream ifs("hello.txt");
ifs.unsetf(ios::skipws); // 取消空格、制表符、回车等符号标志
char c;
while(ifs >> c)
cout << c; // 输出:a b c
ifs.clear(); // 清除之前的流状态,否则无法再次读出;
ifs.setf(ios::skipws); // 恢复
ifs.seekg(ios::beg); // 指针移到文件头
while(ifs >> c)
cout << c;
ifs.close();
7. 字符串 I/O 流
#include <sstream>
#include <fstream>
int i = 1234;
double d = 26.45;
string s = "tarena";
ostringstream oss;
oss << i << d << s; // 自动把上面的 i d s 三个变量值装入 oss,保存于内存中;
string str = oss.str();
cout << str;
// 读取字符串
str = "hello 1234";
istringstream iss;
iss.str(str);
iss << s << i; // 把 hello 放入 s,1234 放入 i
cout << s << i; // 输出:hello 1234
举例:输入输出文件对类类型的影响
#include <fstream>
class Dog {
public:
Dog(const string& name = "", int age = 0) : m_name(name), m_age(age) {}
void print() { cout << "hello" << endl; }
private:
string m_name;
int m_age;
};
int main() {
ofstream ofs("dog.dat");
Dog dog("bai", 25);
ofs.write((char*)&dog, sizeof(dog));
// 首先:write 要求传入的是 T* 格式,所以这里强制类型转换为 char*
// 其次:传入的是 dog 地址,也就传入了 m_name 的首地址,而 m_name 的内容没有传入;
ofs.close();
// 读取文件:
ifstream ifs("dog.dat");
Dog dog2;
ifs.read((char*)&dog2, sizeof(dog2)); // 也读取 m_name 首地址;
dog2.print();
ifs.close();
return 0;
}
运行会提示吐核错误(两次释放内存);
-----------------解决办法-----------------------
#include <fstream>
#include <cstring>
class Dog {
public:
Dog(const string& name = "", int age = 0) : m_age(age)
{ strcpy(m_name, name.c_str); } // 利用 strcpy 函数赋值
void print() { cout << "hello" << endl; }
private:
char m_name[128]; // 首先把名字字符串放到数组里
int m_age;
};
int main() {
ofstream ofs("dog.dat");
Dog dog("bai", 25);
ofs.write((char*)&dog, sizeof(dog));
ofs.close();
ifstream ifs("dog.dat");
Dog dog2;
ifs.read((char*)&dog2, sizeof(dog2));
dog2.print();
ifs.close();
return 0;
}
0 0
- c++笔记08---I/O 流,格式化 I/O,非格式化 I/O,随机 I/O,二进制 I/O
- 二进制、字符I/O、格式化I/O
- 格式化I/O函数
- 格式化I/O
- c++I/O流
- I/O
- I/O
- I/O
- I/O
- I/O
- I/O
- I/O
- I/O
- I/O
- i/o
- I/O
- I/O
- I/O
- eclipse快捷键大全
- JSON在线校验工具
- 分布式Hibernate search
- jqGrid设置三级表头和表头合并
- 【c++ templates读书笔记】【5】模板实战
- c++笔记08---I/O 流,格式化 I/O,非格式化 I/O,随机 I/O,二进制 I/O
- Android Studio如何更改SDK的版本(非gradle)
- SwitchySharp
- irrlicht启动两个控制台
- 经典算法题——第九题 优先队列
- 添加Rubygems的国内镜像站点
- Android 获取控件的宽高的靠谱方式
- core dump文件
- 两个队列实现一个栈