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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
3 ]# y6 b: S" T: x! f , E+ _4 |8 D4 I6 S4 o
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:4 @: A; q& n; ?4 X8 ~

4 ?& v/ `0 e) F' K+ U  1、插入器(<<)4 M( V! f! |; x0 N% d* Y8 @

, C  F7 R4 I! M# S3 }8 J  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
( q. w; h1 }! C4 `( _" F
; e2 ?$ ~3 o- D" d/ a4 h  2、析取器(>>)) \! M# u, ]( r
4 T+ r3 u1 `, g; P1 e/ |
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。2 n( W5 U, j* S% ]3 @; r% {' J
8 |+ |7 [7 E, A9 r% P. z
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。% O/ i3 g2 C8 j9 l

" B9 t* V  q7 ^3 i1 v" y  一、打开文件* {* V$ T& ]2 O2 M$ B
3 t3 m1 H% O% F& j, a; N/ H
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:
3 e: [9 N" S& I4 _0 p: g
% t- w. ^( o7 p' v8 H/ X  void open(const char* filename,int mode,int access);参数:
+ [+ D! o6 N4 K
$ E/ `; V: [; q  filename:  要打开的文件名' C8 k+ G  i& d5 \% s
6 }0 D% Z0 z# N0 w" r
  mode:    要打开文件的方式/ d7 ^2 Z' U4 `6 I% _$ t7 B

3 Y, F* }: L0 l" u! Q4 e  access:   打开文件的属性3 m* _. P6 M5 {/ d* X. b
+ h& Z7 L+ _$ Z" G  {
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:+ o2 X: Y- F" t$ w; a

