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

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
0 z8 T! |% q! w7 y# S3 T4 a% O ; d  S6 l3 U2 U) f
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
- M7 `& X% b+ j. s
! ~$ F, B+ `$ x" Z1 a* b6 S' t  1、插入器(<<)9 b0 K1 j3 u5 B8 Q

5 w7 I- o1 I. l+ Y3 t0 F  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。
' x% D( j" Z+ Q) W
: c( {- a" h# x- `' @' m# w! m  2、析取器(>>)
+ Y' F9 o1 e+ h# C( ` - H( M8 @* F: q9 o  P( W7 {6 a- }
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。
7 e! y. W% g, p* o; R4 j3 M( b
. h  }" E; n1 f1 [6 z  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。
6 `( [5 ^5 a" j& e- Z 0 q2 }4 R5 m1 z$ m
  一、打开文件
4 z( I% r7 @, D
8 o# F" Y' k+ M* z& M  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:
" V' S/ v4 p' |/ L8 }
9 J/ D$ L! {* ~7 Q- S0 x: l  X( h  void open(const char* filename,int mode,int access);参数:. E% A# O; N) [! h  l+ A
6 k- ^( g3 V* g4 P
  filename:  要打开的文件名
' `, I! V1 S8 h' U# m9 j! i) M
8 `) {6 S# ?6 D; p/ q& }0 U% u  mode:    要打开文件的方式
7 B6 f6 y# _* _: y9 H$ ^, e
4 Z' Y: N4 M/ o# f  access:   打开文件的属性
8 X0 F! W6 F9 G
; b8 ?. o) h) y! M: j, j- W: b; i  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:- M' T# U' F0 p4 Z2 n0 o
$ F! o4 r/ s9 @  U8 a
  ios::app:   以追加的方式打开文件
2 `% V' Y1 F1 }0 e& v
) D. Q0 l  P- A) |# ?* _  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性+ g5 X$ n6 y  a  b* q
6 _8 p! Z  X4 H
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文, _, ?( t  }! U' N" x
+ f+ a/ }5 X% I$ G) r5 B/ C. B
  ios::in:    文件以输入方式打开(文件数据输入到内存)( R$ Q! J. t- P" F& F2 r

, ]* }" m  a- c( D  ios::out:   文件以输出方式打开(内存数据输出到文件)% o+ G. z$ r# E5 l! t) H9 l' d$ b

. U6 x% C* z" x8 ^% _  ios::nocreate: 不建立文件,所以文件不存在时打开失败* A( i! j. Y" U: a
- Q' `9 r! {- p$ R+ D' l
  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败2 ~2 u6 I+ U$ K/ g! S5 m% e
