C++流操作之fstream用法介绍

 更新时间:2020年4月25日 17:44  点击:2272

在Windows平台对文件进行存取操作可选的方案有很多,如果采用纯C,则需要用到File*等,当然也可以直接调用Windows API来做;如果采用C++,首先想到的就是文件流fstream。虽然在COM层面上,我们还可以使用IStream来实现文件的读写,其效率也非常高。不过本文仅对C++流操作做简单的探讨,相比于Windows API或IStream,C++的流操作通用性更好一些,因为你能轻松将代码移植到其它平台上。

fstream有两个派生类,即ifstream和ofstream,分别对应输入文件流、输出文件流。在使用它们之前,必须将它们的头文件包含到你的cpp文件中。

创建一个文件流的方法很简单:

ifstream fin; 
fin.open("C:\filename.txt"); 
这样就创建了一个输入文件流fin,它对应的文件是C盘根目录下的filename.txt。实际上,open方法还包含一个参数mode,用以指定其打开方式。
ios::in 以读取方式打开文件
ios::out 以写入方式打开文件
ios::ate 存取指针在文件末尾
ios::app 写入时采用追加方式
ios::trunc 写入时抹去旧数据
ios::binary 以二进制方式存取
上面的代码并未指定任何打开方式,则采用默认参数:输入文件流即ios::in,输出文件流即ios::out。一般在需要组合特殊的mode才显式指定,比如:
ios::in | ios::binary; //以二进制方式读取文件

除此之外,还可以在构造时指定相应的文件路径和名称,让创建过程一步到位。上述代码可改写为:

ifstream fin("C:\filename.txt");
与open方法相反的是close方法,它的作用与open正好相反。open是将文件流对象与外设中的文件关联起来,close则是解除二者的关联。但是需要注意的是,close还起到清空缓存的作用。最好让open方法与close方法成对出现。

创建并打开一个文件流后,就能像操作标准I/O那样使用流插入操作符(<<)与流提取操作符(>>)。对于输入文件流来说,可以调用getline函数从文件流中读取一整行数据,这样就可以读入含有空格的字符串。

下面是一个例子,该例的作用是读取一个STLA格式的文件。STL是一种常用快速成像文件格式,其格式非常简单,特别是ASCII版本(即STLA)。代码如下所示:

stdafx.h

复制代码 代码如下:

// stdafx.h : include file for standard system include files, 
// or project specific include files that are used frequently, but 
// are changed infrequently 
// 

#pragma once 

#include "targetver.h" 

#include <stdio.h> 
#include <tchar.h> 
//added 
#include <iostream> 
#include <sstream> 
#include <fstream> 
#include <string> 
#include <vector> 
using namespace std; 

// TODO: reference additional headers your program requires here 
readstla.cpp

// readstla.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

struct facet { 
    float normal[3]; 
    float vertex[3][3]; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 

    if (argc < 2) { 
        printf("specify an input file!\n"); 
        return 1; 
    } 
    ifstream in(argv[1]); 
    if (!in.is_open()) { 
        printf("fail to open file!\n"); 
        return 1; 
    } 
    //var 
    vector<facet> solid; 
    string line; 
    string word; 
    //check format 
    getline(in, line); 
    if (line.find("solid") != 0) { 
        printf("wrong file format!\n"); 
        in.close(); 
        return 1; 
    } 
    while (getline(in, line)) { 
        if (line.find("facet normal") != string::npos) { 
            facet f; 
            //read normal 
            stringstream ns(line); 
            ns >> word; //eat "facet" 
            ns >> word; //eat "normal" 
            ns >> f.normal[0] >> f.normal[1] >> f.normal[2]; 
            //read vertices 
            getline(in, line); //"outer loop" 
            for (int i = 0; i < 3; i++) { 
                getline(in, line); 
                stringstream vs(line); 
                vs >> word; //eat "vertex" 
                vs >> f.vertex[i][0] >> f.vertex[i][1] >> f.vertex[i][2]; 
            } 
            getline(in, line); //"endloop" 
            getline(in, line); //"endfacet" 
            solid.push_back(f); 
        } 
    } 
    in.close(); 
    //output 
    int cnt = solid.size(); 
    printf("read %d facet\n", cnt); 
    for (int i = 0; i < cnt; i++) { 
        facet& f = solid[i]; 
        printf("\nfacet %d:\nnormal = (%f, %f, %f)\n", \ 
                       i+1, f.normal[0], f.normal[1], f.normal[2]); 
        for (int j = 0; j < 3; j++) { 
            printf("vertex[%d] = (%f, %f, %f)\n", \ 
                              j+1, f.vertex[j][0], f.vertex[j][1], f.vertex[j][2]); 
        } 
    } 
    return 0; 
}

