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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
* e$ A' ~: D8 V; [; s+ I7 R 0 q" o: U: N0 b1 W. L4 s4 J
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:7 D+ n! R6 F( V; }& ]1 K) l

  F! r4 `! C6 x3 w" G  1、插入器(<<)
/ ^* L7 G7 e4 {0 u& r% t 2 C& |& H. L4 r, T, o+ _
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。& E8 W% `$ `7 f; R5 g  o9 y" h

5 J0 x8 e# Y8 o. c. p6 z1 {* d  2、析取器(>>)) m5 n, g8 L7 E  G5 i, b  k& {

; T5 k+ A5 K, f7 j; t& U  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。* e2 F" B. q# U% C
, ?1 F8 z: \4 t2 a) U
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。; x2 z3 K! z6 S; o( j. i2 b

/ c3 N% Z% X8 k( T1 w) [+ E* Z' m  一、打开文件
$ x) o- e+ [. D2 v$ Q' Z! H
5 }* j0 J3 H1 |6 O  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:! j' X  f  j! n2 A- w! R# E# X
& {9 `, E. I4 f  s- r3 T
  void open(const char* filename,int mode,int access);参数:
% D! }, o- s3 u! r 1 X( B7 \! _2 K2 C
  filename:  要打开的文件名7 |" K* p6 ^$ F% x( h/ g

' [/ x" u- J. A  mode:    要打开文件的方式
1 e+ z) y5 E1 j( {# B , ?- Q0 N# \& Q; x1 n; K9 t
  access:   打开文件的属性
9 W& \  a' N8 {* K: h
2 f: P; B4 g/ r  l) i; n/ L  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:
) c' ]" O/ [: m, } ; A! C+ C1 V2 t! A3 R
  ios::app:   以追加的方式打开文件
/ N! }2 Z9 g( Q. u! P ' E- ^! a) J, x; D3 P7 k
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性) t/ S5 r1 }5 _* v' c: H

