查看: 4742|回复: 0

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

[复制链接]

6

主题

4

回帖

60

积分

管理员

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

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

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

×
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;- K, m! z$ M) _$ |, G7 M
3 n; h- j) M0 b9 I3 R: C
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:, l( Y0 B- g& h9 w5 ~  m& F

+ j1 ~( Y2 w, v  1、插入器(<<)! C5 k+ m2 ]2 ?( ]8 ^! z

# Y( B0 l! y/ g* L1 Q6 l' Z  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
' ~$ j( F0 }! s& E8 C   V6 ~* a" O( _+ |& o$ E
  2、析取器(>>)7 ?3 Z0 _: a1 i" M2 ^. k7 `9 |  i
8 C. q' m" W  I: M- Z0 _
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。4 I- \9 w! p5 v
1 j& x9 c: j6 S: y5 x" k
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
/ f  r( e) w2 O4 w2 `6 r
) }+ v# j* P1 v! J. T& K  f5 s4 y  一、打开文件6 G# t2 P3 g* \- p. M+ G3 _
/ l) c- q, q4 X
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:
4 m5 |/ L9 W& K 3 \# R% r! q/ d( Q' Q' Z3 p" G, Y) D
  void open(const char* filename,int mode,int access);参数:4 d3 P  @* U0 N
/ [5 {  w+ d3 t: C4 d3 r
  filename:  要打开的文件名" A2 M1 a% @3 R  e

# |8 u6 Z- k  @7 n, r  mode:    要打开文件的方式0 T2 `7 @! B4 h- G* D
/ e- T  e# R) S. h
  access:   打开文件的属性# n4 A7 r( `8 k$ {$ [% W( r

0 c; u3 n- Y* s9 `4 X/ t# l) z  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:1 R+ _7 h( C# W# y4 G: k0 e
! v! W2 y( D/ o. f
  ios::app:   以追加的方式打开文件0 ]" f# p6 x- V, F  T/ L2 S
4 W, A; c; A. c& n. K9 x9 w
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性5 l( E. y4 x) {$ o3 M% ]$ d. H
( b( W$ i5 |( F  i/ K, m# `  y
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
1 Y: M2 B% f4 J* B1 r
) H, ^3 `6 y% z) b  ios::in:    文件以输入方式打开(文件数据输入到内存)  f! b6 w" X6 i* ^5 R+ b

4 F/ @! ]+ p6 W0 P+ z4 j  ios::out:   文件以输出方式打开(内存数据输出到文件)
7 ]5 [) R3 ^# K* [- J  y/ B7 v+ ~9 E
7 I' j, O2 v9 I0 [# @) k& g  ios::nocreate: 不建立文件,所以文件不存在时打开失败" }( o' S5 z  N5 }1 w
2 ]' v* i+ [% @. |
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败1 r. H4 U; R3 E, q8 O$ }# D
6 |; }4 T0 `" B6 ~/ n! U
  ios::trunc:  如果文件存在,把文件长度设为0
" A  j1 y& ~" O% j8 K
! D& S1 d2 }/ M1 i: R3 R, Y% W  可以用“或”把以上属性连接起来,如ios::out|ios::binary$ t$ L" f1 U+ \1 \  H0 Z

. r# h' B, G/ W" ?3 `  打开文件的属性取值是:
% Z5 f% K' t, y& Z; K
5 S0 C2 \0 M; k  0:普通文件,打开访问
5 q. P' n+ w$ f6 x1 j
8 f) b: t  ]& c+ g( l# B* d6 s7 A  1:只读文件
! x' y, b. ^2 ]5 \! Z0 y # q& i5 b$ [, z4 E8 Z
  2:隐含文件
. M7 r) K0 l& [ : p. p0 _5 T  O1 K1 v( J
  4:系统文件
" R) m- A. m4 {8 `: T! y1 s
0 V! n  \# k5 {  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。+ I) V& w8 e' H$ \
# z4 G! A0 ], T3 W- m: O
  例如:以二进制输入方式打开文件c:\config.sys0 c. ~' {' d; t) b

; V/ z' V( k& v! n  fstream file1;$ s  k- }/ O% F& G1 A
% a- i1 t2 a2 |! g/ }
  file1.open("c:\\config.sys",ios::binary|ios::in,0);7 T& N. R0 d! D) w3 @
