PLM之家PLMHome-国产软件践行者

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;. t" ?$ X1 N, S* q5 Z/ Z

' D* n& H1 f. k  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:9 Y% O' T6 V! u: G3 e
! o0 |& G2 i8 G. s" ]; U
  1、插入器(<<)
  ?& `" s+ f5 \  c  O6 d) h+ }
# |$ e6 o2 u0 o5 S4 w+ Y/ d  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。5 T7 c8 O  O& L  ]1 i/ ?% Y- A
9 V7 S$ h' J8 w$ D- A/ V
  2、析取器(>>)  Y# S  y$ O8 ]
7 i& l( {  f' _8 H  C
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。. i. k0 F6 u% }
- P4 M( }" g( h
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。1 w; P4 c0 T( r  t' t9 t

% W% }. f  D, {% F0 ]$ |0 a" Z  一、打开文件, }9 ^  u/ i7 K* ?  h1 z

  V7 ^3 k$ y, R7 t8 h, r( n  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:5 A. G- [( Y2 l

9 Q6 f/ Q& d5 {. Q) F6 H  void open(const char* filename,int mode,int access);参数:
! ^7 s+ _+ ?- _ 7 ]8 m4 z: L! D2 G' W; |+ N+ i0 K
  filename:  要打开的文件名
$ @# S2 u! P9 T. n- ~$ I$ V) @ $ b- c0 @- v% S: i7 Y
  mode:    要打开文件的方式5 u: t; w) {& k/ L! T& `$ |7 [

, i! u  ]  t$ M0 o+ n# p8 P  access:   打开文件的属性, y4 d7 W! y9 |* a6 X

2 Z, f3 O) w" c- v7 }: t0 z  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:4 A1 P2 [% w5 i& S( \% @3 y
. [# F3 D2 S- K$ ^
  ios::app:   以追加的方式打开文件; B% D4 ^9 U9 r# m! U; }

. K# ~1 J1 R1 \* L" Z  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
) l7 |( Q! \6 H4 y' z
8 n; u9 o  d( o/ M5 h  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文4 h6 [  ], J! Q' t3 C  o& e

  z. ], X# P8 Z/ D# i5 d  ios::in:    文件以输入方式打开(文件数据输入到内存)
- E; L; d. o, v6 K$ j0 L! Y3 z/ D  N . Q' C7 {4 ~" @$ q+ [2 s0 O
  ios::out:   文件以输出方式打开(内存数据输出到文件), `( D8 _( b- w
% f& l( r. t8 U, N( `1 x
  ios::nocreate: 不建立文件,所以文件不存在时打开失败
, g3 V# W( _3 D1 f8 Y/ | + _* T3 e1 |' e2 l7 e, S
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
' e; i1 }+ y4 B/ s0 R: o 3 _  R6 ~, [# B. d
  ios::trunc:  如果文件存在,把文件长度设为0
- H1 w2 s8 ^4 D& U  K; h- ?% K0 b9 D 4 N: G/ O7 p9 W/ I# Z
  可以用“或”把以上属性连接起来,如ios::out|ios::binary
8 t  W3 Q# w$ H: d4 ]- ]; r ' @( h1 X  {/ d3 a* A3 N; \
  打开文件的属性取值是:
7 V7 \/ ^6 E& Y! L3 o/ _: ]5 D # e/ Q& ]  \3 B( @/ l, M& C0 b
  0:普通文件,打开访问5 `8 _5 V) ~' v4 u# Y

9 z+ K4 W: S7 I+ s4 w" L6 p+ k) R  1:只读文件
" o. u+ ?1 L1 d - h& u! O( }% B: ]# f4 }0 B
  2:隐含文件
& L) Y& c8 m7 w' i 3 v9 L7 j( e$ M: C4 F- Z
  4:系统文件$ ?# L1 \( f# u$ r3 @, r

9 @8 [2 Z5 H: c6 ?1 [0 b: o2 V  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。7 G0 s& I4 w. }2 X  g5 ^6 i8 H: d

$ f3 I5 u: c( d% n3 U  例如:以二进制输入方式打开文件c:\config.sys
1 E0 |# _! O/ e! M' K4 s
# o& C2 L" O! T* L9 z& R  fstream file1;
' |6 j, W! F3 ]9 y0 e# o
1 f, q- |  t* h5 |0 j% i# q- t  file1.open("c:\\config.sys",ios::binary|ios::in,0);
6 O3 }6 N7 K! w+ I9 j0 o4 G! A ! c8 b; z! D. o* W- W  m# j
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:  |; s& h" ]" E" _
! h. @7 l9 X9 _1 p
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);$ c: @7 ^1 R5 m; E

* Q4 j$ r+ q$ b  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:1 o! v. J! h* x, L5 t5 Q% g2 R4 q& a

0 U! j, {8 Q+ {  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。0 {( k; m" {2 B0 i

3 L! e6 H) b9 i: q! v; }  O  ifstream file2("c:\\pdos.def");//以输入方式打开文件
$ w! n" q  M8 z " |( }( e7 t4 H- Z$ q
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。4 E9 \) S4 ~( L

/ j: ~4 T! c. E# t7 h9 j3 e  二、关闭文件& o( ?  n0 S/ s6 z; V  k
! p1 j& s8 v' M& \- [5 n( b8 i' n5 _
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。7 `' p" P, d* p

