PLM之家PLMHome-国产软件践行者

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
" C6 U9 ?' Z2 R; V
% m" K( B2 E/ f% E  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
1 o' E  B5 p5 _ ! V3 l1 ]: o. l. v* B
  1、插入器(<<)3 }/ x+ M8 h# H8 r1 U2 ]

8 U8 f6 z* k: g. Z  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
( m4 f! O7 K' H& K1 s& q$ s2 L " L3 Z: m! b0 @8 z6 h
  2、析取器(>>), f& ]' J; N/ _# p
. }% u) V8 `+ w' u& e
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
! V- T3 _. d0 R8 |' o+ ~ . _' J: A! V1 `; |" @1 s8 F+ s
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
, O* T+ w! `. d" p
& o, [* p) y8 X: r0 n1 a6 {: C+ G  一、打开文件5 g( z0 G" v( r  t  Q" H4 D: n( r
) D: D; `! j) h* R5 \
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:" S1 C1 E7 W5 ^' E  v

) d* D$ L) {& X9 \! ~9 ^# Q- k! S4 e  void open(const char* filename,int mode,int access);参数:% `/ N" w8 p# s  z0 \& Q: R* ~: d

: }# r% a. J0 c, S4 H( Q  filename:  要打开的文件名
+ a% A! X/ J9 T8 N6 V7 X# K9 D " `% v& c) ^, m, B  M' u
  mode:    要打开文件的方式6 l' f) d1 Z' _5 D

) t- J7 f" \8 }% z8 P9 e  access:   打开文件的属性
6 f1 ~7 D/ _! O; i1 _' t # x$ G+ V+ s1 L8 o" p" z, B4 y  X
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:  ]/ K7 \& x! Q
, r! X- _+ I  P: `: E
  ios::app:   以追加的方式打开文件+ {6 |; }* A# Y( {  }/ w1 |
2 U! ^+ S0 c# h( X* l. a: ^
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性8 T; ~9 W3 D: y) r1 F+ B% J

% y# i; _, [  X" j. u# t, Y$ D3 J  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
9 R# @# l/ I) e1 F5 R0 J0 }7 L ' d0 T7 W8 q2 @# Y: W6 R/ G
  ios::in:    文件以输入方式打开(文件数据输入到内存)
6 z8 [' V2 q, d9 s) j! l
& _  ]/ s0 ^# |6 x' X+ m  ios::out:   文件以输出方式打开(内存数据输出到文件)
, {. |. M& |2 e0 K! N8 n5 d
, J- i" C+ ^! m/ b" d- V* S8 L  ios::nocreate: 不建立文件,所以文件不存在时打开失败
- C' z5 N( D% n$ F( Q1 M& q9 Z : |3 d# E/ t+ Q
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败$ T! R# r2 g& R6 B! w* E: P
- ]  l5 t% l; [2 u# l
  ios::trunc:  如果文件存在,把文件长度设为0* B+ C7 s6 P7 ^7 x  _
8 q9 A' X8 B  R+ K2 ]
  可以用“或”把以上属性连接起来,如ios::out|ios::binary
: P, V1 o  {; [  u# E 8 i- G7 J; {! d: E0 v, ?* u" A
  打开文件的属性取值是:3 C4 E+ H" R0 E; E

5 R* V* R: \2 _% \: U  0:普通文件,打开访问/ F: y& z2 ?) \3 P+ o/ y
( t+ b% {! R1 u- L' z
  1:只读文件$ {# x0 l+ M& Z9 W4 J+ X( `7 s' _

* F2 B' b6 r* z$ |" B  2:隐含文件8 L3 ]0 V2 \# o7 D$ K6 d6 i

  Z) I5 D% m7 E) Q: C, F6 L  4:系统文件9 S- Q" v$ A: l- t" @6 r
