c++ fstream + string處理大數據

2021-02-20 GitChat精品課

一:起因


(1)之前處理文本數據時,各種清洗數據用的都是java的File,FileReader/FileWriter,BufferedReader/BufferedWriter等類,詳見java讀寫文件(可點擊閱讀原文獲取連結,下同。)

(2)應用java的原因是java裡面的map非常靈活,eclipse編譯器更是給力,而且ctrl可以追蹤函數等,詳見java map的排序

(3)應用java的另一個原因是java裡面的string類的字符串處理非常靈活,各種函數是應用盡有。

(4)上面兩點算是自己的誤解吧,因為c++裡面也有也有與之對應的fstream類,c++map容器類,詳見c++map簡介

(5)c++裡面也有相對比較成熟的string類,裡面的函數也大部分很靈活,沒有的也可以很容易的實現split,strim等,詳見c++string實現

(6)最近從網上,看到了一句很經典的話,c++的風fstream類+string類也可以非常好的處理文本文件,讓我們一起來見證

二:fstream的前世今生

(1)簡介

包含的頭文件#include<fstream> using namespacestd;

C++中的三個文件流

a----ofstream ofs("文件名",打開方式);

b----ifstreamifs("文件名",打開方式);

c----fstream fs("文件名",輸入打開方式|輸出打開方式);三種文件流分別用於寫文件、讀文件、讀寫文件,一般用a、b兩種方式進行,因為一個文件同時進行讀寫的情況採用c方式。


三種文件流都可先定義,再打開文件,以fstream為例

fstream fs;fs.open("文件名",輸入打開方式|輸出打開方式);

其中「打開方式」可以不給出。若不給出,對於oftream默認為ios::out,iftream默認為ios::in

(2)文件打開函數

在C++中,對文件的操作是通過stream的子類fstream(file stream)來實現的,所以,要用這種方式操作文件,就必須加入頭文件fstream.h。下面就把此類的文件操作過程一一道來。


打開文件在fstream類中,有一個成員函數open(),就是用來打開文件的,其原型是:


  voidopen(const char* filename,int mode,int access);
  參數:
  filename:要打開的文件名
  mode:要打開文件的方式
  access:打開文件的屬性

(3)打開方式

ios::out輸出數據覆蓋現有文件(默認的寫代開方式,文件不存在,創建之;若存在,則覆蓋原來的內容)
ios::app輸出數據填加之現有文件末尾(追加末尾寫代開方式,不覆蓋原內容)
ios::ate打開文件並移動文件指針至末尾
ios::in打開文件以輸入(默認讀的打開方式)
ios::trunc輸出文件中現有內容(ios::out的默認操作)
ios::binary二進位打開供讀寫

(4)文件指針定位

和C的文件操作方式不同的是,C++ I/O系統管理兩個與一個文件相聯繫的指針。一個是讀指針,它說明輸入操作在文件中的位置;另一個是寫指針,它下次寫操作的位置。每次執行輸入或輸出時,相應的指針自動變化。所以,C++的文件定位分為讀位置和寫位置的定位,對應的成員函數是seekg()和seekp(),seekg()是設置讀位置,seekp是設置寫位置。它們最通用的形式如下:


istream &seekg(streamoff offset,seek_dir origin);
ostream &seekp(streamoff offset,seek_dir origin);

streamoff定義於iostream.h中,定義有偏移量offset所能取得的最大值,seek_dir表示移動的基準位置,是一個有以下值的枚舉:


ios::beg:文件開頭
ios::cur:文件當前位置
ios::end:文件結尾

這兩個函數一般用於二進位文件,因為文本文件會因為系統對字符的解釋而可能與預想的值不同。

例:


file1.seekg(1234,ios::cur);//把文件的讀指針從當前位置向後移1234個字節
file2.seekp(1234,ios::beg);//把文件的寫指針從文件開頭向後移1234個字節
file1.seekg(-128,ios::end);//把文件的讀指針從文件末尾向前移128個字節

注意:一個漢字是佔用兩個字節的,一個字母佔用一個字節。

(5)fstream,stream;ifstream,istream;ofstream,ostream等的關係


三:實戰篇

(1)read word by word;no write

[cpp]

//讀取方式:逐詞讀取,詞之間用空格區分(遇到空格認為本次讀取結束),輸出之後進行下一次讀取

//read data from the file, Word By Word

//when used in this manner, we'll get space-delimited bits of text from the file

//but all of the whitespace that separated words (including newlines) was lost.

void ReadDataFromFileWBW()

{

ifstream fin("data.txt");

string s;

cout << "*****start*******" << endl;

while( fin >> s )

{

cout << "Read from file: " << s << endl;

}

cout << "*****over*******" << endl;

}

(2)read by line fin.getline(char*,n)

