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

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

[复制链接]

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

admin 发表于 2014-1-23 14:57:18 |阅读模式

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;: H! P( c# K: g8 A. \

, W9 H2 `& R  `0 f$ X" [  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
" B# h+ F+ y* G 0 E( p  G0 d- x
  1、插入器(<<)
6 P6 x, ~8 x% K0 `3 `
8 s6 d( J' r$ ]; c' R) w  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。$ ?# c# ^+ ^8 K2 n! {
+ z& J2 h+ c0 J# q9 V. E, H
  2、析取器(>>)+ g0 W, c9 q, s0 |1 v2 L4 B9 @

. T! R7 M7 S" K' j0 }' [/ M  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。3 V( `) @4 }4 O( C% L& {
, w. f4 A, q% a: {3 L3 C- Q
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
& D7 j6 ~, n& n4 @8 b / e# K  ^! Z: `2 ]
  一、打开文件
) Z4 A- @5 H7 B& L- k
7 i  c: p5 }5 a/ }  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:- E& n# G8 R* \& d. v3 T& I1 y

) R1 D6 {3 I- H5 b% K: s  void open(const char* filename,int mode,int access);参数:
4 _' F7 n% @% N8 c5 W$ I1 N# t8 `
1 O7 L3 Z4 y8 {- H' N  filename:  要打开的文件名( R" X! u! _. k4 [2 \5 C- Y
. X/ a* ]* |& F$ b
  mode:    要打开文件的方式' `0 @# Q2 ^* I" R7 C
7 `! f9 A& U7 ~( q0 [
  access:   打开文件的属性' V8 e" m) W; }8 h! c( P
9 i. o) h- ^% B8 b
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:
5 Z/ z, c% r0 N. @& d& J$ U" n
5 z9 o6 _' x5 j; Y0 W# {  ios::app:   以追加的方式打开文件
4 w6 v: m1 I9 i6 }& i
8 T' E8 `. i# N& t/ a( t  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性- t3 N' z  \# w, ~
: X3 m* R- o  T) E: [: ?, D8 T
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文: ~3 I" g( ~/ @- ]5 y
9 L; M8 D6 d( a1 T* y2 }$ w6 J/ ]
  ios::in:    文件以输入方式打开(文件数据输入到内存). @" d7 I, G% ]: s* s; m

