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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;' c4 @7 h  T, j5 S' ~& v8 p" t/ ]

! l: ^( v4 ?  B0 z  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
5 R( t0 g6 X' _7 q, } + c+ Z6 u. \) p2 y2 ?. U
  1、插入器(<<). ]) B& s1 [$ R8 o$ i

# B) b9 c8 G- U7 p/ z" u  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。3 D! P5 \( O: K/ g& K6 ]5 n6 I

7 W+ x& D$ C/ e5 V8 }  2、析取器(>>)
, v' J! x1 L1 ?" D ' Y6 B: \+ I, o* {& ]
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。& M  P. `: \8 J. d; n

; V1 _7 J  S; \- {4 C1 u: v  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。8 t) T; p) h# F3 J$ d! c0 x8 C
6 Q) @; s& c: G- c7 N3 h
  一、打开文件
6 n( r% D% Z3 W$ h7 l, r   a4 h) ^4 G* w$ w0 M5 Z. O
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:% A( Q# U5 d- n- @9 ~. S. e
/ E8 G- W1 D7 B1 h
  void open(const char* filename,int mode,int access);参数:' Z3 e1 y' T4 ^& d

) l/ i4 K, f) e/ r; Y6 v4 L  filename:  要打开的文件名2 w, e" O2 g0 n$ I) \- ~( D

  e3 ]+ a; }5 C7 X7 @' G0 C, |% E  mode:    要打开文件的方式
; n) z/ `, P' S9 K) H
1 i& g& t- }$ R3 d& S2 ]& z) x  access:   打开文件的属性
: F: c; H/ r3 H: [. E- F4 B9 R# ]
5 t) o, B, D% ^  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:. v4 H2 g: Q& z: U& y( K
' P/ M& O' S8 d  ?* O: r) b
  ios::app:   以追加的方式打开文件
: x* B4 d' p$ v: l( E: L/ t" n + i2 D, y% N3 S) w& R7 }3 L0 O2 `& o4 p
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
) d; n% z* O( W1 j7 v7 k6 n : G4 g* h/ v% u" _
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
; c6 \2 d! m+ k- i$ g: ~- X
. j0 J7 \, d# k( @9 ?  ios::in:    文件以输入方式打开(文件数据输入到内存)
% M0 D0 d, p6 t% K+ K0 V3 Q 9 x9 v1 Q1 g- ~, E$ ?6 G: I  k
  ios::out:   文件以输出方式打开(内存数据输出到文件)3 n5 q' c9 w. c. h5 w& o

* Z' ]2 S- |, u# W+ e  ios::nocreate: 不建立文件,所以文件不存在时打开失败% l" B1 a. V* z& b6 b

- u6 H5 x9 k' z  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
- \5 Z+ `0 K+ [' K# M' L4 D& I- F ) Y8 X5 B4 O* y: v6 @. ]
  ios::trunc:  如果文件存在,把文件长度设为08 G$ Z4 q9 [3 \
& Y, y' @$ D) y9 i0 C
  可以用“或”把以上属性连接起来,如ios::out|ios::binary" |  Q# R9 L( w. h5 _

+ E  Z! _+ [" v! D# F  打开文件的属性取值是:
! ]9 t  S) v$ y8 l1 Z
* c1 @% [- O- J5 x) _6 N' c( A  0:普通文件,打开访问8 i$ q& B' q% H: A9 C2 x
' l& K8 z7 D, ]' P" Y
  1:只读文件
' u- e; X5 V- i! I% A& D 1 `; H, q1 V2 V) L+ ?% C
  2:隐含文件
- y  D- e5 m$ W# {6 A# e4 x- t
" L% V6 }  t8 _4 W  4:系统文件' g' N+ E9 Z/ n( v: a$ n# s& C1 s

7 l5 H  Q5 J% g$ b- h, m  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
6 d' L" ]0 G* D& |$ i ) W* G! {1 s6 t: j! E; \' O4 q
  例如:以二进制输入方式打开文件c:\config.sys
