C++学习笔记11:输入输出流、(重载输入输出运算符、二进制文件读写,文本文件读写,一组数据文件的读写,随机访问实例)

感谢 https://blog.csdn.net/qq_38289815/article/details/82388157

输入/输出流简介
C++流类库简介
输入/输出流
自定义类型的输入/输出
文件的输入/输出

输入/输出流简介

数据的输入输出是最重要的操作,C++的输入输出有iostream库提供支持,它利用多继承和虚拟继承实现了面向对象类层次结构。C++的输入、输出机制为内置数据类型的输入、输出提供了支持,同时也支持文件的输入输出。在此基础上,设计者可以通过扩展iostream库,为新类型的数据读写进行扩展。
C++学习笔记11:输入输出流、(重载输入输出运算符、二进制文件读写,文本文件读写,一组数据文件的读写,随机访问实例)_第1张图片

C++流类库简介

今天把这节整理完,还有多态底层再理解整理,就开始看网络编程,之后的这个月就白天上课晚上看看弄弄论文。加油争取四月底就把课上完,项目有个样。然后就开始源码剖析,刷题整理,知识点深入(五月)加油加油。要早起,休息时间做做运动。

C语言中的scanf和printf很灵巧高效,但不是类型安全的,而且没有扩展性。scanf/printf系列函数要求把读写的变量和控制读写的格式信息分开。而C++正是克服了这些缺点,使用cin/cout控制输入/输出。(类型安全就是指如果两个类型要相互转换,必须显示地转换,不能隐式地只用一个等号就转换了

  • 1,cin,表示标准输入的istream类对象,cin从终端读入数据
  • 2,cout,表示标准输出的ostream类对象,cout向终端写数据
  • 3,cerr,表示标准错误输出(非缓冲方式),导出程序错误信息
  • 4,clog,表示标准错误输出(缓冲方式),导出程序错误信息

为了在程序中使用cin/cout,必须要加iostream库的相关头文件#include

iostream类同时从istream类和ostream类派生而来,允许双向输入/输出。输入有重载的操作符>>完成,输出由重载的操作符<<来完成。输入输出格式:

cin >> 变量名;
cout << 变量名或常量;

除了用户终端的输入/输出,C++还提供了文件的输入/输出类:

  • 1,ifstream,从istream派生而来,把文件绑定到程序上输入
  • 2,ofstream,从ostream派生而来,把文件绑定到程序输出
  • 3,fstream,从iostream派生而来,把文件绑定到程序输入/输出

使用iostream库的文件流,必须包含相关的头文件:#include

文件读写示例:⭐⭐⭐

#include
#include
#include
using namespace std;
//文件操作需要用到头函数fstream
//用ifstream打开源文件,备读
//用ofstream打开目标文件,备写
int main()
{
	string sourcName("asdfile.txt");//定义源文件
	ifstream sourceFile(sourceName.c_str());//打开源文件流类
	if(!sourceFile)
	{
		cout<<"Error:打不开"<<sourceName<<endl;
		return -1;
	}
	string destinationName("z");//定义目标文件
	ofstream destinationFile(destinationName.c_str());//打开目标文件流
	if(!destinationFile)
	{
		cout<<"Error:打不开"<<destinationName<<endl;
		return -1;
	}
	string buf;
	while(sourceFile >> buf)
	{
		destinationFile << buf;//输出到目标文件
	}
	return 0;
}

输入/输出流

基本输出流

C++的ostream提供了丰富的格式化和无格式化的输出功能:
流插入符输出标准数据类型;
put库成员函数输出字符;
以八进制、十进制、十六进制输出数据;
以各种精确方式输出浮点型数据;
以科学计数法定点输出数据;
以指定宽度输出数据;
在区域内用指定字符填充等

流输出可以用流插入运算符,即重载的<<来完成。运算符<<左边的操作数是istream类的一个对象如cout,右边是C++的合法表达式。

用插入运算符实现流输出:

using namespace std;
int main()
{
	cout<<"hello C++\n";
	return 0;
}

输出操作符可以接受任何内置数据类型的实参, 包括const char*,以及标准库string和complex类类型。任何表达式包括函数调用,都可以是输出操作符的实参,只要它的计算结果是一个被输出操作符实例接受的数据类型即可。
函数调用操作符的实参:

using namespace std;
int main()
{
	cout<<strlen("hello!")<<endl;
	return 0;
}

C++还提供了指针预定义输出操作符,允许输出项为显示对象的地址。默认情况下,地址以十六进制的形式显示:

#include 
using namespace std;
 
int main()
{
	int i = 10;
	int *p = &i;
	cout << "i:" << i << " &i:" << &i <<endl;
	cout << "*p" << *p << "  p:" << p << " &p:" << &p <<endl;
	return 0;
}

C++学习笔记11:输入输出流、(重载输入输出运算符、二进制文件读写,文本文件读写,一组数据文件的读写,随机访问实例)_第2张图片关于输入操作符的优先级

#include 
using namespace std;
 
int main()
{
	int i = 10, j = 20;
	cout << "The max is ";
	cout << (i>j)?i:j;
        cout <<endl;
	return 0;
}

结果:
在这里插入图片描述
结果输出0问题在于输入操作符的优先级高于条件操作符,所以输出i、j的比较结果的bool值。即表达式被解析为(cout<<(i>j))?i:j;因为ij)?i:j);由此得到正确结果:the max is 20

