PLM之家PLMHome-工业软件与AI结合践行者

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;/ R6 D3 J( f* E5 |- p$ N) Q

) p: X+ ^! s% n* ]1 q" l' |( i  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
3 n& H4 w; F5 |4 R* }/ G2 H! M
. G/ ?( Z8 [$ T8 i3 `  1、插入器(<<)& K8 K7 l4 }# A3 L- i
! `9 z9 ?+ s$ a; E! ]# E- L9 F/ g
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。" d) H* O4 g: g: E

5 u0 ?/ h' ^' V. `$ r8 u9 ?  2、析取器(>>)) t5 Q% g; t, F! b7 H$ F* d9 O. Y

  G: r8 x9 b# E7 ]! W  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
0 u! A+ y' F) Q) D/ C# o, s' n& N * j% L  K+ d" K* ]  C
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
% e1 A; Q- h; r
/ w3 E! }& Y6 F$ A  一、打开文件( Q1 S% J$ n6 @# K5 T
/ y' `; a$ \& B* P' W
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:
, @* d" u  m  q7 m. k
6 j" G5 t1 ?) [& Q& B8 k- d  void open(const char* filename,int mode,int access);参数:
  ]. ~  ]/ _9 g9 A) i
* P; \- ^* O3 H* @2 l  G  filename:  要打开的文件名7 e" L2 Z& X- X+ h3 f. ~
/ c4 X, j, j4 I# _/ c
  mode:    要打开文件的方式! r2 s3 q% i, ~0 N8 Q3 K( s4 h
  v" Y; v* W- ?, f+ e
  access:   打开文件的属性
5 H; T8 A) o) G* P- h6 | ; B  X  j9 S" X1 f" b
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:# \# a7 e: v2 S/ N: ?; u# `. y$ c

* Z, V" e4 Q! @$ e  ios::app:   以追加的方式打开文件
3 ?1 h: y  Y, Q9 f; \: p# y) m" h
. r- c0 h* z+ l* g) z  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性. I  k2 g7 P  @+ U: L

, Y1 ?) J; h) O' m/ o  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
1 Y6 K* [8 S+ E5 E & t8 n1 f/ f- B6 s6 D
  ios::in:    文件以输入方式打开(文件数据输入到内存)
. w  i& o2 m+ f& G- Z
2 s) ?- H0 C+ _5 C% e  ios::out:   文件以输出方式打开(内存数据输出到文件)
0 {& p4 P( Z& T& L( k1 ] 7 n! v. e# ~: l* l1 [+ L
  ios::nocreate: 不建立文件,所以文件不存在时打开失败
  n% b* u# J1 Y, D; u8 V: R; ?$ a
4 _# u* L% i  m& J  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
& V& o& }7 e" \1 H- L ' a! M5 G$ i! P9 N' B* O! N
  ios::trunc:  如果文件存在,把文件长度设为0
! p5 H, M  {  k  P  K' r4 i , X2 m) j" G. A0 _! M
  可以用“或”把以上属性连接起来,如ios::out|ios::binary, ]0 s& _) ^" ^- j1 B2 n$ f