% J- Z, ]. ~) M5 ^" a6 X3 l; m9 U
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:0 n7 n/ U) W% e: s: ^
- v  x3 j8 K; h) ~
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);" ?: V& ]  @' h

1 r1 e3 _! l; O$ E, Q" j  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
! @! u6 p4 {1 Z$ g9 l " M; f8 ]- [( [$ u$ u9 }$ ]7 t4 U
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
9 ^3 Z0 ^! N. ~  y! L + q& Y. |' y3 [* F, g
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
  Y2 V! f/ O5 E 8 z/ Z6 X7 r% U) k( z' X) P4 z. h
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。3 O. L( g, d  d* x1 |1 d6 G

0 ~# W0 G0 x5 g) X& P7 j  二、关闭文件
% P; C$ M- J4 R( T# e, Y/ h
- l' r' @: G9 l  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
* G4 t9 d0 c/ X. ~: U- {
0 e9 W5 m2 j; |  s0 o  三、读写文件! Y8 P9 N# E' U

' P1 J% H: X5 i1 C( u  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
, p4 l9 I1 U+ v+ a- L
) z9 L4 m/ S3 P  1、文本文件的读写
$ b' P$ g" ?- G& l' M" b) N
9 k; x# x) D  Y( X  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
4 z* A+ q; {0 g3 j& N; [/ }5 Z
) s! D# q' Q$ |. O! d4 i  file2<<"I Love You";//向文件写入字符串"I Love You"4 p; P  _2 o( |  H2 P" I' f' W

# i3 y' O- }- p/ O# b2 D  int i;
) @/ I8 H2 n$ i2 j
& J  U( K& \4 M( K! _' @9 C7 C  file1>>i;//从文件输入一个整数值。% p" N% g( r7 U0 w/ T$ P

3 o, x" M, p; O/ A  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些8 n# x2 Y0 i/ m8 Y3 D+ l7 G+ b

" I  U" J+ [1 u/ L( V; u  操纵符 功能 输入/输出
' `9 H- J6 G1 T  p6 @
* [+ u  c2 t1 s* M# j# h  dec 格式化为十进制数值数据 输入和输出' k* E' n4 H0 O/ A! a
) Q5 q! k5 _5 u
  endl 输出一个换行符并刷新此流 输出
4 w- n& I( y% l' c& S/ i
2 L" q, j( _) @$ i  ends 输出一个空字符 输出
. o8 [  ]( ?; @8 j7 J4 W  s
+ f/ y. P; i/ }  hex 格式化为十六进制数值数据 输入和输出
7 \7 R6 H& |* r) W# K, h3 p- c
, x) `/ s3 {( `  oct 格式化为八进制数值数据 输入和输出
# J/ [/ ~( M+ ~7 D
* ^" W3 [7 S0 G  q1 k  setpxecision(int p) 设置浮点数的精度位数 输出
( x2 y) ?' h, D( `* M4 Z6 q ; G$ @- g$ k0 k$ ^- t
  比如要把123当作十六进制输出:file1<
& ~9 }- T7 ]7 a; U
  2、二进制文件的读写4 {# M+ |* g% t5 Q* h5 e5 @

# o$ z! t' j( k' ]+ o# i  ①put()" m% A* K) b# g  u# N4 R

! K: g: k8 S& _1 @. w  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。8 V+ y& q9 R: q, d
. m2 g! t, n1 S( N$ S
  ②get()6 j0 ?. }; c' e; V7 U' \+ G% @/ R
* z* h" B' L% S0 y4 ~: s5 c# M
  get()函数比较灵活,有3种常用的重载形式:
" w% t2 y5 F& s
+ l4 Q2 f1 E) e& g6 L& [  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
8 m& c. _  i# B/ i! `2 C: o- s' Y7 _ 6 [5 t) _* y$ @  J$ v$ B
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。2 t) d4 r# ?+ C/ A$ n+ C

/ Z# f. {5 n9 G  J# N) }5 b  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
; v0 p9 A2 b/ O0 u, S
, d! {7 F6 O6 k! a  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。  a0 X; F( V# z7 t

  \! e6 p- G  `% e  ③读写数据块% T0 D# a1 Z  a  o6 T7 x- p- f

$ }6 q0 W) a9 d0 w$ w3 d0 i% @  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
; A6 ?8 |5 f* D3 G" ^0 g7 o. S/ W
* ]8 v  c1 O- Z! O( e3 p  }& H  read(unsigned char *buf,int num);
- X  }& H( @- ?. c' R4 ?7 t# @ ( B- `" E" Y. |. E) N6 d; r! M
  write(const unsigned char *buf,int num);
) r' w5 ?: E- I3 I& m  ^
/ q8 Y5 I9 U8 [6 K1 E8 D4 Z  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
9 v% k5 g- I8 \, W9 j0 k 7 |) Z, ^) k  G
  例:* F& l5 g8 B. l) h/ a6 H2 F

- ]# U" }9 @: m, v  v  unsigned char str1[]="I Love You";& e. p2 \% T9 f1 H5 o% ]
- G+ L4 z8 w/ R$ |
  int n[5];/ Q$ r  F" G1 t" ]4 c

