查看: 4590|回复: 0

[转载电子书] ifstream 和 ofstream的用法详细介绍

[复制链接]

4

主题

3

回帖

38

积分

管理员

积分
38
发表于 2014-1-23 14:57:18 | 显示全部楼层 |阅读模式

请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!

您需要 登录 才可以下载或查看,没有账号?注册

×
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
) K: \! e/ \# j% p$ |- i
- Z. K% ^, o- V4 r% p. @  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
0 P! V" n! b: Y : A$ i: [6 l$ J7 W. V) c, g
  1、插入器(<<)
: J4 k6 G0 i; D" Y 9 C) |$ x5 E+ @% B
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
, W7 Z3 Z+ W' K6 }" b' l
+ J% H7 O( |7 _/ w& h3 }  2、析取器(>>)4 X; x+ n# F! _- d* ^( @
" N6 R% V; U' \, e5 M
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
/ A2 K9 W/ ]2 a# w+ }/ f# X . Z; c" v7 x  l
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
- X$ g" E" O1 V( }& ^$ V % w8 M  |. w9 g4 H
  一、打开文件
: A3 K, v2 P$ r# C. e ; U! m! y, O! f: t) [& J! p. A& ^
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:2 a8 z! P& X  f( w/ W3 d: S6 Q

3 b1 j; P$ M% g: I* U  void open(const char* filename,int mode,int access);参数:
8 f* P3 c: [) ]  _9 i ! u) s3 O% z( T8 B
  filename:  要打开的文件名) v4 T5 C% j" N7 f; O
; \# b. \; u' k5 V% N* y6 }7 S& o
  mode:    要打开文件的方式+ Q% ]/ l* s& o8 _! N
/ E/ K4 A1 z5 Y- I) R! ?/ ~
  access:   打开文件的属性
' D) D  V' Z' L. k
8 \: i- `8 u$ u& {  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:
( Z6 v( D" j# u4 y) N) H6 d 9 W0 [) l6 l4 E/ T' ^9 K/ |
  ios::app:   以追加的方式打开文件, T; K/ {& G9 o+ T2 v% P$ S* J. ?: Z/ Y

! {3 {5 |+ Z4 m, o9 f9 ]+ Z: W: W  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性- C. w8 C& Y* ~

+ V& d2 y; y# f7 ]# A) S: v9 m  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文, o, |5 u& P. W  H, w
: o6 Y$ e+ P( i0 Z; g
  ios::in:    文件以输入方式打开(文件数据输入到内存)* D8 i8 \# s( ?
: _. R+ ?: x' M3 b; a' W
  ios::out:   文件以输出方式打开(内存数据输出到文件)
5 U9 C4 K0 Q% u- K* {$ l0 ^
; m6 Q, V' `6 j) ~# w! T; B1 p$ ^6 {; Q  ios::nocreate: 不建立文件,所以文件不存在时打开失败3 E8 ^- M0 \+ u