! U( A( g% P# E% J& Z
  ios::trunc:  如果文件存在,把文件长度设为0* n: B% p. i: F. I3 ]/ B

5 _6 e3 `* o- E; f0 ^* y) N1 C  可以用“或”把以上属性连接起来,如ios::out|ios::binary
1 i: Q5 @$ y; h) |' i
4 }6 y0 q# e4 [9 ?  打开文件的属性取值是:
! H. c& }; u$ U* u5 [( X* ~ 2 t. D$ U, t6 ~6 l  x- k+ z9 @
  0:普通文件,打开访问4 x4 q- G! l7 W% O: V
( n0 v% B  e+ \
  1:只读文件
$ d( U1 X$ @* ]- c
9 P4 Z, h2 w1 h* E: a- \+ I$ L# F  2:隐含文件. r8 R4 \0 p5 A( j) t3 O
2 K+ M' X1 U) s; t- }1 |
  4:系统文件
' j8 S; i' |! Y# I8 Y$ n6 o' I
7 G/ _- a& V+ u3 x  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。/ }8 K3 g. d6 W/ B5 ~
: Y$ W  I, [# p  K$ W& s
  例如:以二进制输入方式打开文件c:\config.sys
& u" a: E& ?, p* w. j
- X+ z" R. X% Z  fstream file1;
; R- W- b& k, O$ C2 P 7 z& `" Q: M, K
  file1.open("c:\\config.sys",ios::binary|ios::in,0);! c: M* h& t3 S. r; I2 T4 ^" ]

$ ~6 i) G/ d% _0 a  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
4 \6 d* k, c( A! y: i& x
/ t* n; h( d4 W  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
7 }# [- \& t6 f! x4 L5 M7 Y: F9 s
4 z9 B+ S. P# F  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:- R! s/ X5 X( u) z) u* g; @- O$ d

% Z. V8 `8 r& s. R1 f' N  g  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。2 T7 P% G  l4 E" H
  F& y9 l" W% x) d
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
. h3 h- ]0 E5 e! s& \8 a$ ^
1 Q  R5 \# Z+ s2 ?: Z* \0 @1 H  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
4 W( z5 }5 S- _$ ~! r1 ?
, Y. B% ^6 M( D# A& a1 w' ^  二、关闭文件
. w: I. y+ v9 z+ U  Y. r: e. g; J ; _9 F8 s) A2 A# Y9 v6 o1 A
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
8 l3 {4 h, R  V% F' i
- Q, z. r# Q, [% a  三、读写文件( E" M! o5 R$ v) V9 M1 C, _$ _

: V) T, g# a, q. t) S9 y) J+ [9 M/ }  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式+ Q& u+ g) y8 v
8 W4 r+ N5 o: d$ B( ~
  1、文本文件的读写; K0 s# t& W/ I  g0 I* D- O

0 z3 s1 M# D2 u' I, e  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
* b; U: t: j2 i) U/ {- A4 n 7 z( U# L  Y6 Q0 C# K( ^
  file2<<"I Love You";//向文件写入字符串"I Love You"
) K+ Q8 f. u) ]; c" M 0 B& I" q- g- L6 r, Q+ A+ j1 J  w
  int i;
' A& g$ l! ?6 G; W  b - U% ^; V# s+ P
  file1>>i;//从文件输入一个整数值。
, R& k& H3 t8 J: @; a: B% a
. q: v' W6 A$ u  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
& }* V  I# Q; h* I* ]+ C9 J% `* T# O# A' @
+ W3 d- |8 f7 x; y4 x/ l( D% q  操纵符 功能 输入/输出
& O4 L- j" w$ ^ " L7 h% c$ Z0 m% D+ b8 M
  dec 格式化为十进制数值数据 输入和输出6 R7 E4 l# ]" j( i  V4 h

; D  n5 w6 ~, n$ b  endl 输出一个换行符并刷新此流 输出: Q" x* a" }) F# E# H

6 R+ C' n6 t: c% @$ W% i1 i4 d  ends 输出一个空字符 输出- n: I4 w$ g0 n9 t9 i% e

$ q, C, A2 _) {3 a& @/ ~  hex 格式化为十六进制数值数据 输入和输出
7 m4 L9 e4 K" V" ^7 Y 3 {9 m  [( P* T4 f
  oct 格式化为八进制数值数据 输入和输出
: Q5 J2 c2 ~% F; F, H
! Q& D: a' d: I; \0 G  setpxecision(int p) 设置浮点数的精度位数 输出9 ]% z" @4 i0 _

; h2 g' S5 ~' F! j9 k  比如要把123当作十六进制输出:file1<
9 N) I8 F6 T) ~- G
  2、二进制文件的读写
$ T- F% L5 C+ ]$ F: k* p% I1 x 5 O  D& ^6 B+ g( z
  ①put()
  _$ B( A1 P9 E" b3 p" I 4 H3 w5 Q" M/ s# e
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。3 p% Q/ E. S+ Z3 k% C
; K  j+ ]4 ]: v, u) a7 b
  ②get()- N, u4 r8 T) I- d+ y. v

$ H. |# C0 j# P  get()函数比较灵活,有3种常用的重载形式:, a! n4 ?  {3 i