基本输入流

对应于输出,C++提供了实用的输入功能,类似于输出流中的流插入符,输入中引入了流读取符

流输入可以用流读取运算符,即重载的>>,读取符是个双目运算符,左边的操作数是istream类的一个对象如cin,右边的操作数是系统定义的任何数据类型的变量,例如:int i; cin>>i;从键盘输入的数据会自动转换成i的类型,存储到变量i中。

注意:
(1)输入运算符>>也支持级联输入。在默认情况下,运算符>>跳过空格,读入后面与变量类型相应的值。因此给一组变量输入值时,用空格或换行将输入的数值间隔开,例如:

int i;
float f;
cin >> i >> f;

(2)当输入字符串(char*类型)时,输入运算符>>会跳过空格,读入后面的非空格符,直到遇到另外一个空格结束,并在字符串末尾自动放置字符’\0’作为结束标志,例如:

char s[20];
cin>> s;

(3)数据输入时,不仅检查数据间的空格,还做类型检查、自动匹配

格式化输入/输出

在很多情况下,用户希望自己控制输出格式。C++提供两种格式控制方法:
1,通过使用ios类中的格式控制函数
2,使用称为操纵符的特殊类型函数

一、在ios类中,格式控制函数主要是通过对状态字、域宽、填充字及其精度来完成的。输入/输出格式由一个long int类型的状态字确定。在ios类的public部分进行了枚举。

skipws             跳过输入中的空白
left               左对齐格式输出
right              右对齐格式输出
internal           在符号位和数值之间填入字符
dec                十进制显示
oct                八进制显示
hex                十六进制显示
showbase           产生前缀,指示数值的进制基数
shwopoint          总是显示小数
uppercase          在十六进制下显示0X,科学计数法显示E
showpos            在非负数值中显示+
boolalpha          把truefalse表示为字符串
scientific         以科学计数法形式显示浮点数
fixed              以小数形式显示浮点数
unitbuf            输出操作后立即刷新所有流
stdio              输出操作后刷新stdoutstderr
  1. 设置状态标识
  2. 清除状态标识
  3. 取状态标识
  4. 设置域宽
  5. 设置填充字符
  6. 设置显示精度
    ====就之后再看吧555

二、操纵符控制格式,类似于函数的运算符,使用操纵符方法可以嵌入到输入、输出语句中。
所有不带参数的操作符定义在头文件iostream中,带形参的操纵符定义在头文件iomanip中,常见的有:

