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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;4 E2 k4 k7 H4 A! G1 n( R/ [

% F7 [8 A) y& ?2 k9 k( g  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:! _2 ^6 i7 J) X  t! l
) ?9 w! y1 x& p$ N9 j- f4 J. P
  1、插入器(<<), q8 Z4 @# R2 m8 p$ n

0 x9 V! M" N2 h$ E6 S5 p2 `  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。6 |# F& @6 ~1 U, h

6 l& M7 @* H$ F  2、析取器(>>)1 w: `! z; @+ [" Y

, w, O+ N" t% V( T# w! p" Y; @6 A  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。2 Y  E0 y) c: n7 Y" `  p
# g* _+ X8 r+ U. U+ ~6 t  n* f6 ~
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。) ]. d3 o* b8 z; u6 S8 Z  S

: Y$ `2 T0 Q( Y. O2 v; L  一、打开文件
0 S  _6 H1 s+ ~; N* b6 i
% ?' `/ N9 N' ~& w  Z3 F  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:  R" s8 D- L2 Y+ B1 {
9 r' t  D6 f8 P
  void open(const char* filename,int mode,int access);参数:: x# e& o4 I2 [/ o$ N/ L# |+ C& P. S
9 O$ ?& R4 `; U/ w2 P
  filename:  要打开的文件名
: H$ y. K! _% ^- q" s+ ]
$ G- {* {7 }' g. k- A9 l. N# P8 l  mode:    要打开文件的方式8 X8 w4 t* U7 k, w  f1 D7 Z6 `
* S  u3 H" T3 r) h& B
  access:   打开文件的属性( f9 {( d: V. c, e
4 Q" p  ]0 J% z& L3 t$ z
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:5 j6 W: y  i9 A8 o9 O

0 }2 d" D0 |+ K; E1 u  ios::app:   以追加的方式打开文件
+ t/ [8 k6 s2 {0 d' p3 X ' T$ P. k7 H- P: e; _" e! V  b* u
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性# ^8 j* y+ f4 u2 @; y5 z! O

" a: f0 l: K" J, K  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
: B9 B6 l- F7 |' l
8 Q) i& h/ M0 H4 Q  C0 Y9 A) O  ios::in:    文件以输入方式打开(文件数据输入到内存)0 M; j% D, ]! w" d' w
" g  d' X* |- z& W, @
  ios::out:   文件以输出方式打开(内存数据输出到文件)
, y% w. I& T* _# ^
7 e& I' N* x) T8 K6 i( ]. k  ios::nocreate: 不建立文件,所以文件不存在时打开失败' ?2 b, W# f  L; y0 x

2 x' _9 z" B/ d4 k9 ~  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败' G: j  U6 ]3 ?
' m: k  v: @4 F, O! ]& w6 ~- Z
  ios::trunc:  如果文件存在,把文件长度设为0
