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

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

[复制链接]

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

2470

主题

1275

回帖

8万

积分

管理员

PLM之家站长

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

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
% o% K: ~' N5 D/ `2 {" U
/ ^. C8 c. m4 o! Z$ N# A! O6 p  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
# U3 t# F3 x, w" k6 N
9 D# ^! o. c3 T8 e4 C$ W  1、插入器(<<)
# M0 o* W4 S; C; ~8 \& F
+ d' R" v. b0 C& F  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。. H7 ~# P, R/ q2 e

) X( T) |5 y5 s0 @' b  2、析取器(>>)
' Y, d8 }% M2 w) G # c5 K' Z+ I" f
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。- k# ?' j& \0 E$ o/ |: J
5 ~; ~: U% F" y9 T0 S
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
  C5 F0 ~4 b! c/ I ! M1 `+ l9 k# _/ Z
  一、打开文件- ?. p% i6 X% u5 S. E$ a! ?/ d
2 q2 I4 E. q# e  d. A/ z' D1 d
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:: n# z! X& ^; j( P2 _& I

: K+ L. l' K2 c5 [9 M: a4 S  void open(const char* filename,int mode,int access);参数:. k2 Y5 p/ y: f) S1 Q; J

% F4 D3 W; \. g2 G  filename:  要打开的文件名2 f; ^! X8 Q# V1 a  V: d" S* y: i
" ], |* c$ v% x5 d& i/ G6 v
  mode:    要打开文件的方式
) j; A6 ?# M/ {; E4 u3 I- T
9 A3 a" \8 b/ A# t; C0 O7 v  access:   打开文件的属性
" l& {* Q% ?* S
& X7 r) Z9 Y: i1 e% D: o" m  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:
1 r) q* a, ?$ @$ l6 ^2 E
7 |1 x/ j- H/ C0 L9 v6 `, ?  ios::app:   以追加的方式打开文件) N1 [4 P6 y* O# Q
" Y" a) D3 \1 ?  {  w
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性- o0 k# O3 N- l% V$ P

3 V* N% c( j, C# r; \2 |! {. x  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文+ J/ w6 |9 m$ }% y

( S/ i2 \; A5 l4 @, I  ios::in:    文件以输入方式打开(文件数据输入到内存)
" I) K2 g. I5 |" d
- r" E! f, m% K' g# |* Z  ios::out:   文件以输出方式打开(内存数据输出到文件)2 e" q+ F0 Y3 `9 v, w% K
2 v/ J) X! d; q1 r( f
  ios::nocreate: 不建立文件,所以文件不存在时打开失败
: f: w/ A# L, Y1 R# l6 [2 c. l- Z
, _' k5 }, r! ?$ E# s  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败+ \  A6 ~5 x+ E7 d' N

' I; m5 P8 p. b$ w7 }& S  ios::trunc:  如果文件存在,把文件长度设为0% u0 p, S; D$ E: g

4 o7 J0 m/ k7 X3 Q. _  可以用“或”把以上属性连接起来,如ios::out|ios::binary, [! X- U! P7 |7 ~
  m/ l1 z/ D! W/ |# E3 \4 q0 M0 Y$ a
  打开文件的属性取值是:! S* O$ Y9 G5 A3 Z* t! v, S( P  X0 v
. t+ y6 z4 f0 O# v1 j, i
  0:普通文件,打开访问
- d4 ~6 e, F! M1 S) c  O% z9 T
+ }* A1 B1 i5 S" r4 p  1:只读文件
! I2 _- A2 w0 U8 {: g5 X. [/ }+ N
# R/ w) Q8 H6 o& b, q/ ]# [  2:隐含文件
$ u; L! d5 g- z, Z  `
* y/ J/ m) k" {/ m: |* X- s5 \  4:系统文件
' z: D3 I( G: U$ Z) m9 k8 @% z0 T4 c! s  N
5 H: K5 @. \/ R# X  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
( g* o* n/ c/ S; D5 h2 U ; T/ j( P$ f( f
  例如:以二进制输入方式打开文件c:\config.sys
8 P1 h0 e5 I/ q+ Q; e# l
; `. r; ]4 g( ?3 l# d9 `" A  w  fstream file1;
: y. j: B& a0 U! S
- ]% n- J( l$ Q7 U  file1.open("c:\\config.sys",ios::binary|ios::in,0);
% A$ E3 i1 ~& x
% W' [/ W0 ]( {  P4 A& L* G  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
- P: a- r* R" ]9 U3 p& R" K4 B/ ~
6 @  d. R' m2 a3 P; A. U$ C  ^  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);' e0 z4 ]$ a8 o% j, M) i
( t& b0 h% t( y/ A& _
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:& \' R  }: m1 R4 E. l

% ?7 U/ K& V6 k9 {  T3 y  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。# r1 v' W+ c+ f" `1 K+ P5 a& v
( f! H* y  T2 i' z
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
5 E8 g7 P6 J& N- ]! R1 l 2 `2 c8 i, @: {& ]/ y# d
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。' L: c! H' C# o4 U- V! ^

! j, b4 B' \, v  二、关闭文件
9 b  S2 S) V2 U6 B5 W) J2 Q
5 I$ o% c3 G& U+ @. a! M+ s: a" b  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
+ G/ M8 @; z) p; ~5 Q* J0 N: M- q- } 5 r" j) U1 b( ?- ^. V; A
  三、读写文件3 i% W+ q6 S) z& `  f1 _1 J

! \3 O) {* h+ e  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
9 c2 r8 j4 g4 z' d8 S" M; R9 g
* N) x+ q/ b; t. T  1、文本文件的读写2 D3 L- h' M! _
  T9 e. _; q$ n
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:5 Z& |) U4 h  s

  [5 G/ h6 s" S4 @3 d1 S  file2<<"I Love You";//向文件写入字符串"I Love You"- E5 G8 @( W% i: x" ?6 E2 x

% r! \4 N. A3 x& Q" S- E% a  int i;6 }# F0 t, }1 f" B" _4 b+ t
" x; w6 H% T* ?, ^& {
  file1>>i;//从文件输入一个整数值。
/ U# s/ Z& M( U/ l4 F / P  U2 h4 `" O, I3 d$ ~1 o. T
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
; y  S7 k) d6 Q$ b! u; A# b( F& G6 X
1 _2 d* h  j+ F. s+ K; `3 v  操纵符 功能 输入/输出
, n; C/ i1 O$ v# E- S: g9 P+ i $ C- O# t. D+ s. K% ]9 W& t
  dec 格式化为十进制数值数据 输入和输出
: H! p; p7 u$ ?3 ~7 O) E) O% C
7 l/ k2 Z; [; b  endl 输出一个换行符并刷新此流 输出  \5 l% r% O: q5 f% V

! p6 o. U8 v* p/ c  ends 输出一个空字符 输出
* b: t; W5 W2 \" r2 O+ @
% u- o8 S5 w1 G5 Q1 v9 S) t- r  hex 格式化为十六进制数值数据 输入和输出; w% I$ B, Z1 {. v% m- W

& V7 f" V2 A+ Y9 k% s  oct 格式化为八进制数值数据 输入和输出
! _) A# z( q9 H+ n  z9 t" o: p 8 S, Z2 X- H. y
  setpxecision(int p) 设置浮点数的精度位数 输出
0 c4 c* x% t1 ]2 g/ a+ ]
; O! |) _9 s8 h8 p# K9 t  比如要把123当作十六进制输出:file1<

/ i9 X" Y4 g9 C: @  2、二进制文件的读写
0 {9 E  V, s/ Z% f$ d
- x6 k  F% c/ v  ①put()5 ?6 z. Z7 e7 {3 P) b

: b+ b: z: S: n+ n0 [1 e) g  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。: O- a4 d- q( Q! G) I: Y9 E. P3 |7 |/ O

5 P3 C" G+ y% x6 X( n  ②get()
4 K" A; B) p$ }, Y1 X# X" \
' A$ Y1 p, f/ u% v  get()函数比较灵活,有3种常用的重载形式:. m4 N- E" {; ~0 U; J) K+ ~
. u8 z; r2 }) \  z9 L" v3 Q/ l: [) m' ]
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
9 P, b8 i% Y# a! ^
! B! V% m* x$ f* V7 b$ N; u* W  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
  f$ x; V8 b& T/ }8 c" z, W# \# l6 |4 v
# h2 w2 u$ ?) Z  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:2 o; |/ f# k8 h( z" `9 T

9 y. ~# l* S' E3 \. r$ V  N: y8 x  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
1 Q8 l* V$ Z8 y. d5 Y& ? 3 X- \. {" _; L" G8 l: _6 R
  ③读写数据块5 g+ k2 V. s9 B: V4 T7 N) ^5 q

  H6 N( E9 w# Y# g- M# _  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:7 E9 ^+ f. r0 \0 L! ^5 g
' l6 R# a0 e4 J3 z2 N( G2 q
  read(unsigned char *buf,int num);
# f! e3 ^2 s) Q6 @ # i7 G3 j; R' O, I
  write(const unsigned char *buf,int num);
7 H: l3 ]; U1 I+ M+ @/ Y  h, t7 k8 C& A   v+ V0 K6 M- u! q
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。- M2 g% m$ v. L3 u  k

7 u- ]/ x) Q! Z# G  例:8 T# E5 ~; u& U* X

( Y. w+ |1 x' `$ L  unsigned char str1[]="I Love You";
9 W/ L5 z% e' ^1 d% S  }: @
* Z6 l: D& ~$ A' p$ `  int n[5];$ n! Y* L- m6 s- a. h
2 a9 O/ x% q" ?  e* }
  ifstream in("xxx.xxx");
& j3 k5 t( @; I+ \2 G2 U" Y& x ( {3 U9 ?+ [& Z
  ofstream out("yyy.yyy");! N& r4 H5 h. D4 j2 y
# N9 y2 O( q  i2 D: Z0 ?3 {( C3 g
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中# Y. A9 [# S9 q& \4 {6 F

% }* t/ k' e0 b7 P( D4 T  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换, G$ h8 C, B8 y4 X% c9 a" W) F

) A) W, [4 f2 F. y- h- u  in.close();out.close(); 四、检测EOF$ B  P9 Z4 o8 r

- R7 N% s: o5 S. A/ m  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
! ?) k8 E2 I. Z* X" Q& W  \ , O4 d% ]/ R" {, U# D- m
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
' W0 o: L  V* O9 y' A$ P. W
. O' F: z2 ^* p( l  五、文件定位
( B5 L9 S+ T: U# _# v4 d 4 ]4 N5 D  ]" _1 j) J. J, Z
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
2 O/ V/ x* @/ e# ^8 [& G
0 m3 S" n$ O' ~8 o3 [  istream &seekg(streamoff offset,seek_dir origin);
& M5 l. y+ A" D% ^% U3 v 5 P# j3 E+ C1 o. k
  ostream &seekp(streamoff offset,seek_dir origin);6 D5 C" C6 u  f3 h

' N1 ]9 c8 n( }$ |  _  o% o  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
# X# f: R: o- [, b6 r $ o! A& @4 g& ~# a
  ios::beg:  文件开头
, V4 s: B$ K  w
8 Y! W. c9 ]7 X2 Z0 p$ W& y  ios::cur:  文件当前位置
( O& w& r9 T  w1 y
- N. L% X; s% R, _! q  ios::end:  文件结尾
0 u7 y3 F& b9 W
: U9 o) |" K+ F  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
6 _9 K) ]2 ~/ N; k ! N: m' i; K6 Q
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
/ I# U' h+ H7 v9 X8 I# D  ?
# a% Q1 \" w2 P" n  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
( z/ m# n( R  }5 g, i% M% X( F
2 c) z* o0 `0 x1 ^  s5 a, N
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了