# n3 R- v- [9 I) c! }* N  ifstream in("xxx.xxx");
- M& |3 P' z0 [9 L7 D; c7 U' b
' X0 W. t- v* V  ofstream out("yyy.yyy");- s; P8 ?- J; n3 B( F

5 D. d% |3 b  O5 v/ w; P  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
/ r( L6 b7 [; o  z% q
1 C' ^5 F9 L/ ]* o/ }, Y7 V" O* ~  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换: e+ `+ W5 H; e1 t' `. `1 g# \

: Z/ p$ h6 l# z' a4 R) X  in.close();out.close(); 四、检测EOF
' J# E  T( s( }
4 L: ]6 B. p5 {9 G  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();* s, F! e7 F/ W% X) e- p) X+ i$ _- K

" L  J7 f9 J8 G% [+ w; @' @( I6 o  例:  if(in.eof()) ShowMessage("已经到达文件尾!");, I5 w1 K( K8 V6 }2 J4 Q6 T- O
# W% H7 V% r6 L! O$ z1 G: c
  五、文件定位
" s  a3 ?( Q& J+ I: |  | 0 D$ W1 R! w0 s0 B  i
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:5 G5 Q1 Z1 h- V+ _
3 J& A0 |" ^2 i' _
  istream &seekg(streamoff offset,seek_dir origin);
3 u! q. P& [8 Z0 b8 y
3 H9 I& k8 n& v0 k, N  ostream &seekp(streamoff offset,seek_dir origin);
7 C+ B2 Z5 q/ f6 q" r! j" T! U
* s" \* j3 L& v8 @9 f+ h0 w& C( W  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
9 U5 k/ g  C2 R, S/ A& X - ]. X& V6 t1 r6 q
  ios::beg:  文件开头1 s. L. u# s/ u- b# s0 d

& y9 X! n  {+ e8 D  ios::cur:  文件当前位置& q( z4 a5 l, Q, c1 A

2 k0 w7 C, ?/ H0 b+ d  ios::end:  文件结尾  B! g+ s4 F0 y2 j- ~

% c; F5 s0 f1 a1 I! S+ Y& ]  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:) n; z$ Z1 x/ i3 {0 r3 B

2 X7 _: B/ a3 U+ g2 b  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节. X* t$ T/ {+ d
6 F& Y# t# Y- i! U$ [( E9 g6 e. d
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

. k; ^/ Z: \. s; _0 |5 G% z& m0 m  A% x# x: G
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.doteam.tech
回复

使用道具 举报

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

本版积分规则

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