; b( S9 ?8 W% z
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。  ?9 \& g3 S( _: R2 t
- z3 K# Q: t- {' u* M  l& W2 Z  z0 Q
  例如:以二进制输入方式打开文件c:\config.sys. w8 r6 \7 }# K1 ?
0 f8 [3 S& Q" w
  fstream file1;" `6 a% t, B0 c' Z$ C, f
' Z; z( P# N* p( g
  file1.open("c:\\config.sys",ios::binary|ios::in,0);
1 S3 b: V7 U5 u# R
* n3 ^% }+ N7 V  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
& s2 X2 x' A% Y$ z" ~
' J: ]; M2 ~4 i  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
* o* U' ~  O. S
% ^" J' `& G/ e# G7 `  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
% [+ p5 Q2 \; w3 p, S7 E ' w) K  |: |; G) M
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。2 x! g- b) W+ A' t& N" h

. I" }! e0 A, B' P, x& [  ifstream file2("c:\\pdos.def");//以输入方式打开文件
+ d# K& c6 e; ^) f5 W
% t) r& b: p% l7 ]/ ~  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。4 F4 _- u) e4 O- Q. }" m9 j) d4 n4 t

/ _  {- w7 O' L+ x2 J! e) X  二、关闭文件
, @/ [7 y) v% c9 F, I
+ ^$ l% Z/ x0 B# @  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。) A. ^0 q- S/ E& P4 c% C

- L7 Q! A  ?/ H4 }  三、读写文件0 K/ l6 K9 \" d( {7 o& r& Q+ d# Y
; s  i. I; @3 j; N4 \
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式: f, u3 n: h8 m4 ?, y1 P
! y. `; R5 s% y0 |; w* n
  1、文本文件的读写2 k2 _' `- q' z2 W6 t