[cpp]

//讀取方式:逐行讀取,將行讀入字符數組,行之間用回車換行區分

//If we were interested in preserving whitespace,

//we could read the file in Line-By-Line using the I/O getline() function.

void ReadDataFromFileLBLIntoCharArray()

{

ifstream fin("data.txt",ios::in);// 默認的打開模式就是ios::in

ofstream fout("out.txt",ios::out);// 默認代開模式就是ios::out

const int LINE_LENGTH = 100;

char str[LINE_LENGTH];

fout << "****CharArray start******" << endl;

cout << "****CharArray start******" << endl;

fin.seekg(-20,ios::end);// -20表示從end向前移動20位元組,漢字佔兩字節;20表示向後移動指針

while(fin.getline(str,LINE_LENGTH))

{

fout << str << endl;

cout << "Read from file: " << str << "..." << endl;// ****str裡面本身包含著換行的,原來是什麼樣子,現在保存的就是什麼樣子

}

fout << "*****over*******" << endl;

cout << "*****over*******" << endl;

}

(3) read by line fin.getline(fin,string)

[cpp]

//讀取方式:逐行讀取,將行讀入字符串,行之間用回車換行區分

//If you want to avoid reading into character arrays,

//you can use the C++ string getline() function to read lines into strings

void ReadDataFromFileLBLIntoString()

{

ifstream fin("data.txt",ios::in);//默認的打開模式就是ios::in

ofstream fout("out.txt",ios::app);//追加到文件尾的方式打開

string s;

cout<<"****start******"<<endl;

while(getline(fin,s))

{

fout << s << endl;// ofstream是默認,若文件不存在,則先建立此文件,並且再向文件寫的過程中換行已經不存在了,這與cout控制臺輸出一樣哦。。。

cout << "Read from file: " << s << endl;//****s同str裡面本身已經沒有了換行的,這和原來的getline()函數是一樣的;數據原來是什麼樣子,現在保存的就是什麼樣子

}

fout << "*****over*******" << endl;

cout << "*****over*******" << endl;

fout.close();

}

(4) main函數

[cpp]

#include <iostream>

#include <fstream>

#include <string>

#include <cstdlib>// exit()函數

using namespace std;

//輸出空行

void OutPutAnEmptyLine()

{

cout<<"\n";

}

//帶錯誤檢測的讀取方式

//Simply evaluating an I/O object in a boolean context will return false

//if any errors have occurred

void ReadDataWithErrChecking()

{

string filename = "dataFUNNY.txt";

ifstream fin( filename.c_str());

if( !fin )

{

cout << "Error opening " << filename << " for input" << endl;

exit(-1);

}

}

int main()

{

ReadDataFromFileWBW();//逐詞讀入字符串

OutPutAnEmptyLine();//輸出空行

ReadDataFromFileLBLIntoCharArray();//逐詞讀入字符數組

OutPutAnEmptyLine();//輸出空行

ReadDataFromFileLBLIntoString();//逐詞讀入字符串

OutPutAnEmptyLine();//輸出空行

ReadDataWithErrChecking();//帶檢測的讀取

return 0;

}

data文本文件的數據格式


(5)總結

第一條,(寫了這麼多了,用兩句話概括吧)最近從網上,看到了一句很經典的話,c++的風fstream類+string類也可以非常好的處理文本文件;


第二條,語言僅僅是一種工具,本身並沒有優劣之分

