PLM之家PLMHome-工业软件践行者

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

[复制链接]

2014-1-23 14:57:18 4489 0

2470

主题

1275

回帖

8万

积分

管理员

PLM之家站长

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

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;  A7 s  A6 n5 l
; @, M* S: I: H- P1 q3 G
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:; e) D) K8 v3 P" d; }
, f/ u5 x1 k6 A2 v. r6 G) M. @" k
  1、插入器(<<)
0 C+ q4 J# I% t( w
+ G2 |, B5 S; Z$ Z" Y' X! A  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。7 f6 R8 b1 q2 }1 n

& A. E+ T# U! t% m  2、析取器(>>)! q, ^5 S9 O8 U0 G2 m- R! y
6 s4 s2 O$ Y, n/ K
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。5 q) P. ^# ^# T, [! ?) z
9 Q- f0 v* j( q. h0 E
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
4 F8 t4 q- h9 {' ~ + F6 B$ ~. i' H4 {2 m2 V# _
  一、打开文件: ]  i2 u2 B; d- ^3 }$ l

6 A9 H) ~! l  M$ a. g  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:. G2 I# Q& ?+ B8 U

/ K: O* l2 o! \4 E& i/ y3 b  void open(const char* filename,int mode,int access);参数:6 s' K/ E: }& i1 T
9 w: [: s7 Z  I6 p! J
  filename:  要打开的文件名9 }9 D$ {, J9 K( [9 v1 D* `

( j* p0 y% s# Z7 w  mode:    要打开文件的方式9 s4 Q  S# `) x3 E: b

1 }7 Y, g5 M2 |/ @# H* e  |  access:   打开文件的属性
. Q/ e7 y& o% B4 q
3 Z3 E) q5 E# t# k, O0 [  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:6 y' J2 T! Z; E0 S% A2 u" x

