查看: 4650|回复: 0

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

[复制链接]

4

主题

3

回帖

48

积分

管理员

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

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

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

×
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;) @" u4 v5 j' o( O# G2 E

# |6 L$ ^9 W9 b6 R# ?( b  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
; ^; x; c3 p- m0 O0 Z0 E1 j% N/ Q / ]- H2 ?6 t, \8 x! Y' i
  1、插入器(<<)
% `1 W) W# R/ p5 s% l3 K& J 2 C/ Q& ?% i& p+ b/ m
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。$ Q  y" [1 k9 ^+ n% g
4 W  M% r/ _$ f, C4 y' c1 s5 I
  2、析取器(>>); H( L( E4 s/ u  Z: ]4 N$ ^

9 V4 a5 J: _: m" u  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。6 ^0 ]6 d' C: A: I' `4 R

( C4 b8 q, \, F  w+ [* g  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。8 H* C* y3 \2 |1 i

+ F" O: R: N) Y4 r* ~  一、打开文件
6 w" V1 R9 a! ^- j3 G1 K" j % K- G) r% W$ p7 i) E! f
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:
4 P* ~4 x) `( r3 r: S6 v8 @; \0 Z
0 k0 e6 X* s$ t+ `4 t  void open(const char* filename,int mode,int access);参数:3 w6 v% E5 t* }" G' V