9 _) N7 [  H" Y: @  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败) d4 g2 M7 ^: h' |1 c: a
/ d/ r2 \( H" H2 I( o( n8 l: _
  ios::trunc:  如果文件存在,把文件长度设为0
2 P! `2 t- r1 i# @$ T7 e; f
6 A( x2 \* m2 P$ x& B2 x1 G  可以用“或”把以上属性连接起来,如ios::out|ios::binary3 m; y* U& O4 |
8 y9 c' Y  p' x4 @; @4 p) D% m
  打开文件的属性取值是:
) k8 b% f) u6 C( g . J+ m2 i$ `! M
  0:普通文件,打开访问
* n$ Y/ z3 q8 v# O1 n - ~: G) A% ^0 _8 i3 \8 o
  1:只读文件
! m( k0 O, F8 F% I7 }# Z
( w* A7 D5 ^; |$ x6 V5 O2 T  2:隐含文件
3 e4 y5 ?2 d& A# e: ^- U
# q6 ^# Y7 e3 Y, _. i  4:系统文件, z& e+ C; a5 l$ b4 \$ I
  t  H! v0 J7 o# T+ |$ J
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
! R# ^' k" u8 k2 D  G
- F" _; M0 @+ q6 Y! v0 }# J' w$ U  例如:以二进制输入方式打开文件c:\config.sys7 I' b/ n* l8 c# a
. X" s# b5 Y/ h) ^+ b6 z7 F0 b, j' n
  fstream file1;
6 @$ o  m+ C7 |: F1 D
% p/ E, \9 z! c6 s, o  file1.open("c:\\config.sys",ios::binary|ios::in,0);
/ O+ Q; H% W: @3 b9 O8 K' p 2 K* u* t$ V2 e8 W4 m7 u' t7 w! F
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
7 Y, Z) T/ D9 K3 D4 b1 _
* @& n9 z: C5 n9 w& l' I. c0 x  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
$ m0 ]+ I" x5 `. z( X
" `9 D# l! U( [! G0 C  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
4 p' R8 B7 q& @# Y/ X 6 z; {1 w$ w2 D3 {4 {
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。" t" z( ]4 l, E

. G0 q  Z' V. I8 _  ifstream file2("c:\\pdos.def");//以输入方式打开文件/ [/ s8 H$ z: {

: r* J; p/ m- d  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。, i7 g  J0 z; E6 Z* ^

6 Z9 V4 D& b/ E- _( s: d3 n  二、关闭文件
! B1 n5 _% |0 p) {& r* K+ b
& |: O5 V6 ]1 u& Q& e0 H+ Y( u  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
+ P# d4 g& f: J) k
; t& ?+ m: E" C9 a  三、读写文件4 V9 b; r3 a9 ]  P! k

' t' ~0 W$ u( J% o, d  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式, J. R8 e5 s+ P1 K+ A5 t$ {! |+ x

) h1 y) \( @6 p: S9 _: P7 r  1、文本文件的读写
; U0 ?7 o9 k$ u7 |: k& N; o
# g% C" b/ X" Q0 |  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
6 y) i, p  Q3 g: X 9 s' \# n) L$ q7 `: Q5 {+ T
  file2<<"I Love You";//向文件写入字符串"I Love You"
/ R% y5 A7 }) ` ; b' x1 Q! q- ~
  int i;$ E! `& c5 \5 {$ w4 F

- t0 K6 g+ e% A" \0 P" H  file1>>i;//从文件输入一个整数值。
3 m5 _) A9 U. e, r% T$ K* D
: d8 R: ?+ }. c) L" k3 V  m* H  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
7 ^! R# k' ~) x+ i) ^/ `
: h6 ^4 i! h1 F. s9 o; I" h( g1 G  操纵符 功能 输入/输出0 U' h6 F0 k8 v5 M1 u: S, S

