|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;4 E2 k4 k7 H4 A! G1 n( R/ [
% F7 [8 A) y& ?2 k9 k( g 在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:! _2 ^6 i7 J) X t! l
) ?9 w! y1 x& p$ N9 j- f4 J. P
1、插入器(<<), q8 Z4 @# R2 m8 p$ n
0 x9 V! M" N2 h$ E6 S5 p2 ` 向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。6 |# F& @6 ~1 U, h
6 l& M7 @* H$ F 2、析取器(>>)1 w: `! z; @+ [" Y
, w, O+ N" t% V( T# w! p" Y; @6 A 从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。2 Y E0 y) c: n7 Y" ` p
# g* _+ X8 r+ U. U+ ~6 t n* f6 ~
在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。) ]. d3 o* b8 z; u6 S8 Z S
: Y$ `2 T0 Q( Y. O2 v; L 一、打开文件
0 S _6 H1 s+ ~; N* b6 i
% ?' `/ N9 N' ~& w Z3 F 在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是: R" s8 D- L2 Y+ B1 {
9 r' t D6 f8 P
void open(const char* filename,int mode,int access);参数:: x# e& o4 I2 [/ o$ N/ L# |+ C& P. S
9 O$ ?& R4 `; U/ w2 P
filename: 要打开的文件名
: H$ y. K! _% ^- q" s+ ]
$ G- {* {7 }' g. k- A9 l. N# P8 l mode: 要打开文件的方式8 X8 w4 t* U7 k, w f1 D7 Z6 `
* S u3 H" T3 r) h& B
access: 打开文件的属性( f9 {( d: V. c, e
4 Q" p ]0 J% z& L3 t$ z
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:5 j6 W: y i9 A8 o9 O
0 }2 d" D0 |+ K; E1 u ios::app: 以追加的方式打开文件
+ t/ [8 k6 s2 {0 d' p3 X ' T$ P. k7 H- P: e; _" e! V b* u
ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性# ^8 j* y+ f4 u2 @; y5 z! O
" a: f0 l: K" J, K ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
: B9 B6 l- F7 |' l
8 Q) i& h/ M0 H4 Q C0 Y9 A) O ios::in: 文件以输入方式打开(文件数据输入到内存)0 M; j% D, ]! w" d' w
" g d' X* |- z& W, @
ios::out: 文件以输出方式打开(内存数据输出到文件)
, y% w. I& T* _# ^
7 e& I' N* x) T8 K6 i( ]. k ios::nocreate: 不建立文件,所以文件不存在时打开失败' ?2 b, W# f L; y0 x
2 x' _9 z" B/ d4 k9 ~ ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败' G: j U6 ]3 ?
' m: k v: @4 F, O! ]& w6 ~- Z
ios::trunc: 如果文件存在,把文件长度设为0
7 H/ ?0 F6 n( J. A
- K1 ?% s) l/ {, t1 \; R 可以用“或”把以上属性连接起来,如ios::out|ios::binary
8 a( U; ~. D$ v3 O
) l! m1 W0 z9 A4 E. h% C$ ` 打开文件的属性取值是:
9 u7 ]- T/ ]. j8 n& B4 \
$ t& B2 k2 \ D' `- w/ y. f 0:普通文件,打开访问
4 B$ \7 b* T& T( H( o7 g) X d, ^
! N! t7 p# r: K7 k8 a& l# i4 _( w- x 1:只读文件- R5 k% M% X2 ?! O2 J U. C
5 f9 b; F% p" n* Y6 u, v 2:隐含文件+ Z* I+ }6 B \# Z+ N; Y, t
6 X* L- I2 E3 [& p# D 4:系统文件
- `9 o% }/ a: B6 L( g( j. D
/ O) G+ J# z% W& R/ n 可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
+ [- x- e6 Q/ Z" } 6 y+ B) _, K9 S# d$ Z& X8 O( g4 W
例如:以二进制输入方式打开文件c:\config.sys
# @' B: m! w3 H2 w 9 B( s; `) G" p: W! ]
fstream file1;' C2 P8 I4 h$ i# D. |
8 H; k6 I7 m! l+ r, h$ ~6 `4 P
file1.open("c:\\config.sys",ios::binary|ios::in,0);
K; A% T0 Y8 q3 R# }4 j. W% ?9 [! a $ N& {9 a% o% ]/ p
如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
" p6 a) w( S- f( B# x" o# N0 G; Z . a( p1 c, a' D
file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
0 v2 g! f9 ^* s9 A2 F6 }# J: o3 ?
/ r' B; Z* s& [9 C7 J) W3 n 另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:4 v3 |& n7 G) _: C/ d
3 x& y5 w# C: `4 N, S8 {; n5 S1 V* c fstream file1("c:\\config.sys"); 特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。% G9 D+ W( M+ @5 h- |. U: n0 x
, J& I7 x/ M% B2 u7 M4 z/ j, i
ifstream file2("c:\\pdos.def");//以输入方式打开文件8 Z9 Y, X: y' x/ T# q d7 B
- }: k% c' s- [- ]
ofstream file3("c:\\x.123");//以输出方式打开文件 所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。 ]1 d6 r5 g! A/ c( w; A! H7 S) {5 ^
& ~$ N1 e' ^7 H8 B
二、关闭文件
1 v. E- e* }% W6 V- z4 ^. l) w
& R* {, l. `! A7 }% A" } 打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
$ L) W) Q; y! Y6 ^
3 S% q/ T3 k. I* C 三、读写文件9 A6 e9 I, G) L' d
/ D3 s1 S% T5 k: Q" p 读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
' b3 [- K! k L1 A+ s' h . s0 }* x3 l [* }% j
1、文本文件的读写) `$ Q; T n4 a, O3 P" \9 c. B4 Z
$ W5 e. V! N2 k5 V2 @2 ]+ ` 文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:2 C: o% g, g) K( M$ o: L
1 y, T* n+ J- M3 q3 s, b file2<<"I Love You";//向文件写入字符串"I Love You") T4 }9 d" g+ u# ]3 O
0 N, n5 W; t. \" _( r9 Z# ~ int i;, v3 o0 j8 T: R
7 @1 Y: Q2 x$ R" D: j
file1>>i;//从文件输入一个整数值。7 a P6 k: `# n% @! N
4 H2 |1 \7 n) I3 e9 H4 O% T
这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些& @3 c8 X; e) g& e
! {* m2 n; q5 n' d& S6 F
操纵符 功能 输入/输出4 Y Y6 n5 q- i& M. q4 Y2 Z9 T
* `* [( t" O# [% v5 @
dec 格式化为十进制数值数据 输入和输出
$ l' h) M3 h) J! x% w
/ L* b4 W/ t; _) j# b) m3 x endl 输出一个换行符并刷新此流 输出
. A0 i% t& Z* K! Y$ n; v 9 O: T! Y+ I7 \6 ^7 k$ v1 u
ends 输出一个空字符 输出
: U8 L5 A5 ~/ K# e( z0 ?. A" _3 U 3 e3 j8 g! Z3 C# z- e
hex 格式化为十六进制数值数据 输入和输出/ f3 O; y: R1 `! r& T
m; @( a& S Z- q
oct 格式化为八进制数值数据 输入和输出/ U0 A# S {7 H Y
2 ]5 z+ Z' Z) S" x
setpxecision(int p) 设置浮点数的精度位数 输出- _& o3 x% c: e
, |/ y4 J" q/ M, U
比如要把123当作十六进制输出:file1<
; t" J" I0 E5 X! L 2、二进制文件的读写) [# B: {& o7 [) g8 H! y
) Y: d/ V/ f# Z5 v1 t ①put()
# e( ^3 i" [8 P- _+ _5 j( U7 E % X( T8 Y4 d2 _% |* Z
put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
/ i: H2 I4 h/ Z# K5 b : |: ^; L6 v m
②get()" g; G9 S! i W% j. i
; b0 k) X( y7 P& X( a9 g6 y" H% x get()函数比较灵活,有3种常用的重载形式:
9 \9 e. p) K( f5 W1 T, E 0 |. v3 d# Y3 A, m" B
一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。5 `% u& I! F2 e5 r4 a7 O8 U, H# g
. W& k7 X0 f& `6 V6 i$ _
另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。; b6 O% ?4 y8 `% H
' t3 G' {6 H' B( \# J1 P+ d b 还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:8 r7 q! o- F0 ?5 A* b1 f* `
! u+ W' l- h y/ \+ {# N' H2 @ file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
# N" S% J/ c* B- [0 s: G; H% z
9 Z9 I& u' ?' j ③读写数据块
/ Q0 _0 Z& L8 { 9 v( h; M5 j* d) u! p
要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
5 }- O5 a1 W0 r 3 P) W$ t2 a7 H+ B
read(unsigned char *buf,int num);/ y% ?9 S7 n+ ]
P; d" q. Z: o write(const unsigned char *buf,int num);
7 V( q! U6 I# _: k * K3 b- D7 ^, K" i5 [0 q: Y
read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
. U, s1 X) t2 k: | / \ y# F7 B( |5 O* E
例:
) k5 r* G- R' p, V$ n0 ?, M
( t, v5 I6 h8 ]0 F- M% ~ unsigned char str1[]="I Love You";
+ P; J# V+ ~$ f9 _/ L
- V4 t) [; B" L& B int n[5];
7 d; d% p6 M7 A0 t+ N
+ U1 D. ], [9 U) h ifstream in("xxx.xxx");
2 | M- e8 X& _! c! {4 b
9 x, ^0 Q" B- k! |+ P; c ofstream out("yyy.yyy");
. N6 ?2 ?! x3 y2 \ 2 o9 { W. I# a. ^# g
out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
. i% N L3 N) z3 S# N 7 A/ q" E" z0 s$ F* l
in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
5 ^- J6 T- {$ z% A, [5 a5 d( N7 J
0 d8 |3 p; ?# B1 C4 y% y) h in.close();out.close(); 四、检测EOF
R% |0 L' q! h5 T! I7 p: K
3 {0 j; [; I/ L: }5 k/ ~: q 成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();- n$ t/ Q2 e$ q0 K% p2 Z K
5 b' f3 h) I% l' I- w/ Y& Y- |
例: if(in.eof()) ShowMessage("已经到达文件尾!");: l- _# p v) V; H! K
3 t! w1 Y2 X4 Y
五、文件定位- N) m, X- @" F2 D1 c9 V
$ O, h3 F# v/ ~, w+ G& J- a 和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
+ d6 z4 D, V, e [: Y' g
# C) b1 B2 _7 Q istream &seekg(streamoff offset,seek_dir origin);
7 p* Y7 w' n8 r. @# L( y# d% l
3 R1 T" f& H; O# \4 B f+ {, Q ostream &seekp(streamoff offset,seek_dir origin);
1 A/ M; P2 W' Y$ K4 k+ ~/ X n6 W& E 1 v. [5 D) U! }
streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:+ H) D, G7 t l
3 ?. S6 ?- o* ^# ~6 I ios::beg: 文件开头
' U$ W$ u" t/ j
D( T; A' t/ P0 \- A+ D) g( S ios::cur: 文件当前位置4 w+ d0 o) U+ L& u
3 d+ d6 L' G" Z6 Y: m9 o+ R
ios::end: 文件结尾
1 |8 r* ^3 B5 [" y1 h ]2 R0 k" @$ K( P
这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:! T" Y2 U4 Q! U7 d
; k' a7 n* ?* V
file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节, O; ?9 `2 L! E( B: Z9 |
, N; D. }* p: f% Z
file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
% H/ e" @: C% d, F4 P' Z/ q
1 N7 }7 t! G+ y- L |
|