ws                      在输入时跳过开头的空白符,仅用于输入
endl                    换行并刷新输出流,仅用于输出
ends                    插入一个空字符,仅用于输出
dec                     十进制显示
oct                     八进制显示
hex                     十六进制显示
setfill(ch)             用ch填充空白字符
setprecision(n)         将浮点数精度设置为n
setw(w)                 按照w个字符来读或写数值
setbase(b)              以进制基数b来输出整数值
setiosflags(n)          设置由n指定的格式标志
resetiosflags(n)        清除由n指定的格式标志

例子

#include 
#include 
using namespace std;
 
int main()
{
	int i = 123;
	float f =2018.0903;
	const char* const str = "hello! every one!";
	cout << "default width is:" << cout.width() <<endl;
	cout << "default fill is:" << cout.fill() <<endl;
	cout << "default precision is:" << cout.precision() <<endl;
	cout << "i = " << i << "  f = " << f << "  str = " << str <<endl;
	cout << "i = " << setw(12) << setfill('*') << i <<endl;
	cout << "i(hex) = " << hex << i << "  i(oct) = " << oct << i << endl;
	cout << "f = " << setw(12) << setprecision(3) << f <<endl;
	cout << "f = " << setw(12) << fixed << f <<endl;
	cout << "str = " << setw(20) << left << str <<endl;
	return 0;
}

C++学习笔记11:输入输出流、(重载输入输出运算符、二进制文件读写,文本文件读写,一组数据文件的读写,随机访问实例)_第3张图片

另外除了系统提供的预定义操纵符之外,C++还允许用户自己定义操纵符,便于控制一些频繁使用的格式操作,使得格式控制更加方便。

自定义输出流操纵符算子格式如下:

ostream & 自定义输出操纵符算子函数名 (ostream& stream)
{
    ...//自定义代码
    return stream;
}

自定义输入流操纵符算子格式如下:

istream & 自定义输出操纵符算子函数名 (istream& stream)
{
    ...//自定义代码
    return stream;
}

例子

#include 
#include 
using namespace std;
 
ostream &myoutput(ostream& stream)
{
	stream << setw(10) << setfill('#') <<left;
	return stream;
}
 
int main()
{
	int i = 123;
	cout << i <<endl;
	cout << myoutput << i <<endl;
	return 0;
}

自定义操纵符函数myoutput(),功能是设置域宽为10,填充字符为#,并采用左对齐。函数参数为引用方式,cout的返回值为引用方式且可以多级输出,所以在主函数中只写myoutput即可。

自定义输入操作函数:

#include 
using namespace std;
 
istream &myinput(istream& stream)
{
	cout << "please input a hex integer:";
	stream >> hex;
	return stream;
}
 
int main()
{
	int i;
	cin >> myinput >> i;
	cout << "i(dec) = " << i << "  i(hex) = " << hex << i <<endl;
	return 0;
}

其他的输入/输出函数

仅仅靠cin只能得到不包括空格的字符串,因此C++还提供了以下输入/输出函数

get()put()函数

get(char &ch)从输入流中提取一个字符,包括空白字符,并把它存储在ch中,返回被引用的istream对象。此函数在类istream中 对应于get(),类ostream提供了put(char ch)函数,用于输出字符

get()的重载版本:get(char *str, streamsize size, char delimiter = '\n');

str代表一个字符数组,用来存放被读取的字符。size代表可以从istream中读入的字符的最大数目。delimiter表示如果遇到它就结束读取字符的动作,delimiter本身不会被读入,而是留在istream中,作为istream的下一个字符。

下面例子使用istream的成员函数ignore()来去掉delimiter。默认情况下,delimiter为换行符。