" x) _7 \& r. F5 l  filename:  要打开的文件名
; j" L6 Y3 D" b% G% o) Q
( E7 X$ w( d6 w  W, }/ a  mode:    要打开文件的方式
, d3 P6 U% Y' }7 d" J $ [  l7 I0 W8 ]$ F, Q- {: u
  access:   打开文件的属性
( Y. m* ?1 M, V, M6 X! i
0 a/ n+ [% b' e# u  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:6 i( i6 p9 N4 ^0 _, a1 C4 L3 V

( f% `( c+ q2 M, m; ]$ J  O: l  ios::app:   以追加的方式打开文件. Q# P0 N# A& [7 F8 ?& s
8 B9 _7 c) s& r* o! k0 _2 b
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
. F6 V9 ?) L% `, Q- [, A- a
0 l" S! A# `4 S  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文+ \$ z, E+ B& x- R7 p, U1 c) G* v

5 y0 ]% o: j. s5 q: l7 S. d  C  ios::in:    文件以输入方式打开(文件数据输入到内存)7 v- Z" l# l% m& Y* y0 k* R2 V

& {9 z( w! X( n  ios::out:   文件以输出方式打开(内存数据输出到文件)
: Y% \; C+ W. G$ U" W( D( i/ }& z% y ' }+ u: E7 a7 i0 g) V+ P0 v
  ios::nocreate: 不建立文件,所以文件不存在时打开失败1 E! f- v; E8 w6 Y& _
5 B4 Y; d( |5 U8 i
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
3 a/ ^) d  n0 s8 I$ X( h" [ ' \0 e# m8 q' T% B$ \+ L
  ios::trunc:  如果文件存在,把文件长度设为0" F" Q1 G- s( O( V* X
7 I. z" I' ^; z$ w0 @' j
  可以用“或”把以上属性连接起来,如ios::out|ios::binary
2 a! i( O- Y& S % W" W* V# R1 O$ U) b% o' F: n& P
  打开文件的属性取值是:
: A' @( N& e! l8 K2 l/ N * L* @4 |. |* Q
  0:普通文件,打开访问4 ^- z6 c+ `" B$ ^0 i5 r3 l0 I! k- z
$ x, v% X$ U: q
  1:只读文件
' H1 e1 A' j. X2 |, K 9 k" A8 Q  q" z5 Y, E$ }" A
  2:隐含文件
' g4 H" L* X5 h! U7 k3 b! B) a
* C; d2 E, t6 H  O- [1 ]0 Y  4:系统文件' c6 u9 ^3 t/ {! t

# ~( V+ Q* W5 e/ d' z  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
, z( w' p( i5 N: `7 u4 w
" g9 i0 j) J; D  例如:以二进制输入方式打开文件c:\config.sys1 Y* L# t. ]! ~# O" T  n; c! @
4 o5 j2 V3 `" @- a" v
  fstream file1;
& ?% A' q0 i" g' N 3 ^( ]2 y1 _! z) X. }& r& Z
  file1.open("c:\\config.sys",ios::binary|ios::in,0);6 |2 P, |( s" r& Y, \! n

, b' j0 m3 ~5 V+ _2 [2 [% |: T  [  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
: H" }! b; w4 \3 [  F
& C8 B7 ?$ `" }4 L' Y  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);, d8 r4 l3 V, a3 p
+ @5 i# H* _; ^4 q! P2 F) J
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
4 Y$ f  m/ o% F6 A1 @
( u( O' T% K+ F! |. ?( V  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
, B( t# Y" D! r2 Q! ?; q- S) M  z
& b3 L* H. B. U  @5 {7 F  ifstream file2("c:\\pdos.def");//以输入方式打开文件
  V/ @! D- D2 ?/ v; a
% b2 v7 i) F6 X5 C2 h8 U3 w7 }! |  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。+ e1 x3 j7 w2 H6 {# j4 p7 a

, a& s3 ^% A, a7 w, s  二、关闭文件
7 |5 T2 H. b- K% {. y& B7 n
8 Y7 B6 W' e7 O; _+ ^  @3 J' t  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
: l* E% O# o' ?. V! R7 _
- e" ]7 \4 s- F  三、读写文件. ~9 I8 j! T9 d; V. U, A# d
- r4 ~4 o( S: x. D  q1 v
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式. o$ f8 A* A4 \

5 ~2 o4 Q: M5 m7 c/ P1 h  1、文本文件的读写
, i+ l2 \# U& W  i+ a2 h
6 q, k/ d' ~+ N6 }0 A! v+ K" u  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:3 z" Z2 N0 ^& u/ f0 I
# @% Q/ k, i! [$ g8 [+ f9 d, ^8 Z
  file2<<"I Love You";//向文件写入字符串"I Love You"
8 c  `  @/ ?& v6 L. ^/ R 6 a& j: O- v6 v
  int i;
8 f' k/ J% U+ g) N / A- X5 d: \2 B4 M; m
  file1>>i;//从文件输入一个整数值。0 {6 p% o) G+ }7 {
( O' L' l, A5 {& u$ j3 M" H2 {
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
. a% w- i6 s7 l! i4 c- k3 h   a$ |  {3 t  y# d& A( ~2 T
  操纵符 功能 输入/输出( Q0 T  v# }- N' u# P. W& s
( S  x# u1 h. p/ U6 r, D9 E
  dec 格式化为十进制数值数据 输入和输出4 a5 b- C" d3 g. q  V1 y) R
2 S* i' r7 f, f! _$ m% M  n
  endl 输出一个换行符并刷新此流 输出: P$ o) Z  B3 I& a6 ?
- x3 p5 L, F' V6 v+ X6 `0 H
  ends 输出一个空字符 输出! L. v7 J' `$ v$ H! p' g

( ]1 z- e+ [9 B9 y  hex 格式化为十六进制数值数据 输入和输出
; i4 [8 B3 C4 Z' \; k
9 d7 n' r3 T6 v+ v9 B( l  oct 格式化为八进制数值数据 输入和输出
$ A/ \4 v# t. M. @- @$ } % z; H5 u4 A* e! M! g9 ^( `. _
  setpxecision(int p) 设置浮点数的精度位数 输出! \0 p9 u4 _8 k

; L- t1 {' Y+ j7 C. D! a. v; E  比如要把123当作十六进制输出:file1<

; \4 W, g0 p1 j9 L  2、二进制文件的读写
$ D0 z+ N; ?2 t
- I2 N: N& _2 R. E- s. H  ①put()6 s. k5 o9 ^2 @0 j. h: q3 R
+ a$ K+ r' `$ U9 d+ i
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
) I& a1 X% v% E0 d- d6 C
) A6 K$ W, E% K1 X) l5 G# S- B6 M  ②get()5 P: t$ _; q& T& K* H$ P, w" l- m

0 m& H( |1 z7 q# Q! Q  get()函数比较灵活,有3种常用的重载形式:7 a* r6 K3 n* ^8 b5 t) M

8 D) K+ d# k: [  Y3 \8 ^0 o  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
0 p) H5 q* W3 \8 ]
* W2 s0 Q4 Q1 f$ N9 L+ z  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。7 w' }3 L; G8 I1 L8 A5 [
6 M7 k5 S$ k* P; P. q$ T
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:9 B$ u7 J  |: E2 y# a
  i/ |- u9 ]' ~, Y- _; g. L4 P( k
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。  j9 h# ^' g6 {/ x; X! H
* b- `9 C8 ?' v) z
  ③读写数据块
! L/ O5 c$ P# O6 B' M9 o* u
1 n, @+ i( R  C% F# x; H8 b* [/ R  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:* Z7 ~/ K( B& K. e8 K' a
8 j  d- S& |4 I
  read(unsigned char *buf,int num);
; M" g, m  Y( K  v. w$ u   G3 a9 Y9 n& j
  write(const unsigned char *buf,int num);# o4 _& D: q5 B8 A3 X- t' ~! I) e$ l) t
) w& S, F! ]4 I! h! _$ v
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。6 }9 U" }0 q- k! s) {
# N% l3 v, f8 `' ]( M) @0 w- ~
  例:6 I* S, C3 q% {9 z% @; C0 M, E

! }3 F; Z  T& X2 Z  unsigned char str1[]="I Love You";5 p5 Y) N+ Q( q

3 W! G' c$ _- D  int n[5];$ F9 H$ x  _( I6 l$ i, i

$ N6 v8 l: |; s% _+ \* D. w7 Z  ifstream in("xxx.xxx");
7 ^( T7 X+ E! w 7 W1 n7 J% d: q! ~' ~8 T
  ofstream out("yyy.yyy");
' |3 v$ B( r) c6 `8 p: ?. l# A( g & E7 |4 W  ^- @+ y8 {  j
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中0 w- `7 Q8 x5 k; a3 c4 g' V
: ^4 P$ O; X, l( u# S
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
/ |4 Y7 d: z: V( K
" w1 h; P9 O+ D9 K/ f; n& x$ t/ G% {1 }  in.close();out.close(); 四、检测EOF: D0 P" [" I; p* g4 a
9 g! {( c) P( t) W
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
* l' @( d# e) a1 I# X 8 A4 ]) f5 n% c
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");7 L# a: S; x" |3 w$ ^8 P* u
7 Z/ y2 y" [" ]+ a" t2 m9 @
  五、文件定位# Z( O& P5 D5 E* s  u* g
& _9 L1 V  Y' _' a8 G3 m
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:: ?8 C) A; _" \( [" o
9 T+ a# b5 D7 r; G8 Z
  istream &seekg(streamoff offset,seek_dir origin);
) }# o, F. t9 |+ p
! A! E/ i' H' v- {  ostream &seekp(streamoff offset,seek_dir origin);
5 F$ p3 X. ^9 k/ V4 u( }" Z
3 D' }/ @4 o) }8 m  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
6 v1 q# c9 ]% l6 k" X7 g) q4 o $ u) c& f) @3 J  D) T# R& r* L, h, ~
  ios::beg:  文件开头& M% Q. Q1 R1 H" O

: `0 M9 S( c3 h( A  ios::cur:  文件当前位置
8 D# y6 d' I; ?6 H 2 l- i3 M* J, q# W% ^% s" b
  ios::end:  文件结尾
+ i% n! ?5 s' m" V
" R% a2 O/ f$ r+ W4 n- W* \, z7 a  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:/ l9 K; Z5 a. p- z
9 c- `. _2 J- f0 y4 m2 c: J
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
8 ~* U/ _9 ?0 A, D5 G9 X1 c& ] & R! ]2 W* N! H* H( z
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

% V8 v& W5 C' S5 L( d3 _$ q' p% R# E" p. C9 ?+ A
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.doteam.tech
回复

使用道具 举报

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

本版积分规则

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