PLM之家PLMHome-工业软件践行者

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

[复制链接]

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

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

admin 楼主

2014-1-23 14:57:18

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

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

x
ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间;
6 {/ R5 K+ e5 z; W  k2 a ( C. O; r8 `) \% j' ^
  在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:' ?4 R8 Q. j5 \( j3 o7 C- q( n( o
$ p) F% ^- z! q# `4 V$ n: b1 l& W1 N
  1、插入器(<<)
. a6 c4 }4 d5 n
9 q% g4 ~! ^3 ]. m- ?  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write Stdout"和换行字符('\n')输出到标准输出流。$ y. k, u: u. u2 m
# Z! j$ A1 B. t5 e7 z+ x3 M
  2、析取器(>>)
1 }0 V* Z/ m. N6 l3 @. D3 t1 ?; [& M " s) b' M0 M9 v! o
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。1 [: Z6 a  A: Q$ d) |; O

: h, h& n4 N, ~. @8 H7 Z6 p+ l  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。! w3 K/ G# P' `7 J
* F( K: V4 h9 ^
  一、打开文件5 [' [8 f; y5 S( }8 I

" n$ Q+ L4 N) K8 m: H  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:3 E! h8 U( N! h: |4 S) O8 `9 j

, ]# l! ?1 m  t6 b3 R) C. f  void open(const char* filename,int mode,int access);参数:
* q# W  A% K7 K! R- C
! U! z. a% S0 z; ]0 m  filename:  要打开的文件名
  @- O7 _4 s, F& M" q0 w 4 a5 G/ n( D; K  O
  mode:    要打开文件的方式
8 k" r( V5 L* b2 B0 M : `7 g1 w7 v! I
  access:   打开文件的属性
9 m1 Q* W/ }/ H( y9 u7 X   A- ^% B, ?2 Q
  打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:. X" s2 p0 B' |
& ^8 Z6 ~) }! J6 {+ J9 R
  ios::app:   以追加的方式打开文件
4 d9 V2 S9 \$ r! q( U# r * Y8 D8 P8 R1 g% ^3 `- K: a
  ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
) E$ J3 ?2 M, a7 g * t% k/ L. x1 F. y- P. _
  ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文0 s$ n4 l7 G* B9 V1 I

/ X2 J# l3 q1 R; d  ios::in:    文件以输入方式打开(文件数据输入到内存)
6 C% G' q% F9 C/ e1 M6 H2 B % m9 b  L  x3 O4 P
  ios::out:   文件以输出方式打开(内存数据输出到文件)
; m& Y# N4 F* d$ y+ o( F
* Z6 ?0 e- Y. e4 x  ios::nocreate: 不建立文件,所以文件不存在时打开失败% w/ b! u. |( J- R

8 V1 j$ A* P" R5 b* d9 b  ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败2 H4 B: L1 m  ^8 I3 i, n
4 k+ O/ w. A+ i4 O5 D! u) ]
  ios::trunc:  如果文件存在,把文件长度设为07 E1 W0 C* y  e0 i' ^' a
8 G3 T' S; g+ j& t
  可以用“或”把以上属性连接起来,如ios::out|ios::binary% P6 I, j# H$ t7 F4 |0 c) w1 d" j
* u9 g- G/ l- w. Q- M
  打开文件的属性取值是:
' f' B# S! Y+ T: [# R& q- c% v 3 V% n( z" E. L9 G+ j9 ?
  0:普通文件,打开访问4 ~( t5 h, O1 v
& o# x8 {, g3 W, P9 |& a* s
  1:只读文件
% Z5 G/ x  R- s- c& D' K: v 2 i  w- z" V; v6 y8 Z
  2:隐含文件1 j% o; j6 Q4 ~8 k. }& i

. k0 n2 M1 }4 [& w! V3 q  4:系统文件
8 w" }, O: C( j
  }; V" b" p- a; G! g  可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
: V/ c0 {, m  ]3 n' l ! }% n8 w* f7 H4 ~& M# U
  例如:以二进制输入方式打开文件c:\config.sys