% @& q5 {( n, E  c6 T! n% {  dec 格式化为十进制数值数据 输入和输出- y: D4 l1 o4 A: z3 \' d

! _9 X( }* J- E$ s( [- d; ?5 ]  endl 输出一个换行符并刷新此流 输出
. i5 A" ?! E4 e- q * s% Z, d( }+ P; t( ]! y2 t) o4 F
  ends 输出一个空字符 输出
3 P" o2 b, j9 U1 e" A 3 h2 b- T0 l1 w- c% |2 d4 `5 c9 i
  hex 格式化为十六进制数值数据 输入和输出
* A; n& @. s2 f3 d, I 4 j- S, q% [3 }! o  L+ a" \
  oct 格式化为八进制数值数据 输入和输出
9 A4 }8 e; J8 V/ P7 B 8 ~  r; ?( G  l0 X# V
  setpxecision(int p) 设置浮点数的精度位数 输出
. p4 a; j4 W; V, ?0 ] 7 A' h3 i; w5 t& r$ d* s
  比如要把123当作十六进制输出:file1<
! e# _3 [3 y- a# j
  2、二进制文件的读写
8 t- R- D: L$ t) l
! @% y" j5 X3 R  ①put()- R1 F4 R: J. X! Z

8 Z' w4 C) P+ f, t5 }, f, z3 T: M  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
/ Q1 d+ s2 ?" K' f( h . p# J: x/ Q( K$ K2 ^# j) B. F
  ②get()
6 q+ a( L0 h# F5 ` . n" G! J( H. |) M3 A" s
  get()函数比较灵活,有3种常用的重载形式:" C& i/ G  D! v8 A& K4 n

1 u" y8 ^* c& d" E9 y3 J  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。: U2 x' v" Z* I/ C+ y0 o# g

( D* n+ B- F9 w/ _6 t( U  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。/ N' O2 o! _: G; g1 G4 Q

$ I/ Q8 S# S" S$ z  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:% I( f2 l/ f) A8 ?5 `

0 g+ f  B  h+ f* j( ^9 p5 d  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。0 c$ b# \0 J0 s' N( d1 y" `7 {
# A( y- }. f  v# V
  ③读写数据块
; k! c3 U5 a; |
/ r& v5 ~& @6 Q1 @$ r) W  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
; b2 g& @" ^5 z! t   K; V2 ^- U4 f: `/ h' T6 Q
  read(unsigned char *buf,int num);
& N' I% k9 j: ~
( L' i/ k2 W% S; b% ?0 R  write(const unsigned char *buf,int num);5 e" d* h0 `4 L, x
  s6 ^% Z2 j. I; u! z% r
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
" _: |2 K4 Y) v% Y ) A! o( R7 s" [' M( g' _
  例:* J0 J+ A# D3 m, j, O

6 `5 {( _8 @! j' A  unsigned char str1[]="I Love You";$ G: [0 R4 ]; e' _( @: y/ |
. k6 v  i6 C- W: \
  int n[5];
  {3 b7 a% }% ~' ^4 R& R ( h0 \( i) S- J) j# `. T
  ifstream in("xxx.xxx");, }) K" u4 ?& R$ ]6 F- L6 M

& v- V/ K- U) d; u9 z  ofstream out("yyy.yyy");$ z) v' o' I7 X; @4 _4 x
  y6 L5 k; v6 V5 M8 t
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中  |% c2 d/ v1 Y0 {* I

! R  I* a6 ~. S: S4 I8 l" T' q  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换% r5 b4 A) P/ J0 M5 r, z! D
8 b; e2 J( U! H! K; u% f
  in.close();out.close(); 四、检测EOF
9 ?4 l7 m& @. u% o: M3 x4 M
& ~4 w4 Z1 x: Y* o  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
3 l% U+ M- `( L) p2 B& Z! A ' g  u/ N/ d  R6 i. K& ^
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");; G: @0 O  H  m5 Z# w; K/ i, T

* A" ^; r3 l( P  {* `" O! b  五、文件定位
& W; [6 a" F0 l3 c 9 q0 G- @" @+ |
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:- J  j( p1 P5 P, Z2 z/ H! P& X) k

5 P& ~9 U; v. Z+ d! P5 g  istream &seekg(streamoff offset,seek_dir origin);
* i; @& l$ a  p, ~1 O
$ o' U# M" W+ g. s" Q% y  ostream &seekp(streamoff offset,seek_dir origin);4 C/ V7 I) Z3 X
4 e/ u6 [6 m6 q8 h( d3 A
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:: d6 @/ f: R, c. }5 C
' U7 m, E3 Q& F" c) A
  ios::beg:  文件开头; H/ M/ P2 @7 A$ Q( m) V9 s

2 ^3 ^9 A8 k" E% Q' Y  ios::cur:  文件当前位置
- t; v9 h* Q! b
; g% `  Y. \# a9 m" }: Q  ios::end:  文件结尾
: j5 q/ X( x% P5 u* O3 C
$ \, Z+ {) T9 P, e  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:% b1 p  ]& ]7 L( S( |$ N9 `
) U  j' U5 b1 X- b& u
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
+ V$ J! l4 J) {9 C# ]8 D" j
' P2 w: f! R  D/ S  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
9 Z/ Z; J. H! K' ~, e

9 K8 D8 a1 K$ v6 s
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.doteam.tech
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

在本版发帖
关注公众号
QQ客服返回顶部