7 H/ ?0 F6 n( J. A
- K1 ?% s) l/ {, t1 \; R  可以用“或”把以上属性连接起来,如ios::out|ios::binary
8 a( U; ~. D$ v3 O
) l! m1 W0 z9 A4 E. h% C$ `  打开文件的属性取值是:
9 u7 ]- T/ ]. j8 n& B4 \
$ t& B2 k2 \  D' `- w/ y. f  0:普通文件,打开访问
4 B$ \7 b* T& T( H( o7 g) X  d, ^
! N! t7 p# r: K7 k8 a& l# i4 _( w- x  1:只读文件- R5 k% M% X2 ?! O2 J  U. C

5 f9 b; F% p" n* Y6 u, v  2:隐含文件+ Z* I+ }6 B  \# Z+ N; Y, t

6 X* L- I2 E3 [& p# D  4:系统文件
- `9 o% }/ a: B6 L( g( j. D
/ O) G+ J# z% W& R/ n  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
+ [- x- e6 Q/ Z" } 6 y+ B) _, K9 S# d$ Z& X8 O( g4 W
  例如:以二进制输入方式打开文件c:\config.sys
# @' B: m! w3 H2 w 9 B( s; `) G" p: W! ]
  fstream file1;' C2 P8 I4 h$ i# D. |
8 H; k6 I7 m! l+ r, h$ ~6 `4 P
  file1.open("c:\\config.sys",ios::binary|ios::in,0);
  K; A% T0 Y8 q3 R# }4 j. W% ?9 [! a $ N& {9 a% o% ]/ p
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
" p6 a) w( S- f( B# x" o# N0 G; Z . a( p1 c, a' D
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
0 v2 g! f9 ^* s9 A2 F6 }# J: o3 ?
/ r' B; Z* s& [9 C7 J) W3 n  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:4 v3 |& n7 G) _: C/ d

3 x& y5 w# C: `4 N, S8 {; n5 S1 V* c  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。% G9 D+ W( M+ @5 h- |. U: n0 x
, J& I7 x/ M% B2 u7 M4 z/ j, i
  ifstream file2("c:\\pdos.def");//以输入方式打开文件8 Z9 Y, X: y' x/ T# q  d7 B
- }: k% c' s- [- ]
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。  ]1 d6 r5 g! A/ c( w; A! H7 S) {5 ^
& ~$ N1 e' ^7 H8 B
  二、关闭文件
1 v. E- e* }% W6 V- z4 ^. l) w
& R* {, l. `! A7 }% A" }  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
$ L) W) Q; y! Y6 ^
3 S% q/ T3 k. I* C  三、读写文件9 A6 e9 I, G) L' d

/ D3 s1 S% T5 k: Q" p  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
' b3 [- K! k  L1 A+ s' h . s0 }* x3 l  [* }% j
  1、文本文件的读写) `$ Q; T  n4 a, O3 P" \9 c. B4 Z

$ W5 e. V! N2 k5 V2 @2 ]+ `  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:2 C: o% g, g) K( M$ o: L

1 y, T* n+ J- M3 q3 s, b  file2<<"I Love You";//向文件写入字符串"I Love You") T4 }9 d" g+ u# ]3 O

0 N, n5 W; t. \" _( r9 Z# ~  int i;, v3 o0 j8 T: R
7 @1 Y: Q2 x$ R" D: j
  file1>>i;//从文件输入一个整数值。7 a  P6 k: `# n% @! N
4 H2 |1 \7 n) I3 e9 H4 O% T
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些& @3 c8 X; e) g& e
! {* m2 n; q5 n' d& S6 F
  操纵符 功能 输入/输出4 Y  Y6 n5 q- i& M. q4 Y2 Z9 T
* `* [( t" O# [% v5 @
  dec 格式化为十进制数值数据 输入和输出
$ l' h) M3 h) J! x% w
/ L* b4 W/ t; _) j# b) m3 x  endl 输出一个换行符并刷新此流 输出
. A0 i% t& Z* K! Y$ n; v 9 O: T! Y+ I7 \6 ^7 k$ v1 u
  ends 输出一个空字符 输出
: U8 L5 A5 ~/ K# e( z0 ?. A" _3 U 3 e3 j8 g! Z3 C# z- e
  hex 格式化为十六进制数值数据 输入和输出/ f3 O; y: R1 `! r& T
  m; @( a& S  Z- q
  oct 格式化为八进制数值数据 输入和输出/ U0 A# S  {7 H  Y
2 ]5 z+ Z' Z) S" x
  setpxecision(int p) 设置浮点数的精度位数 输出- _& o3 x% c: e
, |/ y4 J" q/ M, U
  比如要把123当作十六进制输出:file1<

; t" J" I0 E5 X! L  2、二进制文件的读写) [# B: {& o7 [) g8 H! y

) Y: d/ V/ f# Z5 v1 t  ①put()
# e( ^3 i" [8 P- _+ _5 j( U7 E % X( T8 Y4 d2 _% |* Z
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
/ i: H2 I4 h/ Z# K5 b : |: ^; L6 v  m
  ②get()" g; G9 S! i  W% j. i