' e6 F; x: U/ z6 L  ios::out:   文件以输出方式打开(内存数据输出到文件)
: |/ [& G8 e# A* b+ C / m" X3 X! I( ^
  ios::nocreate: 不建立文件,所以文件不存在时打开失败$ e, g/ [: G+ u7 M
1 h$ S" Z9 ?/ K. U  ~7 b
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
5 r3 w4 m( Z4 M% r" ^" P* ~% V! { * V3 K& k% _( a2 i0 q6 h# c/ d
  ios::trunc:  如果文件存在,把文件长度设为0
% K3 e3 }# }5 m5 K' B: x% j
5 [3 ~: Y; E% N+ U  可以用“或”把以上属性连接起来,如ios::out|ios::binary
: ]5 x. M" e4 Z% x  t
7 @1 F! S2 Y% {. |: Y8 K  打开文件的属性取值是:
; ^1 W4 ~# K& ] ; }; p3 X' d: r
  0:普通文件,打开访问
( J3 T9 C" a0 a0 b  F3 T9 Q6 M : d& i6 J- n2 }! K0 y
  1:只读文件* B4 g* S) X( V. h  C2 p1 @

6 U9 d) \' {4 {6 s  2:隐含文件
: g, T" Y; r: F8 q& e7 G$ s7 a
- s/ B6 H; W. F4 `  4:系统文件0 ?3 P/ V6 Z2 t  }7 K
) @: z+ K5 D& ~
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
2 Q. Z# U# Y2 ]6 [6 e  P
( `7 J3 c: J: ?8 ~" H  例如:以二进制输入方式打开文件c:\config.sys1 p( K1 J+ n  q0 p: l; h
, U' b5 L4 o7 t. b' W
  fstream file1;
6 I1 U7 R2 Z/ C
. f+ p. n; I8 A9 A$ e0 U  i( E  file1.open("c:\\config.sys",ios::binary|ios::in,0);. n/ E5 L/ U" |5 z

2 s+ v1 M% b) I+ x* J2 W  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
1 }  Z; E% G' r8 k/ o: Z
  n5 T8 k; @* ]) o8 A7 m* V  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);, R8 i/ l# w) s8 W

! j/ D8 e: I+ D$ c9 _  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
2 ^  }! Y- h* ?) m$ ]" @6 k
/ X/ X/ ^) y% h  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。! O" b0 V% L% B5 ]0 y" k) w
" x9 A5 s7 W9 I. K
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
! I- D1 J7 O6 X2 N* E$ Z' D
1 n9 N1 F  v9 R0 `  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。& c' x0 s2 l7 t! D8 [, g  t8 t2 L

) o: Q& f! G/ [: g: p  二、关闭文件
: E: ~! a, J4 P
$ d3 r, c: ~: A+ N6 Y. _, {  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
( x8 W  I' d( o/ H; ]- B
  R% @* Q- `  ]% [/ z- l6 d& f' z. z  三、读写文件- F. g7 L' c8 J: L  F3 |6 b
; ?: O6 ~2 d  @% J" R+ ?* Z
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式% D0 `7 _9 Q& Z2 o9 q' A

- b/ Z8 d2 |: z6 m9 c! ?  1、文本文件的读写) g7 W% r: Y5 N& ~) I) l$ `
- ?1 z$ z3 v9 p- W
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:/ _% s. {2 B- \, D8 N- {/ |
1 u( ]% F$ F; |& C4 f4 D9 ?/ B
  file2<<"I Love You";//向文件写入字符串"I Love You"
& ^1 O$ y& V( B: p; L( T
0 C( `) i5 p$ ?/ V  int i;- A  K% j1 t5 l! \7 \* w
8 l( K+ {; q7 a1 I% a# x! T
  file1>>i;//从文件输入一个整数值。
, G3 J, e' p8 n5 g( y& V
/ E2 ]8 b7 {, C/ z4 j  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
, s* _  e( P! V& z+ G+ a
% v- H, m& i6 f  操纵符 功能 输入/输出) o" ]* n/ @7 y  z( h/ f/ ]" j- G
2 y1 M& v' F. A7 B
  dec 格式化为十进制数值数据 输入和输出/ {9 ?4 P) s: O$ U* ^# r6 K+ r5 U$ f

& e' g* X/ I# o. b* X  endl 输出一个换行符并刷新此流 输出
! K7 f# j6 O+ F2 y7 T 5 F2 e+ l4 h2 c( {5 P3 V& K
  ends 输出一个空字符 输出8 e6 T, i- y7 ?) L' ?% N
2 D+ \! f% ~7 t) d/ \$ V( \
  hex 格式化为十六进制数值数据 输入和输出/ d  l. c  L+ j# N

( R& f/ i" k  o/ h+ a  z1 H- J  oct 格式化为八进制数值数据 输入和输出" y* C1 W- @0 T" y3 l
; F  `9 a+ j7 ?- [7 `
  setpxecision(int p) 设置浮点数的精度位数 输出& _1 X+ p+ f% }4 t: b4 `

( n) S0 F9 G. W! Q  比如要把123当作十六进制输出:file1<
+ ]" C4 @" P9 Z3 f4 E
  2、二进制文件的读写3 ~9 J: g/ J6 j  _0 l: X
* R  h/ O$ S* h" x. v, g
  ①put(). V  i; p" Z+ n( K! C
% M% U. u' i. W. w8 d' n" B. m: X
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。* \* U3 y  G- a- U! B
/ b" M& N( W2 n2 ]4 z; L& a/ V; p
  ②get()
4 K# \( @, X$ `+ I7 J 7 {5 Y2 F6 a; v) @" e
  get()函数比较灵活,有3种常用的重载形式:
: L% m  U6 \5 b5 L
8 K% U  v9 z# M' @4 p# e. J/ x' O  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。* r. M9 f9 F  l+ j1 @0 M# D
  t( Q4 Z- ~$ A, [; J
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。8 D5 Z# I# o' c$ @" Z

3 u$ H6 u, w" W/ z. W' \" k  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:' q, j8 f" t6 x4 Z3 }+ e4 L

! y6 b0 A: H& f7 W% Y  j  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
" q- m6 }6 t& J& \, x; c5 r
% s. }, {6 y2 G  ③读写数据块
; C3 ]) @" V+ j0 d0 m: E; o 1 ~% a3 t- Y& u$ \0 n  E
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
7 e/ d/ [) n& M" h8 X
* j' ^; b7 N" y$ V4 j5 v8 l  read(unsigned char *buf,int num);
! ^; O4 ~5 q9 U- x2 u" V 5 N% x$ I# \( d6 L# I1 G3 a
  write(const unsigned char *buf,int num);4 A# P, x3 [- ?. b0 c

  l( H, n6 |- @: H  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。- v6 }2 o9 s& @  V2 \/ a9 |
. v. }; h. f% b! N7 n
  例:6 h4 ?( F' ~! q3 ~; d
# k2 a! D+ A: |9 k) P# O) k
  unsigned char str1[]="I Love You";
8 n4 D& j$ X, I) Z- x8 ~( M 2 V" z& c2 f" K/ [- O1 c+ v
  int n[5];' x% c1 Q8 {- i6 {

; e2 {- _9 S9 s2 z4 ?  ifstream in("xxx.xxx");% N2 h0 m$ E' T( P+ K: f

  e. y; ~" \8 @: p% _6 D  ofstream out("yyy.yyy");, ~. _! T! a& [0 k0 l3 K% F) Q0 U( v

; q1 N6 P" s. p0 z* F! Y; i  P6 o  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中7 L# g) Y/ v: c$ m. L$ I( |$ h! w; F
; g7 U* B1 P7 p, s. ?% d
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换! X5 j; y# S$ H
8 j( f1 f& j1 z, |
  in.close();out.close(); 四、检测EOF3 F" x! e5 n) T8 V1 _# z

+ y' j2 {# s3 V2 s  ]8 k  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();  }7 ]0 A9 R) w! i) I

6 A, f0 U: z: R$ v: z: Q  例:  if(in.eof()) ShowMessage("已经到达文件尾!");8 n3 c' A0 P' c5 {- \

6 X3 e( q8 e% b- v; b9 a' a1 b" m  五、文件定位9 u0 r, J% F* z

' V- X5 P' a7 A* X; a+ B  W' }- Z  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
; a5 d4 o. L/ S/ G6 {0 h# ?. j7 I: x
5 M1 r3 A/ S. p" `* D# U0 d  istream &seekg(streamoff offset,seek_dir origin);- l4 ~7 r: D1 ]/ j8 j( W5 p1 c
6 t' o" R" C7 I3 {& @, Z
  ostream &seekp(streamoff offset,seek_dir origin);
; m4 r6 q; K7 l/ g8 ^
/ }' E8 I- w  V: Z) k1 j  `% K2 S  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
# ~' t5 D, w) Y; E ; \7 c/ C+ k0 t# ]& `5 I% c
  ios::beg:  文件开头( Y$ a$ Z$ A5 x& J$ ~1 |" h$ ^
& l3 Y# Y6 d7 ]
  ios::cur:  文件当前位置8 X. g/ b/ J. p* t
) D! o2 O2 [4 D# D9 n# ?! R7 C
  ios::end:  文件结尾
0 k+ ]2 A# R' c. {& a5 ^ 9 @- X' B; v8 v& G
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:  f% F6 @5 E8 z0 P6 t

8 O$ I% R" C6 y1 a6 }" \  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
& M- Y! v: ~7 F' ^' b) {4 d4 h# u
, Y5 x1 Y1 q- t$ C- D2 I& E2 j# [! v  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
7 S  L: a$ w8 G0 m- Q  a/ O4 W

- d- `; h+ Q, P
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了