9 T" v# M+ g) |3 k7 O1 ^ + \% X- }. Z- y
  fstream file1;
  ]! N  T% J; W$ ^9 H  o( f- y 7 Q* G8 n. ?8 I) f+ T6 P- V
  file1.open("c:\\config.sys",ios::binary|ios::in,0);0 H8 Y5 N3 m+ }, a. j9 B2 f

' I/ w! Y8 f- Z$ T1 O  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
! I. H" v9 T) K
* Z1 J2 e: s0 d" P5 p4 ^* Q  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);8 K# L1 y# }; E1 U- t/ p/ ], I

# G7 H7 m( A6 H  W' i- g# ^* M6 H  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:% Z% [2 B  t( e& I
/ Q* e$ N' ~$ l8 W8 c
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
# ~8 G4 w1 V& `$ x% }0 t7 ~
+ {1 q# l! g/ Z- {5 f  ifstream file2("c:\\pdos.def");//以输入方式打开文件
+ ]' Y7 y# o( v" d6 F
* O9 R; P! m* O3 g# J  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。! ^% v: P/ n4 r1 p1 M" j6 U
& P3 i9 B. _( q" Z5 H; ?; q! D& r
  二、关闭文件
9 t. ~+ N. L: ~( H0 X, w
' J* r; I& N: Z  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。2 q* h& w. |# H2 ]9 u9 u

9 ]1 X1 k5 {) ~  u4 j2 ~  三、读写文件
$ m9 ?2 a  \+ G# n$ p, F: r' c ) f. z6 ?- J: Q7 B9 E$ O
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
# s$ b4 D0 s6 n3 s& W* q4 f 8 A6 k- P0 \7 X6 S0 ?* u
  1、文本文件的读写- L8 m4 q9 H6 W' w6 ~% O& ]
/ T$ R& R  a" H# O. }  \5 A
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:$ N% L7 O9 U4 s. K8 L. d) e
( D- [3 N% g! e' h
  file2<<"I Love You";//向文件写入字符串"I Love You"3 G/ H6 ~% ~$ i8 O
! I3 Z; g5 H9 }3 l
  int i;. x% H6 n: \8 ~  P; ?
" ]9 Q" Q  T9 j. M% {
  file1>>i;//从文件输入一个整数值。, n+ r, [$ n2 }* F
# u) ~- [' |1 ~- x
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些( R* H% Y3 ^% @1 @  n  e
3 t+ s& H( c. _8 o/ H
  操纵符 功能 输入/输出
! V  A+ d, V9 Z( X# b 6 l8 Y6 n2 q) h) Q0 H) q# I( _2 g! {4 v1 I
  dec 格式化为十进制数值数据 输入和输出
% M* t2 x: H; Z# W
6 E$ R& `4 v9 D& j% [# ]) G  _  endl 输出一个换行符并刷新此流 输出
3 a! }2 ~$ |# J: f" l : j2 m$ J, P/ U, V) o2 ?# @
  ends 输出一个空字符 输出
2 D2 C4 N! p1 O5 k ) E5 V5 D+ Y: g; u$ ], H
  hex 格式化为十六进制数值数据 输入和输出8 V7 H" x) A; ~# F/ M3 A' S
8 P; H/ f. Z% w
  oct 格式化为八进制数值数据 输入和输出
8 T' F! a' J7 j, |& O # d9 B( T/ J. s) `0 A, H
  setpxecision(int p) 设置浮点数的精度位数 输出/ a9 ^( ?0 [7 }; V$ d

2 @% s  J# G, Z  比如要把123当作十六进制输出:file1<

  Q9 g' ]7 J) j* I3 F8 a  2、二进制文件的读写
" c2 p3 o  q( |   F1 m2 }+ A+ \$ n3 Z
  ①put()  f" J1 C8 u. I# k6 R! G# C
. C, k( P( \9 G
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
5 Z( B2 ]. _/ p" \, G
7 F2 }  S! I5 n+ ]7 A) Q( x  ②get()  n& n( b. G* O" f6 O0 t
; C8 x! }* q4 y- F3 {, e3 n; `* N
  get()函数比较灵活,有3种常用的重载形式:4 Z# T1 a+ N9 ^2 D$ r2 k

9 t; |0 L4 r, E3 |: y1 s  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。. G4 ~9 C1 g( b! }* u8 k
" z1 D. w- x+ R" {; a
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。8 i5 ]& [7 p8 Y5 h- p

. ?) I# _- I# _% w5 Q4 Z: _  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:' f  p- C! b  R& t3 l

2 g5 b+ [) q' O+ M  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。0 r9 S" ^3 q0 i5 T7 k

* @4 q& b4 C/ p. z8 d/ J3 }  ③读写数据块
, N* e+ @/ A: U% w" a
/ M$ D3 B' J5 ~% t9 T- V  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:  i& S. J' c: b' c) L# W
! c/ v" k; X, P6 Z3 M: P/ Y( }
  read(unsigned char *buf,int num);8 ~1 }& |% G5 y
3 f- {3 u0 u+ h( Z$ k6 r. H
  write(const unsigned char *buf,int num);
3 K, ?1 B1 W, w1 H  N 1 `% m2 @3 Q/ Q% o5 `! M. O# w' {
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
3 g+ D* u/ B/ D
7 j* y5 o5 O' [+ K  例:0 l: P8 h# l" z# r# N, [9 ?

6 g- R  [7 s9 r6 e; m  unsigned char str1[]="I Love You";
2 p) G4 F" ^6 L+ @! m ( @  s2 g, o5 d( ]* l0 ~
  int n[5];
% p0 t6 r! e; ~2 M! ]
6 ^1 d2 G* v0 f  ifstream in("xxx.xxx");
7 l+ s6 Z0 N, O  ^* G9 y+ v; d- ]" u
1 I4 Q5 b* l  G# ]2 I0 Z. Y; D' W  D" e8 n  ofstream out("yyy.yyy");
# d1 R& @) N- g% G  O 8 m( f' r! Q# B
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中) C- _* n: l5 u+ i( {9 t5 E

5 ^: H' c2 j: I  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
7 W  x2 Z8 `) h8 g' q: h
4 o+ N1 F+ X+ ~$ `& S  in.close();out.close(); 四、检测EOF) n; ~8 n$ `  k: J9 O
5 n6 i& @# m" x8 q3 x9 d
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();! _  j( j% l  U# W4 _! O

5 J- _7 x0 |2 L) h  例:  if(in.eof()) ShowMessage("已经到达文件尾!");. N' b% v5 b: P4 m: p- J

4 J- b: s% u  V& A; b  五、文件定位9 j% n* u& g) l1 @
8 Z) u* v/ e# y+ \8 D
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:9 ^& `9 f$ Z7 W$ c" R

6 c& A6 X7 X* S- Y  a- F" w  istream &seekg(streamoff offset,seek_dir origin);
% Q8 X& q5 w' B" T 6 _/ Z& [) Z5 s8 N, V1 `, W! ?
  ostream &seekp(streamoff offset,seek_dir origin);7 P  D+ G9 w, S: M$ i0 v
+ ?) e8 ^6 s, y, `1 v
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
7 e' b) r7 O2 X. s# z) J: f
3 I0 F! O# O& T1 U7 f  ios::beg:  文件开头, q/ v5 q# J  d9 ?

+ k) K% |# _7 Q+ x1 g+ y1 S! c4 |  ios::cur:  文件当前位置" h. T! C9 r9 v7 E# ?! s: n- v' `

) L$ _5 A2 l, X! b$ ]  ios::end:  文件结尾5 _! g5 ^0 ]( Q& k+ {; S; @8 L$ u; C

# ]; M1 l5 P) U  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:1 Q. L% @9 ]; H; j' `8 {# g1 g
+ k) m) x9 Y: e4 r2 h  `% ?
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
. y. R- `/ d+ Y/ H 6 W' h' {, b( K4 m) L# Z" Q
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
0 N" S. @: Q  E! n. M6 t
& A0 M+ ?; Z1 B7 y- I8 B2 e9 T
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了