相關焦點

  • c++ fstream + string 處理大數據
    起因(1)之前處理文本數據時,各種清洗數據用的都是java的File,FileReader
  • C++程序7 :IO流與異常處理
    >using namespace std;int main(){//1.處理字符串string info("ip地址: 192 168 12 1");cout << info << endl;//stringstream 構建對象//stringstream
  • C++:32---IO庫
    ostream,wostream向流寫入數據iostream,wiostream讀寫流fstreamifstream,wifstream從文件讀取數據ofstream,wofstream向文件寫入數據fstream,wfstream讀寫文件sstreamistringstream,wistringstream從string讀取數據ostringstream,wostringstream
  • 第二章 stringstream的使用
    從fstream說起 在C++標準庫中,fstream繼承至iostream,所以iostream該有的操作他都有,fstream還具有iostream不具有的能力——文件的度讀寫。 如同上一講的內容,文件的讀寫簡單點說就是將數據發送到指定的目的地或者是從指定的地方將數據取回來,所以,我們可以這麼來解讀iostream所幹的事——將這個目的地給固定了,而fstream卻可以自由指定這個目的地——文件,對於文件我們可以使用構造函數來指定,同樣可以使用open接口來重定向://+---#include <fstream>
  • C++文件讀寫詳解(ofstream,ifstream,fstream)
    #include <fstream>  ofstream           ifstream           fstream            1.打開文件在fstream類中,成員函數open()實現打開文件的操作,從而將數據流和文件進行關聯,通過ofstream,ifstream,fstream
  • C/C++頭文件一覽表
    #include <errno.h>     //定義錯誤碼#include <float.h>     //浮點數處理#include <fstream.h>    //文件輸入/輸出#include <iomanip.h>    //參數化輸入/輸出#include <iostream.h>
  • 在C++中將string轉換為char數組
    來自:https://www.linuxmi.com/c-string-char.html相信很多人都遇到過這樣一個錯誤:『cannot
  • C++基礎教程示例詳解:C++中的I/O重定向
    顧名思義i代表輸入inputo代表輸出outputstream//流iostream//輸入輸出流,這只是C++的一個流文件,因為C++的輸入輸出都是流處理的istream//就是只管輸入的流ostream//就是只管輸出的流(理論上應該是iostream包含了istream
  • C++標準庫和std命名空間
    string.h包含了C語言的最常用的字符串操作函數。ctype.h主要提供兩類重要的函數:字符測試函數和字符大小轉化函數。assert.h提供C語言斷言功能,唯一的目的是提供宏assert的定義。limits.h指明了基本數據類型的取值範圍。stddef.h定義了一些標準定義,許多定義也會出現在其他的頭文件裡。time.h獲取時間與日期,對時間與日期數據操作及格式化的頭文件。
  • C++ string 類詳解
    學習了C++string類以後,發現原來字符串處理可以這麼簡單。那麼本文會帶領大家回顧一下string類的相關操作,查缺補漏。—————【以下是正文】—————字符串是存儲在內存的連續字節中的一系列字符。C++ 處理字符串的方式有兩種,一種來自 C 語言,常被稱為 C-風格字符串,另一種是基於 string 類庫的字符串處理方式。
  • 自己實現 to_string 性能提升415%
    是不是還在使用 to_string,很影響性能的好不。零、背景之前在《你知道嗎?
  • json for modern c++的使用
    (給CPP開發者加星標,提升C/C++技能)導讀:json是一種十分常見的數據交換格式,在接口中被廣泛使用
  • 跟我學C++中級篇——STL中的字符串
    一、字符串在傳統的C/C++語言中,對字符串的處理比較麻煩,基本都是用char*來操作,而指針又往往是一個初學者的噩夢。STL為了解決這個問題,提供了std::string這個數據結構,其實它就是一個類,不過其提供了常見的對字符串的操作符的重載,實現在實際工程中經常遇到的字符串的長度計算,拼接和裁剪以及和C類型字符串的轉換。它不算是STL的容器,它只是一個類。
  • c++中的string常用函數用法總結
    標準c++中string類函數介紹注意不是CString之所以拋棄char*的字符串而選用
  • C++之字符串類學習總結
    一、回顧c語言對字符串的實現:一般我們在c語言要實現對字符串操作的話,一般是採用字符數組或者一組函數來實現的,為啥這樣做呢,那是因為c語言裡面根本就沒有字符串類型的關鍵字;而且c語言也支持自定義類型,所以更加無法獲得字符串類型為了解決這個問題,在c++
  • C++ 程式設計師 Protocol Buffers 基礎指南
    產生的類提供了構造 protocol buffer 的欄位的 getters 和 setters,並且作為一個單元來處理讀寫 protocol buffer 的細節。重要的是,protocol buffer 格式支持格式的擴展,代碼仍然可以讀取以舊格式編碼的數據。在哪可以找到示例代碼示例代碼被包含於原始碼包,位於「examples」文件夾。
  • 還不懂c++vector的用法,你憑什麼勇氣來的!
    今天給大家帶來一篇c++vector的介紹,難以置信這篇文章寫了我三天,不過總算整理完畢,現在分享給大家。模板類vector 和 array是數組的替代品。模板類vector 類似於string類,也是一種動態數組。 在 c++ 中,vector 是一個十分有用的容器。
  • 學習c++筆記——標準輸出流cout
    前和往常一樣,一邊喝早茶,一邊上網和女粉絲侃大山,在手機和平板電腦上整理修改《html5》、《javascript》、《css3》、《c語言》等多年前寫的教程(c++
  • C++之旅-string
    前言標準庫類型string表示可變長字符序列,使用之前需要包含string頭文件,它定義在命名空間std中。
  • C/C++中字符串與數字轉換
    作者:wxquare連結:https://www.cnblogs.com/wxquare/p/6529027.html本文總結了四種字符串和數字相互轉換的方法,方法一和方法二是c++方法一:c++11中string中添加了下面這些方法幫助完成字符串和數字的相互轉換stod stof stoi stol stold stoll stoul stoull函數原型:float stof (const string& str, size_t* idx = 0);to_string to_wstring