- y& {1 }1 m0 @$ I7 a3 F" G4 Z  G: q  ios::app:   以追加的方式打开文件
* S  _' ^% ^- m ; c) y+ c. J( }. z- }
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
/ T( U7 s$ Y% O3 C
9 {+ z2 |) i7 a; N  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
. i8 Q# S# U- m! I. L1 c 5 n+ h5 l  }8 s+ y# b0 H
  ios::in:    文件以输入方式打开(文件数据输入到内存)1 v: R; J/ t  Y$ R& W% q1 c
# X/ G; U9 M! b1 j* ]3 @5 G
  ios::out:   文件以输出方式打开(内存数据输出到文件)
8 f5 h. y7 z7 J+ ~( t 1 ~4 a3 J1 `& y, m4 @4 v1 H- B
  ios::nocreate: 不建立文件,所以文件不存在时打开失败
% ?* p% }/ V7 f- g5 P3 j
2 H0 Y6 P; N1 l7 J6 c4 T  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
+ G- D5 O" [  s& \/ p) g 8 B: s$ N3 T& M6 P
  ios::trunc:  如果文件存在,把文件长度设为0
( t4 {1 }5 y  B0 S 3 b5 u0 |$ K! A) z" f9 O' g) L
  可以用“或”把以上属性连接起来,如ios::out|ios::binary3 ^- t- t, t: v; }

" `  s- Q3 n' c2 {  打开文件的属性取值是:
0 @% m6 D$ U( W, t # N$ a- f: d3 k3 W: M2 n7 O
  0:普通文件,打开访问
# y% R; f! @$ q 0 C/ j' w- e, v4 _
  1:只读文件
. k. y7 m1 @( G . P5 Q$ E7 V8 |  Y
  2:隐含文件
+ z2 r' i' c& _  B / o% s/ b2 M( H) X. Z
  4:系统文件% y7 a+ @& W# u1 u

# Z. t( P9 p( C- c  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
1 ~! x9 K6 Z% M1 G, b $ a) q- t3 q! e1 `" m: j. w
  例如:以二进制输入方式打开文件c:\config.sys6 a; l; k9 @. z6 y; m6 H
1 F0 ]" J& N$ r
  fstream file1;& }% B* K/ V: \; T5 Y8 Y

8 U: |/ S% i& Z4 @  file1.open("c:\\config.sys",ios::binary|ios::in,0);5 q& c" ^5 V2 I1 o0 n
1 N1 ^9 `" o, }+ A4 P* g
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:6 V4 l* Q) a7 Z0 O
' E; E2 k5 f2 b) }& T
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
$ e$ W1 z8 U! F. Q$ \8 Y 7 I- v  y% F/ s0 d3 U; k2 U
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
4 v( z3 n* G2 w: x6 b0 r2 w 8 }5 X6 n, V' I. d9 A# O! _/ X
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。; P9 p% ^" u" C

; V% u: M# A( S* q3 O% G3 |  ifstream file2("c:\\pdos.def");//以输入方式打开文件+ o% c* w% B1 p! W! t

* g; p9 ]! Z* o5 j( p3 X( S9 s  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
1 P. G7 g9 \, W( @4 {
8 G" L+ l% I* t/ n  二、关闭文件6 O" Q) B7 f& j5 i% r- n( q- B

% `3 l) x" U! F+ q5 T# J  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。) X9 b% w% u: S  h- N
5 ^3 Q. @" T3 d+ i( h8 b
  三、读写文件5 p6 @- n' f) }4 ?0 g& M
! P- Z9 |6 ~. D- K# y
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
$ j3 C5 _$ O2 _
. j- V9 N; n& d4 P7 A: w$ a  1、文本文件的读写! s. w, t, M: c( _& A$ F( y" j/ Q+ P8 D
: g' |# A( l! E4 G
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:0 l7 O7 G/ e  P* c& u9 w* c5 m1 }

3 S# z3 `2 {/ H3 v5 r0 h) u) |/ f4 U  file2<<"I Love You";//向文件写入字符串"I Love You"' _% x5 r3 p9 I- T( l, V7 ^/ a( R
4 A( Q) m5 M6 [3 q# p+ D; M- |$ N
  int i;
2 ]4 q5 |; N& ~8 D. { " ?$ n# k# A: U2 {/ f
  file1>>i;//从文件输入一个整数值。
" l" V+ Q7 t8 N4 U # G8 D: Q4 z9 A+ N- ~: W) e+ `1 ^
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
6 ^4 C* ^- {+ Y$ G6 ? - t0 T5 R. @% c4 x: h
  操纵符 功能 输入/输出: g) r8 j' z  G. e

" H8 H9 C5 ?* ], H' I$ w; I# @  m( A  dec 格式化为十进制数值数据 输入和输出
, L7 E0 k4 {1 t: j1 z4 V# e
. H% ]8 W1 R  q/ J3 S  endl 输出一个换行符并刷新此流 输出& v- Q3 y  o* @6 V

3 j: g, R" e4 n: H( v  ends 输出一个空字符 输出
5 K* ~' Q' P  o3 U% Y* {2 G
! X& c# ?) N. o% [# ^  hex 格式化为十六进制数值数据 输入和输出# T) Z$ ^8 ?( I+ D4 S0 A4 Z

# ]5 O  U4 w8 j: n  oct 格式化为八进制数值数据 输入和输出
1 A/ h4 E4 X) Z' Y+ W 0 ]# _" L9 _1 |5 B/ R
  setpxecision(int p) 设置浮点数的精度位数 输出9 S7 M3 v: |( u1 H1 C" X8 W! b  z
: D$ [! V  g9 N( n/ K' `8 ~
  比如要把123当作十六进制输出:file1<

9 |# `! }" k' ^2 m8 I2 R  2、二进制文件的读写
2 E8 o" N; H- T: N, [  I! c : r, u* J% S$ T5 `' j
  ①put()  r- _8 ^/ F) N- |+ K$ p
5 O. W! C9 g* i6 |# I) l! g
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
7 t; c; E, P$ _ ) m; h9 @: S6 P$ q6 j$ c; ]8 ~* _
  ②get()  p: J( l6 S0 X. d% p

& P8 y& _9 T  P% Q! {0 O  get()函数比较灵活,有3种常用的重载形式:
% `2 C8 y5 y7 M! j: t1 w9 K' n
2 G8 j; q) A" k$ p% M$ |  f% }  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。  Y" F% s  r, t& u+ q
8 A1 X' K9 U& H. Q. f* h3 H7 l9 c/ `* \2 ]  M
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。8 H. _: ^* E: R6 u) Z  f! w* |

* c# q! ^; N) n  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
0 n1 k, ?; \9 b% f2 a/ J# v & n' n2 _+ E0 m1 l+ p9 Q
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
. j3 M2 d# U2 V, e# o 4 t% Z3 Z8 r$ E* P: M* j2 H7 m
  ③读写数据块
9 N5 d! f/ L- f( v2 j& S
. @7 H% c6 b' s! |/ g  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:8 q+ L. S: F8 I3 x  g

$ _6 X. V8 ]4 M8 S  A- |  read(unsigned char *buf,int num);
# k# i, ^* S. G
+ Q4 I9 t6 I1 \  x  p  write(const unsigned char *buf,int num);
% `. a5 k( R" b
) ^5 G( A3 j$ q4 O  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
, }  }  Y; r+ e4 D8 C & v: Z* _/ l  D' U, @* s. t, q
  例:. Q/ ?4 ?, |0 ~$ T3 D; V
* M% X0 t9 b/ `
  unsigned char str1[]="I Love You";* X) H) }2 ?5 ]% H  ?9 Y  \# P& G& J
- X. j7 U- h$ l0 d
  int n[5];7 x( o/ F% T$ i2 t* }1 [& g

5 G+ p) Y, R& }  ifstream in("xxx.xxx");; a7 D1 z: B" D/ r# {+ [0 `7 H( @
) o; z: I/ B( k5 D) K, d1 R
  ofstream out("yyy.yyy");