$ v; P' `. g5 G7 |7 M$ C" _  ios::app:   以追加的方式打开文件) O, \. I- F* w: {8 d. Q, q0 F
( Q9 `+ u) Z% h! s& U
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
$ p; {5 H9 }0 T; ~) L2 @
8 ~# S& y' D( X, {( r$ J  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文7 s# P5 _- }4 b% y1 {4 N, i1 K4 c

0 R  g# J1 E7 ]- J9 d$ g  ios::in:    文件以输入方式打开(文件数据输入到内存)
- Q! ~; N) Y, `, |; @  C% L( T0 \( L
6 n' b$ P2 S" k$ e7 j+ L  ios::out:   文件以输出方式打开(内存数据输出到文件)
5 o6 K, `8 L! x0 o8 q4 G! r! h, f
  V" n# G' C9 f8 D) E8 ?  ios::nocreate: 不建立文件,所以文件不存在时打开失败
  I8 k7 O8 q2 r6 @3 }
+ L* S# [+ ^7 v% ], }* |" L* y  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败, _* Z; h0 r8 b9 a2 x$ f
  B6 h! ]# `6 i4 |4 S9 m: ~
  ios::trunc:  如果文件存在,把文件长度设为0
" S( s1 L: j$ E/ b7 T. g/ i 8 u2 K; v5 W; I: W1 m
  可以用“或”把以上属性连接起来,如ios::out|ios::binary
# Z( A6 p# N" _6 E/ d/ D 3 t( {* O1 G( V! Y* R
  打开文件的属性取值是:# z& x6 X- T0 n9 a' G

! K; [7 t0 j7 E( p: M( E+ x5 E  0:普通文件,打开访问
, y8 [$ n  u$ V ) y. f  A2 v5 j! j7 c* \8 o
  1:只读文件
0 J  a/ E, B' r2 ?8 _
+ D  _# j+ u, k3 L- y  2:隐含文件
# t" w! e, F, d  v0 l) q$ M& h
# h# o. m4 ^1 a: O2 P! d  4:系统文件
7 r) l9 b' L: V+ l) L  x
9 N. U$ [. o2 e+ F" Y  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。' E0 z/ |1 _7 V. L  u; V0 h

  [7 N6 Q" ^+ |- t5 ]5 s2 f! q  例如:以二进制输入方式打开文件c:\config.sys; e" S! s1 u6 ?
' R6 y0 h0 F/ O% ]1 l4 v$ S6 d2 B. M
  fstream file1;- C4 O3 E6 [, n5 ^
: }! p' I0 ~$ n1 @4 T+ {
  file1.open("c:\\config.sys",ios::binary|ios::in,0);
8 W! }. W0 X  B/ P% z/ h
: ?$ R7 o/ \5 P2 j. l  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
% g$ W# |) G+ I  J" w1 b9 I + [( p0 [  l0 B
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
6 s. c4 k( f" n8 O4 _+ o , K, D4 @: G' S7 Q& o* h! L
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:) E0 A# G7 ~, S# z+ T* b6 Y/ e

+ [; o4 n) S5 S  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。  \, |% r, y9 r
1 B; M; G2 P6 ~1 [% x% t6 d
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
0 m- t$ q& _% r0 y% R
4 u) u9 b# _: ^9 t& _9 ?  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
$ x1 Y* i: \5 w1 o- @  A & T1 X! m  x: [7 P% Z) Q
  二、关闭文件7 r4 ~6 D9 g6 ?' }5 K7 b
) `7 c+ D& }7 v! }6 _- ?* G
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。8 @( c( K7 N; x0 e6 T( J" `
8 p4 D4 c( ?: k2 e0 L/ y2 _
  三、读写文件# X+ u/ r) x1 P% H

5 m) }3 Y2 r% u- [  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式+ Y+ G% A- m# u0 n; d
; K% q- }- `! g: s/ Q1 S
  1、文本文件的读写. f* ?$ x; q+ x2 b! k+ I
: q0 O5 A" g  j- V2 ]3 o
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:0 G& W1 y: r8 R0 a0 ~* w6 {9 K; T
6 T; d* }% u) D" U9 I& }* c; t
  file2<<"I Love You";//向文件写入字符串"I Love You"
' ~" I) r8 h* J
- k' L: ^; y4 Z  int i;
5 P8 H: r  n: K+ `% t : P0 w9 ~7 w& h1 p
  file1>>i;//从文件输入一个整数值。5 R% q" V% M- Q! O
5 m; F) t( P* U
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
. [# i8 i" ]' o# s7 I - r5 s) v, o9 @" O+ H  O/ u6 g- ~
  操纵符 功能 输入/输出
' \0 \0 n' a! C. @. k
( _0 k& v, n# h& v/ m3 ]  dec 格式化为十进制数值数据 输入和输出3 D) R) A2 B, k! A) r7 U

  p" H4 M8 }; d8 z  endl 输出一个换行符并刷新此流 输出
5 {0 i9 A- G- J" H, D
* m' H8 Q& E& B( M" U  ends 输出一个空字符 输出8 ^' q3 o$ Z+ |! x

0 Z  b- @* c5 j' y3 A8 S) Y8 C: p  hex 格式化为十六进制数值数据 输入和输出
  i4 k+ f" `' c 7 C# E4 O+ V" |) d. p) |
  oct 格式化为八进制数值数据 输入和输出
+ ?& P! r9 y# ^1 M( e. Y% g   A2 }/ d$ z! e' y# I8 a9 O
  setpxecision(int p) 设置浮点数的精度位数 输出$ {' w% m5 F9 ^

6 ~0 r% S1 A' p2 s! O  比如要把123当作十六进制输出:file1<

3 b3 b( E* N) x- E  2、二进制文件的读写
% v2 N! E& ~7 G9 J% T0 K( `
5 [4 k5 K4 |# i: E5 i; j  ①put()
1 n4 F, m& C. o" ?! U - ^- d: j. k$ z( g+ t7 Z- ~
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
3 o8 N) ?# w( v) t9 x2 T0 X
! n9 X7 X) J" O/ j  ②get(), t" }' }# L5 _7 F0 f  |$ t6 b

0 d. d) U, S9 ?- f/ z  get()函数比较灵活,有3种常用的重载形式:
7 [! U  J, V2 @4 E* Z1 z  l & I$ Y& Z% T1 Z( r4 L3 u7 v* i
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。3 z# U% p, `; b5 o
' G8 U: [- B2 K
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
: v; J& @; ?8 G4 G( b" ?
. R  ~  I  O! s' d, z! Z2 t$ d: b  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:6 f+ H4 l5 Y4 v" l8 U
) @% l9 Z/ \+ k4 L
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。" r5 O0 \' g2 x4 \8 F
) \+ U2 T/ S- E1 B2 e2 h6 f
  ③读写数据块
8 z& O$ H8 \9 P( \ 8 b% H. N0 g% [+ B- t% Q
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:% T  Y$ F: F5 d% M( }
6 m$ X7 \2 X% ^% b6 ]
  read(unsigned char *buf,int num);; v- G' T& l# M3 O. C

/ ~# k7 ?9 Z( [! R  write(const unsigned char *buf,int num);
; l/ z# Z2 u' ?: j. @, f; R ! t( w& s3 Y/ A% k0 B
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
4 K1 t; P3 @2 j9 S( q  v: Z* T 6 ~6 H$ M, @* D* Z$ U$ ~, @  B
  例:
1 m- `- q4 Y" x8 Y7 H7 S
+ T) T$ A9 v! Z  o- z5 E  unsigned char str1[]="I Love You";
, M' |, [0 z2 w: g$ K6 i3 v
. j( o! r* }4 i- m  int n[5];* n8 t  ~4 Z% z, L0 t

/ O& R6 }2 g3 O& e: K6 j  z' Q8 E  ifstream in("xxx.xxx");
6 P6 j9 F( f  ?& B
! n7 e; W3 R$ z/ _" G  ofstream out("yyy.yyy");
; {( I2 A0 e" c5 ^, ^
, F* A7 |# o  B0 b  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
5 m6 O7 I# s+ I5 z  ]. N
; x: ~' a5 k6 R: K$ G  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换2 i8 H* V" L1 R  S8 y% E/ h
0 c2 B  k1 i! i& V3 {4 {2 c
  in.close();out.close(); 四、检测EOF3 B$ h  [1 p: S3 p4 p
4 n# O" ]: v4 Z; F
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
8 E- _: P4 N, q2 n/ C: I& x: _7 N
& n: m! m% l. Q& S3 R  例:  if(in.eof()) ShowMessage("已经到达文件尾!");- P8 Q  @8 E/ v; t6 p7 [: z

: w8 [! \3 @/ g4 X' k  五、文件定位
* E  l& C) g9 h 0 }4 @: y' o5 U$ w' ]
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
8 i4 k" a  H+ i5 O* {3 w
! v3 d' f+ v- F" B  istream &seekg(streamoff offset,seek_dir origin);- J5 L, s6 s* R

5 V- d5 k6 `: P" B) m  ostream &seekp(streamoff offset,seek_dir origin);& G# S) j) V, o: X$ F5 |

7 I9 S8 l7 [) Z: J  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
5 [# S- z/ h0 t- D3 O% @! R5 r: A  @ 1 |. S$ ^. q. I+ n
  ios::beg:  文件开头
- G( C6 U/ s" r3 A% ~
7 X8 R$ d& m. h5 h% {  ios::cur:  文件当前位置0 `0 G. T# w$ [; Z- K, A, E+ [

6 c) o9 `+ [# k3 ^( s" L  ios::end:  文件结尾
+ v9 V4 v  I8 C0 E$ Q
3 E- i; G) i( w" A3 N  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
. v. `1 p9 T0 j, q0 Q7 Z1 W# F
  e2 E9 }, S; [7 {4 l; C  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
  C0 [$ ?0 W8 n+ N/ J" x
; m9 O4 @- ?" m+ b! u9 b  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

0 o$ l  y6 C) d! }' F
, L$ ?' Y/ K  R, u: V8 o
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了