测试文件为:
cube_corner.stl
复制代码 代码如下:


solid cube_corner 
  facet normal 0.0 -1.0 0.0 
    outer loop 
      vertex 0.0 0.0 0.0 
      vertex 1.0 0.0 0.0 
      vertex 0.0 0.0 1.0 
    endloop 
  endfacet 
  facet normal 0.0 0.0 -1.0 
    outer loop 
      vertex 0.0 0.0 0.0 
      vertex 0.0 1.0 0.0 
      vertex 1.0 0.0 0.0 
    endloop 
  endfacet 
  facet normal 0.0 0.0 -1.0 
    outer loop 
      vertex 0.0 0.0 0.0 
      vertex 0.0 0.0 1.0 
      vertex 0.0 1.0 0.0 
    endloop 
  endfacet 
  facet normal 0.577 0.577 0.577 
    outer loop 
      vertex 1.0 0.0 0.0 
      vertex 0.0 1.0 0.0 
      vertex 0.0 0.0 1.0 
    endloop 
  endfacet 
endsolid 

输入结果为:

read 4 facet 

facet 1: 

normal = (0.000000, -1.000000, 0.000000) 
vertex[1] = (0.000000, 0.000000, 0.000000) 
vertex[2] = (1.000000, 0.000000, 0.000000) 
vertex[3] = (0.000000, 0.000000, 1.000000) 

facet 2: 

normal = (0.000000, 0.000000, -1.000000) 
vertex[1] = (0.000000, 0.000000, 0.000000) 
vertex[2] = (0.000000, 1.000000, 0.000000) 
vertex[3] = (1.000000, 0.000000, 0.000000) 

facet 3: 
normal = (0.000000, 0.000000, -1.000000) 
vertex[1] = (0.000000, 0.000000, 0.000000) 
vertex[2] = (0.000000, 0.000000, 1.000000) 
vertex[3] = (0.000000, 1.000000, 0.000000) 

facet 4: 
normal = (0.577000, 0.577000, 0.577000) 
vertex[1] = (1.000000, 0.000000, 0.000000) 
vertex[2] = (0.000000, 1.000000, 0.000000) 
vertex[3] = (0.000000, 0.000000, 1.000000) 
Press any key to continue . . . 

[!--infotagslink--]

相关文章

  • C++ STL标准库std::vector的使用详解

    vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
  • C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ string常用截取字符串方法

    这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • C++ 整数拆分方法详解

    整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ bitset用法

    这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 浅谈C++中的string 类型占几个字节

    本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
  • C++ Eigen库计算矩阵特征值及特征向量

    这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • C++ pair的用法实例详解

    这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
  • VSCode C++多文件编译的简单使用方法

    这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
  • C++中的循环引用

    虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
  • C++随机点名生成器实例代码(老师们的福音!)

    这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++如何删除map容器中指定值的元素详解

    map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
  • C++ 约瑟夫环问题案例详解

    这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15
  • C++中cin的用法详细

    这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 基于C++中常见编译错误的总结详解

    本篇文章是对C++中的常见编译错误进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • c++优先队列(priority_queue)用法详解

    这篇文章主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25