1 U& q/ J" I0 _* J' T % R0 A0 G3 Z; M/ A$ f4 m# b
  fstream file1;- ^* J) v' u# o' z/ M! `
6 I) [# c3 d! p
  file1.open("c:\\config.sys",ios::binary|ios::in,0);, f) S4 y: o4 \

" l1 @4 b# l, |* @2 ?" m  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
) S! h/ r7 H! F: H7 u. c% |: N
' E5 ?: Q& ~/ T; s, s0 |  file1.open("c:\\config.sys"); <=> file1.open("c:\\config.sys",ios::in|ios::out,0);
0 D9 C4 W1 k; H' E7 X& u  | ' m. j' n% q/ g' {6 ]
  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
+ S- M3 H. r6 x1 J" ~! c
7 H# C% O0 c5 G  U) Y" y- \0 ^  fstream file1("c:\\config.sys");  特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。! D' |6 m+ D8 }+ e* b
, Y8 U' H$ Z  n+ T% R- a7 E
  ifstream file2("c:\\pdos.def");//以输入方式打开文件
& ?. B- i3 s9 X! P0 D/ x8 n
3 t! {. e, D5 [! u; y4 C  ofstream file3("c:\\x.123");//以输出方式打开文件  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。
; x2 Z& [, T7 i" K ; w9 b1 K* E3 S1 l$ q0 E! T
  二、关闭文件
+ y, o. _6 n, ~ & g# W$ j" S* s9 R' p
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。/ Q& {. W1 y& s: O5 a# x
( A, |: v4 T3 h8 d. R2 K
  三、读写文件. ?0 e' _  N6 }2 Y1 `9 ]' _1 Y/ g