- C6 A4 M8 U2 U: n+ Y  x. |
* L# x( e* I: I! y4 C4 V7 x1 I  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中0 J( z3 w$ K) J7 \
, M; |+ p: j7 E) }+ w# o
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换% w3 G7 r- r, _3 I  C+ e" U

3 a  u; ]* k, I9 j5 k2 t  in.close();out.close(); 四、检测EOF
7 e0 O$ [7 N- l. I# ?! z" [: d
$ U+ ]! C; m) C* B! \# j  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();. ^( G  X, B/ I
+ _. E7 L- K) Z1 N* {+ ~
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
9 w# k$ m( u1 z6 f* a* I* z5 @ 5 m! A- k# j5 L7 T3 P& d+ z3 \/ J
  五、文件定位
$ X0 V: @, i% T% i# |$ J
3 l8 Y' h" p5 l* E5 A  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
/ {3 A. _- Z) H7 n 7 S1 W# `' w5 n$ d+ s
  istream &seekg(streamoff offset,seek_dir origin);: z) l- r/ t' G6 K/ \1 _
$ I( P" W: M2 D
  ostream &seekp(streamoff offset,seek_dir origin);
" S9 h* k3 c2 b$ O: t  m6 Z
$ k) i% q  @$ `$ n  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:% S" z0 |* k. k. w  S1 V0 d9 y

( k: m$ m) {+ Y8 K/ S+ ~  ios::beg:  文件开头
- w* ^: L" \, @: v+ r
) V. B6 V" {4 Q) w6 Y  G  ios::cur:  文件当前位置5 l- D) ^# l9 u5 Y& x  r
+ O5 C) o6 ?% Q3 Y: d) w
  ios::end:  文件结尾) I7 O8 B/ y- X( m7 T( ?* D
! d) e0 V4 p, `0 C5 _; N: H
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
: X5 C. Z) U+ @9 |$ D6 C
3 t' K/ C! y& k1 w, L! d+ D0 H  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节3 H6 X1 R  w: |1 \) i+ `& S6 g
9 x0 }3 S3 E5 |' o+ |( ]% a0 ^3 g& L- P
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
5 w1 w, y$ v6 D* P7 @

6 p1 n$ y- \# x5 b
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 doTeam.tech
回复

使用道具 举报

发表回复

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

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

    本网站(plmhome.com)为PLM之家工业软件学习官网站

    展示的视频材料全部免费,需要高清和特殊技术支持请联系 QQ: 939801026

    PLM之家NX CAM二次开发专题模块培训报名开始啦

    我知道了