4 ]/ }) z' @9 Z; |+ J/ P5 B  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
! z8 L+ C) ^" s' q7 ^( `" T , B& g4 g, z* v" I
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
# g0 @8 m* _( U9 s2 K$ W2 J3 R5 q
) X' y7 [; e2 v! e# @7 p  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:
2 L* D" d4 L/ w' x% ~1 L1 K3 ]" R ! ]0 I/ G) c/ w6 J8 o1 v
  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
& V# [8 `( F4 J + n  `. ~5 _5 M# C" M' _' H
  ③读写数据块4 I. N  {1 B" _) k

0 I* x/ x' U1 z, q) p, J. y  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
! Z; [+ q3 x$ y- _; k, D4 e
/ I8 a8 R! C& ]% A: A' @  read(unsigned char *buf,int num);4 |/ k& a7 Z, g6 w/ |# y) q" L6 E: q

* h% F, O  z  D  write(const unsigned char *buf,int num);
0 m0 j& H3 }  Z% i8 h. L % R* J, J. c  {+ E! I7 N- `
  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
( f) O9 R; j6 ?3 s
1 {" F! W2 d7 [0 w  例:; s+ S) _  G' m! N  F) M: L; C
: e% \( \5 g3 d% L# u- U! m
  unsigned char str1[]="I Love You";
! w& H0 I8 e; X* i! o 5 D- x& a4 ]% Q. v( m, q
  int n[5];% p8 a3 \2 y3 ^; b
( e6 k, K! E! Y" e/ R# ^
  ifstream in("xxx.xxx");
4 M$ |; [, A4 F$ y9 b : G& p% S0 \2 [" p9 T( o6 H; m
  ofstream out("yyy.yyy");- Q* K" o0 E3 v( ]$ g
9 Z' y% F4 \7 X7 L
  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中% `+ _, P0 [, k
0 P4 Q+ ^% O4 ^7 ]3 j1 Y  O) h
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换. G3 X; W0 G" {5 o0 E

! r6 `/ `% T- h7 {( K+ m9 J  in.close();out.close(); 四、检测EOF6 J! A' Y9 H2 D7 n) j
% h6 p  a- h% O* W8 I
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();: c- \2 y5 A0 w5 _' A8 c* \1 k
/ A2 d/ x7 {5 B) O
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");
/ h, }4 g1 d% t) I# Q/ r
/ F( [$ U0 D6 Q9 z! y  五、文件定位
+ o& b. `. d& ^' }. ]$ W9 [0 b 8 n1 e/ D: @  L/ z1 S
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:* j% P( i$ h- K5 v0 z7 P8 A
! r# y. E& G: K( N6 ?( a+ w
  istream &seekg(streamoff offset,seek_dir origin);5 n( h* M: [% n. f

* P2 x* M& I. r, ^7 i  d! S  ostream &seekp(streamoff offset,seek_dir origin);, ?" ~6 v3 ]7 [6 q0 O2 }

2 M  I0 W" A0 g8 Z3 w  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
& n8 ~" {; N$ s- B. O0 j
$ M2 Q8 S4 W6 n" Y) A, S  ios::beg:  文件开头9 f: o& A+ M* d% y: P2 x( q
; w0 I& {  z' a% N- t
  ios::cur:  文件当前位置
, n  K& U8 R; {4 P4 _5 ?0 n 2 j7 y* k/ M: g5 l' q
  ios::end:  文件结尾
3 `" d. m, Q6 d3 g4 U8 L+ C' w
- h3 D$ u1 n! ~" f4 h9 i  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
* \) L' p6 n* n- ], t, M, S' F3 Q1 N
' Y$ s  s* r: u' n  O4 p  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
, M2 s; H' e# L% A3 p- R2 ]6 }3 r
2 l: ^: e2 s0 c  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
' u8 ]) o  x. ]/ u  I- `# v7 B4 M

- H4 t2 [7 W) p
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了