using namespace std;
int main()
{
	const int str_len = 100;
	char str[str_len];
	while(cin.get(str,str_len))
        //当读入的数据不为空时循环下一次,每次最多读入str_len个
	{
		int count = cin.gcount();    //当前实际读入多少个字符
		cout << "the number is:" << count <

C++学习笔记11:输入输出流、(重载输入输出运算符、二进制文件读写,文本文件读写,一组数据文件的读写,随机访问实例)_第4张图片====》getline()函数:

使用get()函数输入字符串时,经常忘记去掉delimiter,所以引入函数getline(),其原型与get()的重载版本相同

getline(char *str, streamsize size, char delimiter = '\n');

ostream类成员函数write()提供一种输出字符数组的方法。它不是输出”直到终止字符为止”,而是输出某个长度的字符序列,包括空字符。函数原型如下:

====》 write(), read()函数

write(char *str, streamsize length);

str是要输出的字符数组,length是要显示的字符个数。write()返回当前被调用的ostream类对象。

istream类的read()函数,原型如下:

read(char *str, streamsize size);

read()函数从输入流中读取size个连续的字符,并将其放在地址从str开始的内存中。

gcount()方法返回最后一个非格式化的抽取方法读取的字符数。这意味着字符由get()、getline()、ignore()、或read()方法读取的,不是由抽取操作符( >> )读取的,抽取操作符对输入进行格式化,使之与特定的数据类型匹配。

输入/输出综合实例:(まだ)

#include 
using namespace std;
 
int main()
{
	const int str_len = 100;
	char str[str_len];
	int iline = 0;       //行数
	int max = -1;        //最长行的长度
	while(iline < 3)
	{
		cin.getline(str, str_len);
		int num = cin.gcount();//gcount的返回值是获取的字符数,但是这个获取值要被统计,就是肉眼可见+1
		cout << "the number is:" << num <<endl;
		iline++;
		if(num > max)
			max = num;
		cout << "Line#" << iline << "\t chars read:" << num <<endl;
		cout.write(str, num).put('\n').put('\n');
	}
	cout << "Total lines:" << iline <<endl;
	cout << "The longest line:" << max <<endl;
	return 0;
}

自定义类型的输入/输出

当实现一个类的类型时,有时希望这个类支持输入和输出操作,以便可以将类对象嵌入到输入或输出流中。前面的函数都是C++系统预定义数据类型的输入/输出。对于用户自己定义的数据类型的输入/输出,可以通过重载运算符”>>”和”<<”实现。

重载输出运算符 “<<”

其重载函数的格式如下:

ostream & operator << (ostream &out, class_name &obj)
{
	out<<obj.data1;
	out<<obj.data2;
	......
	return out;
}

函数中第一个参数out是对ostream对象的引用,即out必须是输出流对象;第二个参数是用户自定义要输出的类对象的引用,data1,data2……datan是类内要输出的数据成员。输出运算符“<<”不能作为类的成员函数,只能作为友元函数(要访问类的私有成员)来实现。

输出运算符重载:

#include 
#include 
using namespace std;
 
class Word
{
	char *word;
	size_t num;       //存储的字符个数
public:
	Word(const char* const str = NULL);
	virtual ~Word()
	{
		if(word)  //清除指针
			delete []word;
	}
	friend ostream& operator<<(ostream& out, Word& sword);//友元
};
 
Word::Word(const char* const str)
{
	if(str != NULL)
	{
		num = strlen(str);
		word = new char[num+1];
		strcpy(word,str);
	}
}
 
ostream& operator<<(ostream& out, Word& sword)
{
	out << "<" << sword.num << ">" << sword.word <<endl;
	return out;
}
 
int main()
{
	Word word("hello");
	cout << word;
	return 0;
}

程序为类word重载输出运算符”<<”,使得可以通过cout简单地输出word类对象的内容:字符串和字符串长度。在类word的构造函数里,为类成员word申请空间(包括字符串结束标志’\0’),在析构函数中,相应地释放成员word的空间。重载函数的第二个参数为引用形式,可以转为普通形式,但是引用减少了调用开销。

重载输入运算符 “>>”

输入运算符”>>”,又称为提取运算符,定义其重载函数的格式如下:

istream &operator>>(istream &in, class_name& obj)
{
    in >> obj.data1;
    in >> obj.data2;
    ......
    in >> obj.datan;
    return out;
}

输入运算符也不能作为类的成员函数,只能作为类的友元函数或独立函数。重载函数第二个参数必须为引用,且不能为常引用,因为要对参数进行修改。

输入运算符重载:

#include 
#include 
using namespace std;
 
class Word
{
	char *word;
	size_t num;
	public:
	Word(const char* const str = NULL);
	virtual ~Word()
	{
		if(word)
			delete []word;
	}
	friend ostream& operator<<(ostream& out, Word& sword);//友元
	friend istream& operator>>(istream& in, Word& sword);//友元
};
 
Word::Word(const char* const str)
{
	if(str != NULL)
	{
		num = strlen(str);
		word = new char[num+1];
		strcpy(word,str);
	}
}
 
ostream& operator<<(ostream& out, Word& sword)
{
	out << "<" << sword.num << ">" << sword.word <<endl;
	return out;
}
 
istream& operator>>(istream& in, Word& sword)
{
	char str[100];
	in.getline(str, 100);
	if(in.gcount() > 0)
	{
		delete []sword.word;
		sword.num = strlen(str);
		sword.word = new char[sword.num+1];
		strcpy(sword.word, str);
	}
	return in;
}
 
int main()
{
	Word word("hello");
	cout << word;
	cin >> word;
	cout << word;
	return 0;
}

文件的输入/输出

变量中的数据保存在内存中,是临时的;文件数据保存在外存储器上,用于永久的保存大量的数据。根据数据的组织形式,
文件分为文本文件和二进制文件。文本文件的每个字节存放一个ASCII代码,代表一个字符;二进制文件把内存中的数据,按照其在内存中的存储形式原样写到磁盘上存放。

C++把每个文件看成一个有序的字节流(字符流或二进制流)。每个文件不是以文件结束符结束,就是以在系统维护和管理的数据结构中特定的字符结束。
文件打开时,就会创建一个对象,将这个对象和某个流关联起来。C++中,要进行文件的输入/输出,必须首先创建一个流,与文件关联,才能进行读写操作

C++进行文件处理时,需要包含头文件
头文件包括流类ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出)的定义。这三个流分别从istream、ostream和iostream类继承而来。
#include是非标准输入输出流,#include是标准输入输出流。C++中为了避免名字定义冲突,特别引入了”名字空间的定义”,即namespace。当代码中用时,输出可直接引用cout<继承C语言的标准库文件,未引入名字空间定义,所以可直接使用。当代码中引入时,输出需要引用std::cout<

using namespace std; 
cout<<x;using std::cout;
cout<<x;
 
③最基本的std::cout<<x;

顺序访问文件:

要正确地进行文件地输入/输出,需要遵循以下步骤:

  1. 定义相关地流对象
    包含头文件建立流,定义流对象
  2. 文件的打开
    打开文件有两种方法:①使用open函数 ②流类构造函数打开
    一、open()函数
    open函数是ifstream、ofstream和fstream类的成员函数。原型定义如下:
void open ( const char *,ios_base::openmode mode = ios_base::in | ios_base::out );
void open ( const unsigned char *, int mode, int access = filebuf::openprot );

第一个参数用来传递文件名称;第二个参数mode决定文件的打开方式

打开方式:
ios::app             将输出写入文件末尾
ios::ate             打开文件,并将文件指针移到文件末尾
ios::in              打开文件进行输入
ios::out             打开文件进行输出
ios::nocreate        文件不存在,则open()失败
ios::noreplace       文件存在,则open()失败
ios::trunc           删除文件中现有数据(覆盖同名文件)
ios::binary          以二进制方式打开,进行输入/输出(默认方式为文本方式)
 
打开文件的属性:
0 	             普通文件,打开操作
1	             只读文件
2	             隐含文件
4	             系统文件

例如

例如:
ofstream out;
out.open("test.tt", ios::out);   //表示用输出流对象out打开一个"test.tt"文件。

当一个文件需要多种方式打开时,可以用”或”操作符把几种方式连接在一起。例如打开一个能用于输入\输出的二进制文件:

fstream inout;
inout.open("test.tt", ios::in | ios::out | ios::binary);

打开文件后要判断是否打开成功:

if(inout.is_open())    //如果打开成功则进行读写操作
{...}

二、流类构造函数打开

虽然完全可以用open()函数打开文件,但是类ifstream、ofstream和fstream中的构造函数都有自动打开文件功能,这些构造函数的参数及默认值与open()函数完全相同。因此,打开文件的最常见形式简化为:文件输入/输出流类 流对象名(“文件名称”);

例如:ofstream out("test.tt");

使用构造函数打开文件后,直接使用流对象判断是否打开成功。

if(!out)
{
    cout << "文件打开失败!" <<endl;
    //错误处理
}
  1. 文件的读写:
    文件一旦打开,从文件中读取数据或向文件中写入数据将变得十分容易,只需要使用运算符”>>”和”<<”就可以了,只是必须用与文件相连接的流对象代替cin和cout。例如:
ofstream out("test.tt");
if(out)
{
    out << 10 << "hello!\n";
    out.close();
}
  1. 文件的关闭
    使用完文件后,应该把它关闭,即把打开的文件与流分开。对应于open()函数,使用close()函数关闭文件。在流对象的析构函数中,也具有自动关闭功能。

例子文本文件读写(文件的打开方式默认为文本方式)⭐⭐

#include 
#include 
using namespace std;
 
int main()
{
	char str[20] = "Welcome to C++!";
	int i = 1234;
	char ch;
	ofstream out("test.tt");     //打开输出文件流
	if(out)                      //如果成功
	{
		out << str << '\n' << i;   //向文件输入信息
		out.close();               //关闭
	}
 
	ifstream in("test.tt");            //打开输入文件流
	if(in)                          
	{                
		while(in.get(ch))          //输出显示
			cout << ch;
		cout <<endl;
		in.close();
	}
	return 0;
}

例子二进制文件读写⭐
文本文件中存放的是字符,而二进制文件中存放的是二进制位。对二进制文件读写有两种方式,一种是使用get()和put()函数。一种是使用read()和write()函数。当然,这4个函数也可用于文本文件的读写。

get()函数和put()函数原型如下:

istream& get(unsigned char& ch);
ostream& put(char ch);

get()是类istream的成员函数,功能是从文件流中只读取一个字节,并把值放在ch中,put()是类ostream的成员函数,功能是向文件流中写入一个字节ch。当读文件过程中遇到结束符时,与之相连的文件流值变为0,所以可以根据此判断文件是否结束。

实例:

#include 
#include 
using namespace std;
 
void myread(const char* fname)
{
	ifstream file_read(fname, ios::binary);
	char c;
	if(file_read)
	{
		while(file_read.get(c))       //文件没有结束时
			cout << c;              
	}
}
 
void mywrite(const char* fname)
{
	ofstream file_write(fname, ios::binary);
	char c = 'A';
		if(file_write)
		{
			for(int i = 0; i < 26; i++)
				file_write.put(c+i);
		}
}
 
int main()
{
	char fname[20] = "word.file";
	mywrite(fname);
	myread(fname);
        cout <<endl;
	return 0;
}

有时需要读写一组数据到文件,read()函数是类istream的成员函数,它从相应的流中读取num个字节放在buf所指向的缓冲区中。write()函数是ostream的成员函数,它从buf所指的缓冲区中向相应的流写入num个字节。例如:

int list[] = {12, 13, 14, 15};
write((unsigned char*)&list, sizeof(list));

定义了一个整形数组list,为了写入它的全部数据,必须在函数write()中指定它的首地址&list,并转换为unsigned char*类型,由sizeof()指定要写入的字节数。
一组数据的文件读写实例:☆★

#include 
#include 
using namespace std;
 
void myread(const char* fname)
{
	ifstream file_read(fname, ios::binary);
	char c[30];
	if(file_read)
	{
		file_read.read(c, 26*sizeof(char));
		c[26] = '\0';
		cout << c <<endl;
	}
}
 
void mywrite(const char* fname)
{
	char c[30];
	for(int i = 0; i < 26; i++)
		c[i] = 'A' + i;
	ofstream file_write(fname, ios::binary);
	if(file_write)
		file_write.write(c, 26*sizeof(char));
}
 
int main()
{
	char fname[20] = "word.file";
	mywrite(fname);
	myread(fname);
	return 0;
}

随机访问文件

顺序访问文件不适合快速访问的应用程序。为了增加程序的灵活性和快捷性,立即找到特定记录信息,C++提供了随机移动文件访问指针的函数,可以移动输入/输出流中的文件指针,从而对文件数据进行随机读写。

获得和设置流指针(get and put stream pointers)

所有输入/输出流对象(i/o streams objects)都有至少一个流指针:

fstream, 类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
ofstream, 类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
fstream, 类似 iostream, 同时继承了get 和 put

tellg() 和 tellp()
这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表**当前get 流指针的位置 (用tellg) 或 put 流指针的位置(**用tellp)。

C++支持的文件流中,通过文件指针方式从相应的文件位置进行读写。
其中的get()函数指针用于指出下一次输入操作的位置;
put()函数指针用于指出下一个输出操作的位置。
每当发生一次读写操作时,相应的get()函数指针或put()函数指针会自动连续地增加。
另外也可以使用seekg()函数和seekp()函数迅速定位,找到指定的位置访问文件。函数原型如下:
ostream& seekp(streamoff off, ios::seek_dir dir); istream& seekg(streamoff off, ios::seek_dir dir);

函数seekp()用于输出文件,将相应的文件指针get从dir的位置移动off个字节;函数seekg()用于输入文件,将相应的文件指针put从dir的位置移动到off个字节。
其中类型streamoff相当于long类型,定义文件指针要偏移的位置范围。参数dir表示文件指针的起始位置,off表示相对于这个位置移动的位偏移量。Dir取值如下:

ios::beg:从文件头开始,此时off取值为正。
ios::cur:从文件当前位置开始,此时off取值为负。
ios::end:从文件末尾开始,此时off取值可正可负。

获取一个二进制文件的大小:

#include 
#include 
    
const char * filename = "test.txt";
    
int main()
{
    long l,m;
    ifstream in(filename, ios::in|ios::binary);
    l = in.tellg();
    in.seekg (0, ios::end);
    m = in.tellg();
    in.close();
    cout << "size of " << filename;
    cout << " is " << (m-l) << " bytes.\n";
    return 0;
}
 

随机访问文件实例:

#include 
#include 
using namespace std;
 
void myread(const char* fname)
{
	ifstream file_read(fname, ios::binary);
	char c[10];
	if(file_read)
	{
		file_read.seekg(1, ios::beg);       //从开始位置移动1位
		file_read.get(c[0]);                //读取一个字符
		file_read.seekg(2, ios::cur);       //从当前位置移动2位
		file_read.get(&c[1], 4*sizeof(char));
                //一次读取1个字符,连续读取3次,最后一个'\0'
		cout << c;
	}
}
 
void mywrite(const char* fname)
{
	char c[30];
	for(int i = 0; i < 26; i++)
		c[i] = 'A' + i;
	ofstream file_write(fname, ios::binary);
	if(file_write)
		file_write.write(c, 26*sizeof(char));
}
 
int main()
{
	char fname[20] = "word.file";
	mywrite(fname);
	myread(fname);
        cout <<endl;
	return 0;
}

你可能感兴趣的:(C/C++,c++)