, K9 E: }7 Y( a* j) i; B  三、读写文件
# M, x& S# {; W& v 9 B5 P8 K- x' r7 f
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
( @2 b. V; c; X$ x6 M& L . ?7 n/ }( J4 i- b
  1、文本文件的读写* \* g: y+ u0 p

  w0 d6 H/ O/ r) w& J  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:/ e% y- f- N# r: w0 Z5 V  h

1 b' L4 b! O1 C3 r7 ^( f. [  file2<<"I Love You";//向文件写入字符串"I Love You"
" P* t. _: p& ]" @5 P
& o7 x4 \. l5 F2 r/ I' h' ?  int i;
' }+ _6 R# |* s( e4 M
* a7 I8 l, Y# g9 C! N, m7 J  file1>>i;//从文件输入一个整数值。* M9 h7 V6 L1 b, i& g9 ]) ^7 y
9 s9 R! U; Q& \
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
) j) N+ x. E' Z; R
: u% T0 |, F1 f5 e' H1 s' D( p3 o* |  操纵符 功能 输入/输出
- W- L- ]6 \; c& p  m& g
) c0 a1 |- Q4 n- @  dec 格式化为十进制数值数据 输入和输出: d5 P- z2 Y( ?
8 E. Q4 T4 h+ M4 D. O1 a
  endl 输出一个换行符并刷新此流 输出
8 b. \+ a8 G" ]# O- B0 _7 m - w$ O0 S& K; `
  ends 输出一个空字符 输出
/ L( T- Z* K3 ]
/ ?3 g4 y8 ~- X/ N) |! {) l+ W  hex 格式化为十六进制数值数据 输入和输出
9 M1 s8 W5 I) k0 J1 i0 W
) n( p( I. [7 G( p( K  oct 格式化为八进制数值数据 输入和输出
7 K% T4 R) d8 j2 |/ l9 U4 r5 ^  ? 9 J8 n/ `& \8 X8 c0 j6 y; D
  setpxecision(int p) 设置浮点数的精度位数 输出% r) Y% X6 {% f) B

1 L$ a4 L8 k  Z9 w4 s# [& }  比如要把123当作十六进制输出:file1<
1 P) y8 W8 l6 O0 C  p6 a& I3 N
  2、二进制文件的读写
$ i. ?' @: m4 a+ c. j! q& b 0 e1 ~( @5 I7 ~5 V, ?0 D
  ①put()
% O& a1 n2 `2 e; o 6 W4 J" o/ ^0 x% b' r5 ^7 F$ l" A
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。' X) d; A# D# ^7 A
" D* r0 C6 ^! d6 x
  ②get()
0 y- Y4 V$ |2 p2 Z: C . x; B7 c! `6 G; o8 u) `
  get()函数比较灵活,有3种常用的重载形式:6 x. x' K, S/ g
0 f5 c0 j( c2 ]; Z* l* m0 h
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。8 a, G2 E. X& Z% c5 Y' c9 l

  w; t4 X* d1 ~1 A! m  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。" W+ f/ I& P3 D4 o' o
, X7 N3 V7 C. |3 g4 P6 L2 {
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
" c3 `; }" `. h2 ^. Z5 L " S% m3 _$ Q5 i5 h. Y: J4 G& F
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。2 V  F& x9 Z% Z$ a, K- I- Z7 G: i& i

& x4 x/ \; q& t& m$ [! j  ③读写数据块+ N0 r7 l4 h7 k( |1 q% G) L) Z

9 `6 d, I/ X7 K  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:/ r# s  Q; H) B6 H

. {$ e' {# D% i, a' K' p1 ]  read(unsigned char *buf,int num);
; _9 {/ W1 ~# d9 L6 {9 `/ ^ 7 p0 g* e1 f; o7 W
  write(const unsigned char *buf,int num);/ M- K5 S1 ]* ~9 E+ u/ L1 j2 m4 G/ n
7 o5 Z0 T2 f: N. w2 z+ e
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
3 i0 d  O$ a9 j , \: Q! X0 {( o
  例:
) h8 P5 q+ F) t+ X' R! s
( a5 F- T- O; K0 u) [  unsigned char str1[]="I Love You";0 {" ?; p. M0 K! ~

1 Z/ ~# e% L# Z! y  int n[5];
5 v) b- C, z- j7 \' R6 }# B0 Q
9 e4 B0 T2 l( J  m! G' M# r  ifstream in("xxx.xxx");1 s9 A- h# ^2 ?
0 S) g$ V8 B9 e8 b6 m  B! y( r; Y
  ofstream out("yyy.yyy");& l! \9 T$ o  \3 }- o

( g7 Z  H% \& T% T  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中' f' Q2 C! m" M: j; c

5 y$ ^7 v7 J' z  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
& |9 h: J; y( ?! X( b2 ?
  T0 }. p9 t) z1 ~5 c  in.close();out.close(); 四、检测EOF' }4 o+ t/ d) n/ M6 g
. f  z$ ~0 w/ Y
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();" G  w& M1 q" P+ ]' p
+ G) L$ q& {+ ^6 t; {8 w
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");6 x/ O1 A0 K) N8 e! ^% X9 F& J
7 u  ^' A+ F' b
  五、文件定位
; v8 q4 [6 K9 i . A. }7 R+ [9 t5 ^7 E0 D: ~
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
) U, E7 D& r3 [$ [# ]( u& C! N
! M4 ~! v1 E4 F' B( |1 \/ g. B  istream &seekg(streamoff offset,seek_dir origin);
; Z% D* G, ^3 w1 ^7 R' l : w% }- L" c5 _
  ostream &seekp(streamoff offset,seek_dir origin);2 j: _. G  {0 x9 G6 W8 u+ g$ w

' S' Q) k7 H" Y5 N% G! g! c# N  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
* A+ ~( K) y0 o: s' ? 4 f2 T1 r- L% r( G
  ios::beg:  文件开头/ N- J9 G7 _2 w7 R, W3 }+ G, c! _7 C
5 E/ J9 i6 ]' t( n$ H9 B5 k' ]
  ios::cur:  文件当前位置
* N! w# G; O% I7 Z& R, S% | * X3 I$ [" C! i
  ios::end:  文件结尾5 C2 h+ f/ \; C, P
5 w8 p$ z8 m$ N- A- J! s
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:/ f# G& h6 {0 A% w
. c8 {+ _. g8 \  j( s
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
& ^1 ]7 t0 Z; G1 W" I7 j& X' r  U
/ ~, j/ J- t6 Y7 `- n  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
0 u! I/ L. k+ {1 x& A0 }# y9 Z
/ b! u6 U8 w' }# S( r9 }- ^
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了