6 b3 p4 B6 P# N, J4 b  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式
# T: X- X7 ^8 I8 x3 G, g: R) P" ~
1 L. A  W9 \! W$ B2 m  1、文本文件的读写2 _! o9 o  b# D# J% S
7 e* i( o3 F& @4 V6 l' j
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:
9 N2 X, U) A7 O# V! [2 `1 t1 G( P
6 N* A7 i  q+ ~3 Y  p, B7 [  file2<<"I Love You";//向文件写入字符串"I Love You"
/ T% O5 U8 @! z$ b
. N: h2 j# ^! p0 Y* B% g5 t! e( i  int i;; _1 @7 [+ M" {# o4 y8 [

4 U* u9 {8 C% y/ Y  file1>>i;//从文件输入一个整数值。
, k9 w$ O9 }2 Q7 Z" ]4 U- z . l$ F; r' h( A" q* S. Y
  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些
' ?6 h" V* P7 r+ b
# T1 {4 v" k) R# [5 B2 h0 j  操纵符 功能 输入/输出
# E9 y" Q: ]. Y1 `  T : ^+ _2 h0 C+ L5 H
  dec 格式化为十进制数值数据 输入和输出" W* {/ j6 o7 G6 ]; _- h/ k% G

' p6 R; r0 Y0 W  endl 输出一个换行符并刷新此流 输出
* i0 k( h. L& O1 V: `  `
6 z7 F) {# o' f/ I" J# y  ends 输出一个空字符 输出6 ^1 B0 J& Y: ?3 A7 g
6 |: @1 p7 i5 W# L$ W
  hex 格式化为十六进制数值数据 输入和输出
  i6 e2 R- V$ }: v, S7 f( J
/ w. N6 N- z/ s5 u$ I+ d  oct 格式化为八进制数值数据 输入和输出
" V9 D7 i& l2 _7 Y  x# L& ~ - s. G/ o3 y" b5 \$ F: u
  setpxecision(int p) 设置浮点数的精度位数 输出
" K- i" O7 y; A9 x2 f
. Q+ ]$ u, E2 O  比如要把123当作十六进制输出:file1<

; T) F) [9 a- B  2、二进制文件的读写+ {0 w* W" m  P$ {

* _4 p, k8 _0 Z  ①put()! {1 R0 X+ g! Y- m0 g+ q

. \9 ^) \' o' W2 I/ e  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。) y0 [) v: e, W
) U( c/ B* v+ m' W  G( Z! q
  ②get()
. \9 O  N/ t. M8 C7 Y6 }& m
, i* d& L: x# g% D9 D# \+ ~% k" W  [  get()函数比较灵活,有3种常用的重载形式:
% [8 T1 R/ w7 v 2 |9 n: [" t7 G: h5 A" {
  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
) Z9 ~' H$ D0 u 4 p3 W8 P. y5 i0 Z1 v3 D( u
  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
. t1 T  ~$ z( H) m % z4 U( A# C( }1 n# X
  还有一种形式的原型是:ifstream &get(char *buf,int num,char delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'\n'。例如:& ~  r, ]; r. Y, |; L

3 M3 x5 w% j4 |  file2.get(str1,127,'A'); //从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。
) k' s5 }4 ]$ ?: X  ~ 1 s# |7 |- Z% ]7 O# J/ C8 r" q
  ③读写数据块
! V- J1 n6 X0 b. E7 B0 I  I. u* S
5 L7 B( c& D, m0 e% c6 J  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
( r1 P7 R/ f- Y4 O' N4 o3 f! Y1 w ' c$ b* ~+ X6 `) C, V) X$ C8 z
  read(unsigned char *buf,int num);7 W2 v* }: p5 ]8 q  @
; F9 z7 J/ @4 U# @5 R& v. K
  write(const unsigned char *buf,int num);* |$ Q7 k( {1 ?6 t4 y7 z9 y* d. V

! m- I7 W3 J/ b, q" W  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。7 z2 M+ q7 B+ O# X  X0 ?7 B* E
, _+ J" q% }9 Z: X3 m/ X
  例:
8 u% o0 L; o. }& |8 t6 w0 n# G4 K
! v6 X! }2 h5 a$ u: W6 m  unsigned char str1[]="I Love You";1 r1 q1 M* A4 z

7 [3 E! f1 g$ v5 m* r( q  int n[5];
6 x0 x% ]3 m/ F2 D) ?  w
* c' _2 j1 w: D. r1 O4 W5 _  ifstream in("xxx.xxx");
# {/ E) c5 K. Y- J5 e
3 H8 @( V( @& n* P, T4 n  ofstream out("yyy.yyy");
- q6 ^* I: l8 o( r
0 t% E0 v! s9 E  out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
1 s, J  H7 z9 C% k 7 h/ s/ P0 P+ r% ]- T5 K8 L& G+ v
  in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
. d" W8 P: K- p- _
, T% X4 Z: r, |5 K1 Q' I& R( Q% ^3 L  in.close();out.close(); 四、检测EOF
% P5 {) W$ v; F' ` % A9 T: w6 ^0 q  s5 `0 i$ W) R/ t
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
% L& y# s4 U2 E; f0 P; ~9 v & J" M9 P1 z4 P
  例:  if(in.eof()) ShowMessage("已经到达文件尾!");$ h+ |; G& ^+ e) o8 k( P
! @( ^- K$ k4 H! }! A
  五、文件定位7 I$ D" F% B7 R9 `% \: C

; @1 C; G0 v: T; D/ F  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:
: Z: H* d0 H& ~7 u
7 b" Q! c4 `* T3 }8 f+ j. R  istream &seekg(streamoff offset,seek_dir origin);+ V" }+ c1 Z9 O' b/ Q/ ]) I) m) Z+ @
  W1 T: d) D4 _% I4 u/ x
  ostream &seekp(streamoff offset,seek_dir origin);5 D4 T8 w0 A8 W: r3 ]
% f* M# ~" M1 g( v& S
  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:
* K; K$ u! H# l& y% Q: L $ Y# Q  t8 x( c: E
  ios::beg:  文件开头. N* l/ O( X' j: h$ V
- D- s  w( ?9 y5 p/ V4 s
  ios::cur:  文件当前位置3 I/ ~0 b4 R8 H( e& R8 s

- D( Z% b5 P9 H: ~4 u1 X% [  ios::end:  文件结尾
: F* }2 m4 S2 O2 h/ k& h 3 Q# h( _2 z$ F+ q1 v
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例:
. m1 S" S) O+ b. j% R+ m 7 _5 v% f9 p) c1 R
  file1.seekg(1234,ios::cur); //把文件的读指针从当前位置向后移1234个字节
7 }/ Y) _$ V# O' e 3 q* \( I; p$ i! N+ R! \! J9 \
  file2.seekp(1234,ios::beg); //把文件的写指针从文件开头向后移1234个字节
7 d$ |' [4 l1 T/ X& C

4 z; N# ], U0 u, A" r& N' x1 p0 ^
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了