% T1 ?2 H2 |- W  v* {( V7 c
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:: Z4 n7 ]7 |0 [

5 k5 `1 w7 R& d" T/ i! ~3 L  file2<<"I Love You";//向文件写入字符串"I Love You"
% N- _' v* I$ U7 e
# W" Z0 D' N8 C  int i;% |3 o1 z, G( x/ B; c/ @, P
2 I7 F: L! s. o. `  u
  file1>>i;//从文件输入一个整数值。
) q2 K6 m* a  |! h! q , ?8 j9 z+ k9 F- S9 d
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些' g" r" \2 N7 x5 w, W, Y( F2 S
4 {( O7 f. e/ o
  操纵符 功能 输入/输出8 T8 d& R# |/ ?9 h
. x* X/ g% t+ i) t
  dec 格式化为十进制数值数据 输入和输出
# W  J. k+ x: v9 i   ~3 h/ Q4 Z! n6 u4 b6 B
  endl 输出一个换行符并刷新此流 输出
; ~7 \5 j5 r! l& | 1 p) s, {. \* N9 ?
  ends 输出一个空字符 输出
  I  x* i- W  z- ^8 m' A( g . Z. M3 M( J4 n4 v0 g1 V
  hex 格式化为十六进制数值数据 输入和输出
7 F0 d8 I0 Y$ v" [' _
+ S0 o- s, d3 n; p; a# \9 U' m  oct 格式化为八进制数值数据 输入和输出( R7 {3 ]  f' ^% O" N. x* E

% `. U9 u" J4 h% C( B. A$ n$ E  setpxecision(int p) 设置浮点数的精度位数 输出
2 {# ?  b" i# ~( C3 V: _6 A, p7 D 7 d' a- d7 M% M) }& T% }
  比如要把123当作十六进制输出:file1<
, [: {4 k0 C: \; s8 z# o
  2、二进制文件的读写
& e& C6 @- b7 @7 q. V9 w) f
! ]1 h' k2 F% q4 }- s8 s$ @9 k- s  ①put()5 B4 q9 i. C# y( m: I( M7 Z# ]( @! ]

' U& h6 n9 @) v6 e" T6 P$ V  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
2 H2 B1 G+ N3 A
. A) Y( a+ P# Z/ _! W  ②get()5 R' k9 V8 e( ^: Y0 |

8 e( O+ }% p2 N  get()函数比较灵活,有3种常用的重载形式:) j+ S8 f6 @- r8 O
2 s4 c1 l9 X4 `1 L( z
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。6 [$ P/ Q$ \5 t# P* `

; x( P. p4 H' o6 n% S. ]  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
3 p% V( I6 `1 P" H3 T & i& q9 N6 g! S& B. Y" j
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:# o: _4 }0 q& @% s. ~0 e& x
3 }6 |0 d! x: k
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
) W% S0 t. e$ y9 g9 Z  }8 s
8 N+ V  F! A4 ^  ③读写数据块* j, Q8 [/ i! t4 o# Y1 }
% q  B8 \) A, Y2 k* `# c
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
: k4 W$ X. _$ @" n 4 z# i1 k% Y: u) g% _
  read(unsigned char *buf,int num);
# M" C$ e- {$ |* X% ~1 j
* c9 E/ k4 U9 i- |' R* {  S8 s  write(const unsigned char *buf,int num);
& b; K9 f) X) i . X- r( N6 Y7 i$ Y& }
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。$ D7 e4 x3 G8 ?4 s

# N0 }3 s# t  K$ E+ }2 T  例:
% ]! g- w$ z0 B - O& |" n+ E8 ?
  unsigned char str1[]="I Love You";
% J# x1 H  [0 X' I   B6 S& z$ f9 C
  int n[5];
. X/ h4 q9 L- ^: K! u3 U$ g " J8 X; k1 @" Y& T
  ifstream in("xxx.xxx");$ v& g+ I- w. X( b$ C: v
& f) K5 ^# {) ]; B) s8 W: j
  ofstream out("yyy.yyy");
+ X& D- b# m) F 6 z. `3 o! [' e' U/ d/ q0 v
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
. d9 U& X6 U5 c7 ?5 s; e* h
# v* }( e# R' z4 e# q  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换4 a) a5 c9 D) b& f, _

0 V0 P% L) I; R3 y& b  in.close();out.close(); 四、检测EOF
  X" e( J$ S7 ^: _! ?
1 L: T9 A" H; Q3 T7 L# \- j- I  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
( C9 I8 s. X! d  q$ n
7 w9 }( w. @9 Y  例:  if(in.eof()) ShowMessage("已经到达文件尾!");: P9 L/ c. d# [: ~/ ~

- L5 ~: Z2 v, o% @0 e) u: T  五、文件定位
, I$ q2 I$ _7 ^- x4 a" Y
6 N! H1 w4 P; D* y0 T, m  V( _  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
* W9 E" e) }4 G0 M2 `( b* x: b$ D
4 e* K  d* C. x: @- z- ]  istream &seekg(streamoff offset,seek_dir origin);
$ Y2 l0 V# [, R; |; K4 r2 V$ y/ F, E5 S3 e
3 N" c& t) K1 H' G4 q  ostream &seekp(streamoff offset,seek_dir origin);4 F! x" |& j5 I1 f& t

! p$ G- M8 G! c: N  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
: E$ F0 u/ E9 E4 K  l4 P+ _
) R5 ^6 d+ L+ e  ios::beg:  文件开头# f2 F+ v% i1 R9 [: `

% S1 h* D& t) E# v( `  ios::cur:  文件当前位置
* C4 ?4 C8 h5 H3 o5 W1 V0 \2 M 3 E  w. C' \2 \& f6 j+ x
  ios::end:  文件结尾6 x: v& a2 R7 X: ]% E1 N
9 K, n: Y8 }! t/ Z8 U; r+ D
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:# d! c  z1 f! L
. R8 G, L- A$ r. V3 P5 l3 ~% `( R
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节2 H; D3 v+ Q+ b( L. N

+ v9 o" T! f* V8 Y5 t  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
8 v9 Z7 U2 s+ G! G  O' ]$ Y5 b! J

$ [; w! V: a/ ^; ]( B, U- E
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.diantuankj.com/ doTeam.tech
回复

使用道具 举报

发表回复

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

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

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

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

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

    我知道了