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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;# o# b0 \& d+ h  [& }
5 t  f7 t( @7 i- Q. B; ?0 G, l
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:# j6 {. }, M& }% ?. E

6 n$ t1 d3 W: o" g! c- U  1、插入器(<<)4 o* P! h' z- q/ `. E
* n9 g" Z- z$ U6 b" Y/ ^
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
. L+ ~/ Y0 d: j% K3 R4 o " U" o% x; G4 p. m) ]# ~4 t
  2、析取器(>>)
- c! P4 E  ?6 Y+ q6 N: J
  k4 M0 x4 u. G$ w8 d3 U) e1 q  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
! o6 e. h2 n1 B, ^2 z* Z
6 Y2 i4 @' F# t4 T9 V& l3 u  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。6 {; S. H- f5 b$ Y, ]( x
* n& ?& G( A! y/ o$ Y8 k
  一、打开文件
# t* w& o9 L' T/ F) e( A& S, z ) ~; R' @3 @( }0 k( W# ^
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:( Z: i% \6 G  ]* O7 Q, n; t9 g

& _2 l1 E. Y4 z  void open(const char* filename,int mode,int access);参数:  [. v3 {* N' p
6 {1 N$ }5 Z& }8 k7 w& H
  filename:  要打开的文件名
1 ]# y% p1 |+ c
# J' v, L5 D  s( W/ W  mode:    要打开文件的方式/ ]0 V* L  M1 L

% B/ C. ?$ j( A1 i  access:   打开文件的属性0 T  t8 i) {. E8 l$ {" z
1 |9 b% M* ?! B/ c6 c2 m; H
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:( a! Z  b+ e  c# b7 G1 h6 f; [

& d+ K7 _& x/ M# b) y* h; z1 {) a  ios::app:   以追加的方式打开文件
9 E" {* {8 A& v/ ^& S* ^1 Y) \ 7 {8 m' D% i( ^: w$ W- X+ k
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
) |6 e! p% O3 @9 d" C, M
, W/ b& T% o# }; G  M, K3 H0 B  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
1 m: x& \$ U" f! q; P
; M( ]. Y7 A) X( K' V$ A  t( A! L  ios::in:    文件以输入方式打开(文件数据输入到内存); h9 T: ^3 K2 u# V4 s

! R9 H: A" O9 w. k  ios::out:   文件以输出方式打开(内存数据输出到文件)
" `! {! b! j) L5 K
; g* L2 a6 y, P( {% e4 Y5 {3 g6 R  ios::nocreate: 不建立文件,所以文件不存在时打开失败. _8 [1 ?1 r* m2 L9 \. @
3 s$ b7 J8 o! B( R3 p- e
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
7 r% S2 R/ K" b# z' C* t$ ~$ R : z' {3 a) J$ B1 p' I0 h1 {
  ios::trunc:  如果文件存在,把文件长度设为0
. M* Y" m* y6 D2 h& o8 l
1 `0 A5 I3 n" A1 ?5 [3 d  可以用“或”把以上属性连接起来,如ios::out|ios::binary9 O! i) w7 N8 [0 q/ W1 E; O

' V5 L, B% a9 X. M' i3 r9 S8 z  打开文件的属性取值是:! b4 N  e1 D2 G+ `) R

- ]0 W# V/ J8 F  0:普通文件,打开访问- D1 W1 n& d8 d+ N
/ F4 o  N9 C" D0 p: a' X
  1:只读文件# H9 z0 q/ i3 w% T; }8 [# ]

9 _  ~: L1 q% n8 I  2:隐含文件
, z7 X9 R( c5 D, P3 f1 \
' T$ P* B0 F  F% v  4:系统文件
) t$ p7 k$ D( O# q: E8 s- Y8 P$ N 5 E  x3 ]# o) m# Y7 R
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
6 K* S# g" K) u) ?6 M 2 B! X+ q! m# n0 |+ v- ~5 Z
  例如:以二进制输入方式打开文件c:\config.sys9 @; i+ h- ^1 {

, {, _5 D+ }. ]( {: Q" N  fstream file1;, P. @7 n- O9 N. X! V$ a# c

" k2 J/ ?0 y7 Z  file1.open("c:\\config.sys",ios::binary|ios::in,0);
& [: y9 [! u. N& ?1 o
1 g' u5 R! f: E4 N) i* W# f  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:: R  }3 c( b( h, h# e, y5 q

! F" }- x/ ]; L/ M# V! r+ g: R$ r  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);+ ]( s) o. V8 v" r! L

* e7 K; Y- u0 k8 S5 T! n' e$ G; M) X  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
& a% Q+ a' M0 x& Q) n+ x7 N; s - f6 }! I+ u! Q& W% r1 Z
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
+ i  d9 D# J! Y* c* l- u1 {+ H 8 K) O- `8 N, Z5 O2 S& e, @
  ifstream file2("c:\\pdos.def");//以输入方式打开文件( u8 t/ ~2 f+ A8 K0 }
9 K; D9 G  k' {+ M" T  M* O3 e+ y9 f9 H+ P
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。% L/ ^/ I5 \, X4 ~+ P7 `3 y

- f2 t2 q8 f0 k( H$ D- U1 W  二、关闭文件
% }( N) m: ]8 ]! }3 t4 ~ ; s( F- N0 D" {% f+ Z1 B+ d- H
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。. H5 Y) o7 f5 O
' c1 E. d! c5 m, M
  三、读写文件! d1 [" D7 _0 N; I9 q# U9 g6 S
9 |( s. Q9 P. [+ u9 T
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式* f; X5 l5 b% R0 [

' Q$ r( w" R' K8 e3 }& T" ?  1、文本文件的读写
5 B* g! E4 Q$ s+ S- y 8 h$ v4 r4 W  V' T2 R6 g, L% G" W/ A
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:5 Q0 X2 U- p+ V5 r: Z, Q( u
. f! Z. V/ I7 s$ F
  file2<<"I Love You";//向文件写入字符串"I Love You"9 J( E* Q5 a$ Y5 g

8 L7 B. q/ r0 H/ W* Q$ l  int i;8 {( ]- N9 j* _. J

6 a- w+ X! z! G6 d6 Q4 Y# G2 I  file1>>i;//从文件输入一个整数值。* v9 t1 p! I* p+ P
! N+ R' g' l% g; h& `/ I
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些& g% d5 o* i& @  D' {
6 u5 q/ W: d* M' C  t
  操纵符 功能 输入/输出
, n0 P# V# y' [3 I9 z
0 A' w+ Q4 _, ^; o  dec 格式化为十进制数值数据 输入和输出
5 w: ]; R5 z- u6 E$ p3 E + A: @. P5 N/ \( s* j
  endl 输出一个换行符并刷新此流 输出4 ^9 L0 d- A# l' _
: L. K. R1 J5 D' [% N6 M
  ends 输出一个空字符 输出
4 `3 h& p2 a* n' S
# z' S5 a$ Z9 t  }6 C  hex 格式化为十六进制数值数据 输入和输出
1 ~9 V- S" t# M/ V: i; t+ Z; w; U
1 ~! g: M+ Y; F; I2 n  oct 格式化为八进制数值数据 输入和输出
" K3 U" v* N- x9 a9 q* N
8 T" ?- P- \$ u7 `  setpxecision(int p) 设置浮点数的精度位数 输出' B% B9 w, o; |2 [0 n; [# |9 g
/ X+ n; ]$ N4 y; m' l# n* `" M- T
  比如要把123当作十六进制输出:file1<

( E# k7 B# w  a* b6 {  d  2、二进制文件的读写
* q8 ~' \9 U+ v% U / c5 K0 K  a% v5 t- A! ^
  ①put()1 r/ m7 j5 |+ }

1 }" @, l/ w, H% x! n2 x8 a! w8 `  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
+ k; s! Y' d6 j/ ]# Z5 |$ L- Y3 {. U 9 s& g3 N( B- K' C6 W4 [
  ②get()& q8 N  Y: _- |

/ ^2 W. `( Q; e1 M+ t; }  g6 e; d3 Z  get()函数比较灵活,有3种常用的重载形式:" R+ r; q& q8 h
  j0 q  |. }2 _  W* R2 i- q4 g: r; a
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
( r7 R# j8 k' k2 U8 x# g& H 8 u" q/ h3 u) }( j, F0 O2 W
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。8 P4 L' a9 _3 h
8 Q% \8 R1 K  q; ~7 ~
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
* ~' I: t* E6 X# j
! b: T' l) r7 h. V% @2 A  p  [$ O  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
; q% i& S% L: _! }3 A6 I2 l : T, T0 j. \& Y9 i6 Z
  ③读写数据块' R- }7 l' I7 a

3 p0 Z9 W" A/ V( D$ o0 j3 q  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
; H2 ~$ h/ [/ M/ `3 R, n & F) V) A: r5 \7 e' P7 @' Y
  read(unsigned char *buf,int num);
- A5 `; v# H- S5 J
3 d7 U9 z1 q+ q& f/ w* N  write(const unsigned char *buf,int num);5 s$ f  ], l4 V
3 ?$ j8 u% R' @* F7 s1 U7 O+ |4 S4 ?8 J
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。  P3 m* m  F* }# A/ P2 g
; R# ]; N: \% H3 `, B5 \& s
  例:
4 g' _) ~! P. e' j 9 S+ f- s  g6 U0 l2 @
  unsigned char str1[]="I Love You";& x3 ^! x* ~- x$ _

6 v& B- d7 K6 d  int n[5];8 k# K4 V) p- H

( A4 \; D( d, o% o  ifstream in("xxx.xxx");
) o, n" ]1 O, u9 s/ W5 V2 r4 u
2 {3 [& s( Z% {9 }8 x  ofstream out("yyy.yyy");
2 z/ V3 F) J7 \0 ^9 }/ r% P( A9 _; n , w$ g0 T2 O# S
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
) G$ w' Y7 f$ U4 u* Q) O
( C3 ~, X  F' @8 ~: j  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
1 z, x& P* h5 Z3 g& h6 u$ j- s
5 J' Y1 J+ z  y& L" I( |  in.close();out.close(); 四、检测EOF9 n9 G4 U6 _8 O" ^! m8 B  q4 j) F
- ~9 y( _4 p2 I
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
+ M# L$ e" v- v6 J9 R# J  C9 {
3 [$ X; r4 c4 d, m. [  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
( B6 A& |- U: Q' c
0 d2 D/ \- }% @( `9 S( \7 z  五、文件定位- b" g7 b" r2 h) @5 t# {

) R' b# g$ q6 D. p! c  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
; Y6 Q6 i$ U5 T( V9 t) P 9 t5 r7 G7 ~# n( s% t% p
  istream &seekg(streamoff offset,seek_dir origin);  ^6 R9 h# Z* ^7 c$ j; G! O* P
. Y2 X) H$ ?7 x, u( S
  ostream &seekp(streamoff offset,seek_dir origin);
6 J% R; B+ M3 N- a5 o, X% m  O
1 ]4 N  a2 a, t7 S+ P! G: f  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:' Y9 m6 o8 L0 u) _3 }

) J2 @6 ?  b6 @0 U2 t, [  ios::beg:  文件开头7 w+ E5 m5 C' n
! E: m  c% b2 b% f
  ios::cur:  文件当前位置
9 b; M0 m9 ~) A5 |
, y2 H  r. v; s0 ], A  ios::end:  文件结尾
2 O: g- j" c- J* o8 ? 6 X4 d5 r7 \/ Y/ ?7 V! L0 `* T; g
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:( ^) t+ s( Z  E; o/ l

- S  i6 D. L. Q. n  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
0 N8 k. {1 K' I9 ]
( X! r0 L. b2 Z. w4 b  S0 N  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

7 S5 {9 `; I4 i# s+ d0 M0 |" b6 _/ B5 c8 x: T
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.diantuankj.com/ doTeam.tech
回复

使用道具 举报

发表回复

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

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

    本网站(plmhome.com)为PLM之家工业软件学习官网站

    展示的视频材料全部免费,需要高清和特殊技术支持请联系 QQ: 939801026

    PLM之家NX CAM二次开发专题模块培训报名开始啦

    我知道了