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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
0 _  W' l* B5 Z/ n8 y6 T3 e' R9 h
* g' [* u2 ?5 i6 _  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:6 a" ~# M  J& E  o! X
9 F! [1 Z# K6 B" T% P8 ~# x
  1、插入器(<<)
1 p: S: a8 t1 g: {
+ Y% K) e$ m$ S& K$ E4 w+ }2 \5 F  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。! E/ A! k* G9 S3 N8 \# v/ ^3 A7 k
7 \% y2 |4 ?% m
  2、析取器(>>)5 W! @9 l6 }* A) k
3 S4 u; z3 h/ Q/ [6 u& r
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
5 @4 b3 v6 X5 o4 ]7 o9 q4 J7 z 8 o7 J* Y1 I$ \
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
$ o- F! k5 h- H- @0 E% Z  a
  \  \+ K) `* n  一、打开文件( ]7 @( R; ^% P( e4 \. m8 ~" h
- K+ ^2 S  d7 {6 H5 K0 c4 D
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:" s: a7 v. n$ [& ?3 o* n

( [+ U1 G9 d* S/ h  void open(const char* filename,int mode,int access);参数:; f; U+ t! K3 g# j
2 X( l* L& [8 m- L" t/ P2 C
  filename:  要打开的文件名( h- l' L! o) H
7 ^- B4 Y6 R- b; H8 x
  mode:    要打开文件的方式2 ]! L% z$ ~: J6 u8 s, K6 J

/ g+ A8 [, J6 X+ c6 O6 k  access:   打开文件的属性
1 D2 l* \4 i8 A' Y 7 E9 b; N7 K0 z, n2 Y. t: ^' u' ?
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:( v' E9 o: J- Y' f
6 I. _; h) A$ D% [$ C! z' i
  ios::app:   以追加的方式打开文件4 z2 G) `& B0 J. q' Y6 O2 r/ B8 V