* b' B; @7 T5 r3 P5 e  打开文件的属性取值是:5 [5 ?, \, s# l5 U9 Z& w
9 `) I% [, D$ \' I3 Y
  0:普通文件,打开访问  }) L! s8 K; n

8 u3 ]) t& \6 M5 v3 ?4 ^  1:只读文件
+ w$ z! S3 W5 \. @2 Y- Q ; q3 s! X) }* _5 m+ _: ]# o/ {0 X
  2:隐含文件4 f  |8 c  E: F4 @# h) f2 Y

5 }# @+ h5 x  [7 u0 U. ^0 l  4:系统文件, z" O8 Z4 p3 f6 [
( X# e6 m4 m+ ~- k# }4 V( j
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。& }+ ^# @7 s. S9 j

/ G  U- g( ~- q. L1 G* z6 T  例如:以二进制输入方式打开文件c:\config.sys' K( P8 p: L% a, G/ X; Y, d. y) i' o3 a

& m9 L' ]# K% g. U  fstream file1;
6 l0 p/ n$ s; [7 Y! c6 X 9 l' a2 w  t: ]0 n3 K
  file1.open("c:\\config.sys",ios::binary|ios::in,0);
% y# S7 T9 M* j- T, u$ L - ]4 S+ e5 K& u4 I0 }, b0 ?  Z
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:( }# G/ J9 H. _4 q7 _- |# \
% ^' \- g3 W: M
  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);. O3 G- R6 }  Z$ |& d0 y

6 R* J* p, Y$ H" f- C  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:) O+ P6 r8 S, T5 Z. w8 @- V5 W1 l

5 k) I5 C1 S+ D3 z) y  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
: l* M; v  H4 p, Z0 k' S
6 r3 y. [8 ~  H, d% T/ g  ifstream file2("c:\\pdos.def");//以输入方式打开文件* P) T# s  v. R* O5 ?

$ D) H: z( ~/ s+ @9 u  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。7 u& W0 o; }5 \/ K; _

8 b1 ^) x/ \$ r  二、关闭文件
5 s; S8 L! ?/ q1 K7 a( f
2 E6 Q/ \: c1 m2 G; P, Q( |  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
: g' g8 `% g1 [: S3 }6 j 2 y+ X; r' d- m% T# _# N- d5 V
  三、读写文件7 n* _5 A1 n( c& A1 K
& a3 T& Y. `3 a/ F8 _6 f: r9 @
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
  E  q8 {8 B1 M# v+ L. g- M9 f) Q( L 4 O! b) m) a2 t+ G- b
  1、文本文件的读写4 c! b7 i1 W) v4 v1 u
; ~1 T' X' X1 x* K: H; m! }
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
( C) F+ Y! E  e% y; T
7 p& L9 ^. `/ E/ }  J  file2<<"I Love You";//向文件写入字符串"I Love You"4 t; [* h+ f9 m% E
9 @, s, _" l1 ~' ^
  int i;
6 u0 \' r" I2 U7 T4 X% S$ h
* h; N6 P; @+ ]& L- i% b: a  file1>>i;//从文件输入一个整数值。  H. D5 |: j- l: V) P