; b0 k) X( y7 P& X( a9 g6 y" H% x  get()函数比较灵活,有3种常用的重载形式:
9 \9 e. p) K( f5 W1 T, E 0 |. v3 d# Y3 A, m" B
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。5 `% u& I! F2 e5 r4 a7 O8 U, H# g
. W& k7 X0 f& `6 V6 i$ _
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。; b6 O% ?4 y8 `% H

' t3 G' {6 H' B( \# J1 P+ d  b  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:8 r7 q! o- F0 ?5 A* b1 f* `

! u+ W' l- h  y/ \+ {# N' H2 @  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
# N" S% J/ c* B- [0 s: G; H% z
9 Z9 I& u' ?' j  ③读写数据块
/ Q0 _0 Z& L8 { 9 v( h; M5 j* d) u! p
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
5 }- O5 a1 W0 r 3 P) W$ t2 a7 H+ B
  read(unsigned char *buf,int num);/ y% ?9 S7 n+ ]

  P; d" q. Z: o  write(const unsigned char *buf,int num);
7 V( q! U6 I# _: k * K3 b- D7 ^, K" i5 [0 q: Y
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
. U, s1 X) t2 k: | / \  y# F7 B( |5 O* E
  例:
) k5 r* G- R' p, V$ n0 ?, M
( t, v5 I6 h8 ]0 F- M% ~  unsigned char str1[]="I Love You";
+ P; J# V+ ~$ f9 _/ L
- V4 t) [; B" L& B  int n[5];
7 d; d% p6 M7 A0 t+ N
+ U1 D. ], [9 U) h  ifstream in("xxx.xxx");
2 |  M- e8 X& _! c! {4 b
9 x, ^0 Q" B- k! |+ P; c  ofstream out("yyy.yyy");
. N6 ?2 ?! x3 y2 \ 2 o9 {  W. I# a. ^# g
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
. i% N  L3 N) z3 S# N 7 A/ q" E" z0 s$ F* l
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
5 ^- J6 T- {$ z% A, [5 a5 d( N7 J
0 d8 |3 p; ?# B1 C4 y% y) h  in.close();out.close(); 四、检测EOF
  R% |0 L' q! h5 T! I7 p: K
3 {0 j; [; I/ L: }5 k/ ~: q  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();- n$ t/ Q2 e$ q0 K% p2 Z  K
5 b' f3 h) I% l' I- w/ Y& Y- |
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");: l- _# p  v) V; H! K
3 t! w1 Y2 X4 Y
  五、文件定位- N) m, X- @" F2 D1 c9 V

$ O, h3 F# v/ ~, w+ G& J- a  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
+ d6 z4 D, V, e  [: Y' g
# C) b1 B2 _7 Q  istream &seekg(streamoff offset,seek_dir origin);
7 p* Y7 w' n8 r. @# L( y# d% l
3 R1 T" f& H; O# \4 B  f+ {, Q  ostream &seekp(streamoff offset,seek_dir origin);
1 A/ M; P2 W' Y$ K4 k+ ~/ X  n6 W& E 1 v. [5 D) U! }
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:+ H) D, G7 t  l

3 ?. S6 ?- o* ^# ~6 I  ios::beg:  文件开头
' U$ W$ u" t/ j
  D( T; A' t/ P0 \- A+ D) g( S  ios::cur:  文件当前位置4 w+ d0 o) U+ L& u
3 d+ d6 L' G" Z6 Y: m9 o+ R
  ios::end:  文件结尾
1 |8 r* ^3 B5 [" y1 h   ]2 R0 k" @$ K( P
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:! T" Y2 U4 Q! U7 d
; k' a7 n* ?* V
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节, O; ?9 `2 L! E( B: Z9 |
, N; D. }* p: f% Z
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

% H/ e" @: C% d, F4 P' Z/ q
1 N7 }7 t! G+ y- L
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了