0 N. x$ i* h0 V( p
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性3 z- i) }' V6 x; E$ [% O
& P, Q* e3 Y. i8 P: F
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文1 k/ I4 {' ^9 e  f0 o3 i

! I& |& P' _3 B  ios::in:    文件以输入方式打开(文件数据输入到内存)
: {& R, g3 w. ?4 [# Y) Q! b
" J7 k& k+ l" s- ]; r3 y  ios::out:   文件以输出方式打开(内存数据输出到文件)
0 f! s% X9 x9 ]* T2 J: ^% q3 e & h1 [) ^4 W9 _6 ^
  ios::nocreate: 不建立文件,所以文件不存在时打开失败
4 L  S4 s* h1 G5 R4 X$ w( d/ x
" {/ `$ w, S) B6 N+ p  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
: q5 F; n4 b, K. p8 N; y) L; u
* f2 o* e4 B5 m9 _5 }  ios::trunc:  如果文件存在,把文件长度设为0
0 H5 Q, k$ q) U 0 P5 ~; ^( B, B9 l. h8 `
  可以用“或”把以上属性连接起来,如ios::out|ios::binary
. T7 `4 @, A5 o* h4 e9 r( n( h
0 Q- Q9 l) Y# e: @/ i* B. N0 \  打开文件的属性取值是:* p7 C7 j2 k% d" ^
2 q9 B& y1 \4 i# P, J
  0:普通文件,打开访问
: }+ A/ T; g! [% @2 A & F' ?  t3 Z" }' o* X
  1:只读文件
: H$ _4 s$ T6 J
4 x) p* x; a7 r1 L( j6 l  2:隐含文件
' ]4 G, M4 ?6 j" S% X: o2 S5 q9 k- x
. I/ V4 M5 Y* H" d& K2 F  4:系统文件
( {7 X& @5 ^% {" H 4 T! y* T  ~! T9 B$ o, t' Y
  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
3 A+ w" i. H: `8 R. F' u
4 [- H: B) w, H3 a+ [% _, r  例如:以二进制输入方式打开文件c:\config.sys9 e' X/ t& G9 f6 d" D8 ?
' @; Y$ l: i$ A) A+ _, L
  fstream file1;
$ a; I: k/ }/ ?8 o) V7 U  t! ]
' v  J* E/ g! {# ]7 V  file1.open("c:\\config.sys",ios::binary|ios::in,0);  @" |2 Q0 O1 x; p2 p  i0 ]: v) g
' s' p7 O% K5 J$ W0 H6 e
  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
5 t* ]4 @2 f8 |/ l/ b
' d1 a, p/ E1 O3 D/ K/ i  N( K  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
$ Q5 Y# r! x5 U$ x
) \* W2 s" ]+ Y+ }3 U0 a, B  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:5 W2 Y& V/ R5 j/ _- G2 `
" Y" R) L9 L' m( [  o: Z. m
  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。
  L# [/ z- T) T; R1 c3 L- h ! H( U6 Q1 T: M3 o
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
/ \7 j1 W$ c0 _% \/ B ! {( A; Q" C' n
  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
$ g4 f5 m" i5 u0 U4 ]; [. M
" A6 C- L6 }7 N  二、关闭文件8 u; Z3 l1 [$ H7 B7 u/ @
6 l( p6 B' E" L7 ~4 j& e
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。* [% E: |, }$ l; B# p8 u1 I
, a3 H- \* a3 [
  三、读写文件2 ]9 s# k! h/ d1 w4 _6 T

6 }/ w$ b' }% m, c3 _% o  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
" @2 V2 M% E2 M1 N2 }4 U
+ x2 L$ n, I/ _( I& Q3 D% O  q  1、文本文件的读写
7 n' A# h; ^# x5 ^( y( l
+ q% N1 |& x# A' i  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:& |8 G+ N& M$ I; N

9 ]: C+ }4 o3 U1 R2 Y# `  file2<<"I Love You";//向文件写入字符串"I Love You"
# p6 z, F5 X( M7 F4 N( i+ { 5 U5 Y8 }1 z, M9 P
  int i;' D4 d8 P. v% }' V& v/ b( A( L" X
8 A( {  W! O8 q% c3 i* k6 u
  file1>>i;//从文件输入一个整数值。
* h( [; e( R- E& v$ I
' s# O! ~: f. ?1 _& ]: l  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些- V$ L2 X( W0 E% ?
* H0 Q) `1 l& v& u6 u; I' a# K1 ]% h$ p
  操纵符 功能 输入/输出
2 i! E& W- F& Q  Z7 D/ X. H7 I) X ( Y; ?. R, L) X" X5 c( Z/ w  k
  dec 格式化为十进制数值数据 输入和输出
1 p' p2 N9 l+ l' r- H( P $ [8 @2 C+ Z* q% |
  endl 输出一个换行符并刷新此流 输出
3 J. |6 h7 g0 c- U' d
: [2 Z) |* r3 m8 [3 f5 m' _  ends 输出一个空字符 输出
, m+ }1 ^4 I4 e/ ~9 S2 Y' @) s 9 e! \9 N; N3 s0 a1 n9 `
  hex 格式化为十六进制数值数据 输入和输出
, b5 d' X, l/ K  x- p" V
7 I/ z8 v( `+ f, P# X3 F  oct 格式化为八进制数值数据 输入和输出/ C6 o/ c3 \# f) L

' e/ x+ w3 a2 Q% Q: M4 w. K: e  setpxecision(int p) 设置浮点数的精度位数 输出, y6 U5 ]4 Q. ~, T# C

+ b8 j5 O$ R* c: S6 `. l+ ]$ m  比如要把123当作十六进制输出:file1<

) X- [9 s( P$ ]/ u4 _- j  2、二进制文件的读写) M( G. G" \" ?& q; a' ]1 x

( u; Z: Q2 ~' J+ o- ~  ①put()
# H$ X7 P) B% S5 [; c9 [ , W( R' I6 v2 Y& `- t
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。
) a3 I$ d  G, U' A
: l6 l# D4 l" \% Z& [+ _8 I  ②get()% D8 x+ P' k5 \8 h* n
" B+ `) B  p& N  i$ ~
  get()函数比较灵活,有3种常用的重载形式:
" ?5 X, w$ ]- F( x8 Z  y7 { ; h6 s$ u8 F  z- B1 B8 `
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。4 ?* a: P) a6 I( W$ _

9 {+ |9 T8 K9 _! B- r  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。9 i' ?+ z% T3 y" H9 ]5 z

0 O" y9 h. }; Y: _2 \  j  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
/ s% S! ?3 A- I2 y5 e
5 ]# ^* @7 S' J. O  d# A- q: c: \9 l  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。4 v- S- }2 m: r& C' z1 H& ~/ W# O4 s+ L. ^3 R
8 |6 W% a4 w3 u1 k
  ③读写数据块& u, i: `7 v& \; N. o

8 J8 R" z* x: d% o6 X  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
9 P. v9 r* T' B( U
1 x3 A, @9 [% y9 ]2 c  read(unsigned char *buf,int num);4 f1 j5 G" r# x: z
5 {! s" H) t1 g/ E8 L) U; Z. @
  write(const unsigned char *buf,int num);. _+ B! z3 c# C8 }9 r6 |7 {( B
" U; I/ I  z/ B& _4 L# m7 p  r
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。$ O$ Y" K  \0 K5 l+ Q/ h! B! N- W$ x

2 l5 r+ E/ Z6 p% S: C  例:* i# d7 P* b3 y* M, v" q

) Q4 w, ?8 v* z' }* M  unsigned char str1[]="I Love You";* i! t/ [+ ?& G; p9 Q: j

, k8 Z! P: i$ {' }  int n[5];9 M' F" s  {) }5 H

2 K, k& J! S, d) e7 l5 b  ifstream in("xxx.xxx");2 a4 s) v& b7 @% N5 c( [+ ]& U
8 u6 s1 u& h5 `& b; U
  ofstream out("yyy.yyy");
: _8 i8 \2 D" q 3 V& Y5 F5 `- b
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中, O  T& v# k' f9 L9 a
" e7 I5 _' \$ N0 B8 |) G
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
( Z) Z+ _0 g# E+ d9 Z
0 F. {7 R6 F& z- j) G  in.close();out.close(); 四、检测EOF  A2 y9 P' c% z# x8 @# T6 b

+ n- x( G2 n) n2 I  [& s+ E  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
( D' o/ G+ O! f9 Z4 u9 n
, Z- ~1 i1 V  M/ W5 \  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
" B& t% c0 x" n' @% b& F) ^7 t+ Y
" k8 @, n; [2 t6 H6 Y  五、文件定位
% v; |8 D) G3 g" Z% c. {5 W; g
* O. p! `- Y, x, t) w" \3 C  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
) @" F+ b1 v! r( f' x& P
" S4 C/ I  t- l& Z4 d: x& v  istream &seekg(streamoff offset,seek_dir origin);
- x: y& N9 S; H% n; L; h2 M
7 T2 Y+ d5 k, N6 i: W- X6 }  ostream &seekp(streamoff offset,seek_dir origin);  A" Z  t1 X, z6 K/ a( D! _
! S2 x3 c7 Y( y" ]$ ^/ ~
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:, F6 z' K$ c$ t
; i' [+ }7 B$ l
  ios::beg:  文件开头4 R* o" t) }5 A5 U# [( e
- W4 w* e6 j- g
  ios::cur:  文件当前位置
' Q: L+ L9 J/ y, V& V* U8 n( P 7 q3 i& @7 Y2 w2 I6 f' O
  ios::end:  文件结尾
$ N0 a% a2 R/ |7 A5 L) k+ r9 r5 z % B# s( @: p, S6 G
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:, C7 t" @$ }. z: G  b8 z

% G% p7 v& X/ a  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
3 z4 M  s4 x( b) r% n 8 u, [0 g  z  s$ V) s0 @/ g' q
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节

1 p7 F  H3 X% q5 E8 }! \+ J- M3 N2 i0 W6 h- O2 w- V
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了