# M  j/ D6 \* U9 x2 P" o  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些' K) {) y: M( _6 N) Q
! [2 r( c0 R/ S
  操纵符 功能 输入/输出
6 Q( Y6 ^* p1 L: M( T+ d3 i$ N
' h6 ~# ]/ t( l3 H: t0 Y  dec 格式化为十进制数值数据 输入和输出
& }1 b: e- w) y( z
( j; }7 B1 {' G2 F  endl 输出一个换行符并刷新此流 输出
2 r( P8 \9 [' G
6 g( L9 @# `, a. }3 _' W3 L  ends 输出一个空字符 输出
  t  q; x" |( s) h9 o  \3 k3 v
+ R" ^# _3 \+ S3 `( \% T& H3 s# H  hex 格式化为十六进制数值数据 输入和输出
6 B1 T$ Z' k6 r  d9 B2 \4 C
5 z2 J/ V/ e1 h4 M  oct 格式化为八进制数值数据 输入和输出
- O" m. s- K; b" n! B4 L3 x* E7 S 0 G* d$ m( o5 J5 [2 W" A& v
  setpxecision(int p) 设置浮点数的精度位数 输出2 ^) c" u1 ^2 s$ N

* T$ E& d( E' H  比如要把123当作十六进制输出:file1<

8 S4 N/ T* |" P8 z& C$ m- x( ~  2、二进制文件的读写1 m" f  m" x6 o- q8 q# l
2 T2 J! Q6 N. ?' u! m
  ①put()- J" F. l) j! M# Z) ^

6 N1 l: L9 n, }1 C0 W  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。8 f" ]- t, R6 h4 e2 h; X. E; {0 Z  f

* I; P" J3 h% q+ c5 y" d. V  ②get()6 d) L) {' b7 V% p- q; w

% X/ E$ X5 y6 @$ \6 [( W( |" e  get()函数比较灵活,有3种常用的重载形式:
+ @# ^( y$ ~, _2 o9 v 1 w) I3 H- B/ d5 r- m; `# B
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。( a9 h" M- Q- k  h
. t1 Y# u$ H8 f4 ?$ s' F' {8 u
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。* u6 B- U  P9 m9 T% `/ e0 [
9 R2 X; R3 ^5 G% g/ \& W
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
% @: o0 u8 C9 F8 r+ t) J
1 v0 |5 M) I7 c! p8 c4 T  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。; B& p' G# F3 g, h, G8 q
! R5 [% P0 u  [# g7 i. X9 p
  ③读写数据块
/ O- Q% c- M# C3 l- ^; o
- C( V0 [( q7 `: e4 z  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
2 ?: q# T1 d6 N$ {. P3 o / h8 g/ }& ?$ y5 u5 E
  read(unsigned char *buf,int num);4 t4 K/ l: z2 A3 b. \3 \

7 t" n+ y/ T6 E. S: r  write(const unsigned char *buf,int num);
, P( f5 {! J: b" L7 x% t
  g* c' b; X% _6 F- W% R( r5 k  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。+ x5 X' @+ n  V( o

  g  G" {; Y6 M4 U  例:
; ^# |" o. l5 ~7 H4 F5 h # i0 m4 M. h1 h# a- v( Z4 o
  unsigned char str1[]="I Love You";. d5 L* N  L: o& h( p+ Q' h: y& a
* y" r3 g1 l9 ^! M
  int n[5];
' X( a/ g# Z* a9 Z& n# X6 |
4 ]- ]. \! H" e$ S2 o; m7 l3 a  ifstream in("xxx.xxx");- J  q* X9 q: m% t2 v

4 C* _9 a, y/ I1 d# x  ofstream out("yyy.yyy");
0 E9 T. o% W4 B- K 4 Y3 I4 ]9 w* G  j) z6 s$ p
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中6 j" ?' C. g0 X, ?6 G* }2 t

$ X) ^& `: s! ~. m$ Y0 L  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
+ }* O' J1 Y8 x/ E- X% V' H; R
! r: X; d- W( B) Q: \  in.close();out.close(); 四、检测EOF
% Z( I% c- X+ A* q1 } 8 R2 a/ ?$ q5 B. F, z
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
/ a/ k' ^7 g  a3 _5 q* S
1 f) {6 n: r' D6 V  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
( s" H. M4 x6 n& o! u/ [! C$ G$ ?
! e4 Y% f- N+ u/ r% e3 \" G$ E* S  五、文件定位9 y6 m, Q2 u% @8 _2 T: ]. P

: ^) D8 N3 ?# k, J' S& Z  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:. b4 P; S. L8 a. i

: z6 i4 r. e3 b$ f6 E) U1 a! }" @! I  istream &seekg(streamoff offset,seek_dir origin);# [; T1 \7 {1 u

( P, l: f3 F+ i; v4 ~  ostream &seekp(streamoff offset,seek_dir origin);
, f7 L- a3 G+ S2 J3 w) z 9 N( K1 Y5 p0 ~
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:4 D' I; f/ ~# W1 m

7 A. I  p! Y) |. D+ v  ios::beg:  文件开头0 a' C# `* z% n* b1 |6 _

) q: m9 l$ [& O8 r  ios::cur:  文件当前位置$ g3 R0 v2 l  h! B
9 W) t) K0 a" f0 N9 e; q1 \7 {
  ios::end:  文件结尾  n, x: O0 k# _' V$ R/ }

/ N3 U3 X: z# l. R/ F  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
- [" N, p7 E) e! k; p8 B) S ! S' F, w+ x3 Z9 m  Q! K# R
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
( i# `' u! S. `
. [3 h8 {) B9 R  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
* X& K/ a: e! z( c; K
5 ^: W1 h( p& Y/ k: W
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了