7 Q5 i* P  x6 y9 G. }  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
: l: O; m* Z) i7 g( t- t, ^& R0 _
) M# m# g5 ]8 }7 ^4 L  b* E  ios::in:    文件以输入方式打开(文件数据输入到内存)$ V8 Z( Z4 q4 i1 \* U3 F# j8 ?2 w

) F7 n7 [8 {  X% S5 t: f) M6 v6 [: ?  ios::out:   文件以输出方式打开(内存数据输出到文件)
7 E1 L+ x2 X# I5 S
0 x3 ?4 y- l" ]! U) J3 A* O; ?* w. m) Y  ios::nocreate: 不建立文件,所以文件不存在时打开失败
8 }! E# _% C/ w  e$ S 0 K* ]; l  B# G) e( j
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
  Z, T- x0 f# `/ \6 n8 P " p$ r1 Y( @: d
  ios::trunc:  如果文件存在,把文件长度设为0% v, B0 Z( q8 n" X/ R
0 E5 |" B, w, I! y1 ^9 S. V
  可以用“或”把以上属性连接起来,如ios::out|ios::binary, H5 v% j* {5 B, C- Y
7 z- l" U; M5 l* @6 a5 q- o; n1 J( k
  打开文件的属性取值是:4 R. A: o3 K4 w3 Z& f+ e
2 Z1 C: M$ g4 U0 T' x
  0:普通文件,打开访问
8 v# g7 V, Z' Q- } - K2 h5 w# u. Q0 \2 F) a& R
  1:只读文件1 B. D) J( U. ~: q

7 T( m9 L- \+ {& t) X  2:隐含文件' d$ x# e' R0 Q6 p  }( a

& Z! S  M1 n+ w( h- V' y1 Q  4:系统文件
3 _8 D& I6 V! i' N; Y& |' i1 h
5 T  k  g0 W# e& A- C  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。. [. x% N  Z0 z8 U. H
' A4 q1 o" B3 d+ }' L# N! u
  例如:以二进制输入方式打开文件c:\config.sys# o. r& p& \: b, E9 X% ?

. ?5 z" }8 e( A  fstream file1;# ~# c. m1 z/ A

3 `# W& m- p9 V  file1.open("c:\\config.sys",ios::binary|ios::in,0);' H& z0 v- O& T
& x# |2 p( q& z% T* R& x7 s
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:8 E2 C4 E. Z! w! R2 w: b' G

" V* Q) _7 c" A% Z7 ?) ]  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
: ]2 h$ o0 H: V + w9 K6 j( [& f% O: o/ r1 l8 j: S
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
2 @, }( [. ^2 A" J% g
5 Y- Y! M3 }( Z6 f  N  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
$ z4 X9 e2 ]9 E3 W, I; P# r , Y+ r0 I9 X* ~1 o
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
0 j& q: v2 X& u5 x7 }2 x . b0 H  v8 y- v3 ?
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
" D2 _4 l/ d& q* S" N 2 T4 y" W4 U) {& G
  二、关闭文件' e, m; Y0 D3 ^2 _- T
& t" N. L- `0 {0 g2 x' E
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
7 t+ @( o, c/ D% r  \ ) _* ^" {1 H, A  U% }1 i& W) I+ F( ~
  三、读写文件
0 F4 T9 X9 L. J: h5 v9 j' c& E* b 7 O0 s- n8 l, k& H+ A
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
; c% [4 c( d) ? # w; |2 S; p) t' L
  1、文本文件的读写0 N9 R2 b3 C* ]& ]

, [0 n6 ^9 |$ @8 r$ y% O  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
( U% K) R6 J2 v% n) x" P 8 y$ k3 a7 P3 M( P- P
  file2<<"I Love You";//向文件写入字符串"I Love You"
$ e. B/ Z- k  k1 K8 Z+ I7 _
8 x( |7 C. @+ g* C+ p  int i;
. [' p% ?- }6 v) k5 N
' y& A+ ?  D% T) ]  file1>>i;//从文件输入一个整数值。
3 F' M7 N, s& V/ b5 J1 I
& F: B5 b$ e, k8 ?6 U* w9 S$ h  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
4 G0 u. j5 m9 l9 \2 W
1 Q6 `% \" V& |5 z/ e, a) ]  操纵符 功能 输入/输出
5 k3 _0 @/ j% N: ]
3 q0 h; H; y+ e$ u: x3 }$ o  dec 格式化为十进制数值数据 输入和输出
2 X4 |( y/ {8 j
7 S0 ?) y+ [  f$ ^' S- _) x  endl 输出一个换行符并刷新此流 输出
2 S3 N6 D; R* M , K) ^, b' @/ V: ^
  ends 输出一个空字符 输出
- }- G7 Y) \& k5 p
& j" m: d/ e; {5 {0 o& X  hex 格式化为十六进制数值数据 输入和输出
5 _4 F# A7 A- n. L& b9 X! {4 w ! {/ I* Q" v8 F, y6 _
  oct 格式化为八进制数值数据 输入和输出
$ ], j( F. l+ u4 T% l  v1 { / B  w3 I0 D3 E4 c4 r
  setpxecision(int p) 设置浮点数的精度位数 输出0 p7 ~1 c4 u: Q& C. V

. c9 c2 S0 }; w+ g4 I( ~6 I8 h$ @: m  比如要把123当作十六进制输出:file1<
/ J. z, p( z' F: g: f
  2、二进制文件的读写
$ M3 Y& `! h+ n6 H+ S- F& t
$ Y* ?1 |, y- o7 b  Y5 t/ e0 `& j- C8 n  ①put()
1 H0 @  j  R0 d; t7 F5 J+ C5 y
5 V( g3 X- d3 H  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。, i" W9 Q; A' d9 d& `" D# E

/ k+ F  i: c5 P! S$ {( S  ②get()
+ a, z4 F; f" Y; g  ?6 t/ R6 X # |& D0 X$ B8 y! {
  get()函数比较灵活,有3种常用的重载形式:
8 @8 ^' ]& D1 x' i& C
% K! u: X1 l- S  y# b/ v* R  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。" N: E! b4 H( w& Q+ r; p+ S
  T5 n/ Q+ ~0 C$ |
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。7 A8 w! V9 X8 U/ R1 I3 a

, Z  e# n- u( {# }. s  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
) F( ~1 O, |4 g) K( v' h $ Q+ @: W4 x6 q; T0 j) f
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。; W; z4 G5 S% {& A* d- K

& @$ f( u% T. b  ③读写数据块7 ?0 G4 B) m0 i2 |0 i9 ?" {1 @4 M
' s. D8 I, O. r7 r
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:" G1 ^5 ^: [3 v8 Q' E0 {$ ^
) F2 h' \. R% N! A
  read(unsigned char *buf,int num);
+ L1 h7 p* W; ?, n+ m7 g- Z ) n8 S* _& h- f1 |. G# S
  write(const unsigned char *buf,int num);! |4 R. k" P# D* r& ?7 x9 m% q
: i! o) o4 r% _! _7 \8 f
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。5 J8 O0 K/ M" B) a% c" g
7 M" W- [# ^: b$ ^$ E# x
  例:: W. t. m2 c" w/ @3 b5 _4 o0 U8 n

' Z; M- N6 A7 ]: }( u- J  unsigned char str1[]="I Love You";0 c! G. h7 L; L7 r9 |5 Y
6 D- h, W4 M( k: O. \% v. A8 O
  int n[5];
$ g& a  S0 Q; M+ I' }
# \: S) `5 u& \  ifstream in("xxx.xxx");
. c* D( o) s  j6 ?4 I- c) S; |
7 |1 g( Q. ]6 e# @  ofstream out("yyy.yyy");
' L# B8 b) y7 v% r5 ] 3 p) V& ?3 j4 C# T, \
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中' y" f" H0 z. a, U7 U

, }% c  e8 h" x+ `; k' u, f3 B  M* [  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
- n& j; J5 J5 A9 H3 i: z
2 @: f+ U7 u9 j# T: j  in.close();out.close(); 四、检测EOF/ p% X  S4 L& n# o) [

7 _( J" N0 H2 x' z4 g2 ~  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
; f2 @3 N, |$ y
1 p  L; A# p0 K! A  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
' A9 z+ }! @' b1 X : y- \2 y9 [' c5 C4 i4 z; [
  五、文件定位
- {+ Z+ f" y: ?1 R3 n 3 H0 Q: \; k! p& C* p  j, t& \# s
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
! D9 c. F0 k0 E: i8 A4 V * E# Y+ q1 L, S: y* c0 O3 D+ }4 ]
  istream &seekg(streamoff offset,seek_dir origin);, o3 r/ @! I  T3 E
7 @9 e* h& H9 C1 T; e
  ostream &seekp(streamoff offset,seek_dir origin);0 q7 v0 \* K1 o0 u

1 r- h0 s; t# T  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:2 X& _" l( L" l0 {

; Z, U1 r/ C$ n" r- ^1 I9 a  ios::beg:  文件开头% ?: `7 L, a& q( ?% M

& J# d! }0 z1 I7 X6 C1 P+ t. Q0 S  ios::cur:  文件当前位置5 G8 F$ [7 ^$ y/ K- L' {
" r, i3 f8 A8 [& K; ]
  ios::end:  文件结尾8 H: [6 D9 F0 a* T3 G  T3 F9 l2 K
; R6 a" s  W2 A
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
% A2 {5 d0 S" a  @. n: s1 {
2 `; _" L; Y1 U' v  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节' i4 F' ?& Y0 Q

+ g1 g2 ~8 D/ h# H8 O$ k  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
& l" o, v0 z7 `6 V* O% z, a4 S" k
1 {8 y* F& }% U9 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二次开发专题模块培训报名开始啦

    我知道了