欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++讀寫(CSV,Yaml,二進制)文件的方法詳解

 更新時間:2022年05月06日 08:29:59   作者:求則得之,舍則失之  
為了處理文件,我們可以利用fstream庫。在這個庫里面有三種數(shù)據(jù)類型:ofstream,ifstream,fstream。本文將利用這個庫實現(xiàn)不同文件的讀寫操作,需要的可以參考一下

介紹

為了處理文件,首先,導入 fstream 庫。 在這個庫里面有三種數(shù)據(jù)類型:

  • ofstream - 用于寫入文件
  • ifstream - 用于從文件中讀取
  • fstream - 用于讀取和寫入

為了打開文件,我們使用 open() 函數(shù)。 該函數(shù)接收兩個參數(shù):文件名和文件打開方式。

可以打開文件的模式如下:

  • ios::in - 打開要讀取的文件(ifstream 的默認值)
  • ios::out - 打開要寫入的文件(ofstream 的默認值)
  • ios::binary - 以二進制模式打開文件
  • ios::app- 打開文件以在末尾附加新信息
  • ios::ate - 打開并將控件移動到文件末尾
  • ios::trunc - 刪除現(xiàn)有文件中的數(shù)據(jù)
  • ios::nocreate - 僅在文件已存在時打開文件
  • ios::noreplace - 僅在文件不存在時打開文件

我們還可以使用符號 | 組合不同的模式 例如: myFile.open(“saldinaFile.txt”, ios::out | ios::in); 在此示例中,我們打開 saldinaFile.txt 進行寫入和讀取。

1.讀寫txt文件

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
	fstream myFile;
	myFile.open("saldina.txt", ios::out);  // write,清空再寫入
	if (myFile.is_open())
	{
		myFile << "Hello\n";
		myFile << "This is second line\n";
		myFile.close();
	}
	myFile.open("saldina.txt", ios::app);  // append,追加
	if (myFile.is_open())
	{
		myFile << "Hello2\n";
		myFile << "This is third line\n";
		myFile.close();
	}
	myFile.open("saldina.txt", ios::in);  // read,讀
	if (myFile.is_open())
	{
		string line;
		while (getline(myFile, line))
		{
			cout << line << endl;
		}
		myFile.close();
	}
}


2.C++讀寫CSV文件

據(jù)我所知,C++ STL 中沒有內(nèi)置 CSV 讀取器/寫入器。這不是對 C++ 的打擊。它只是一種低級語言。如果我們想用 C++ 讀寫 CSV 文件,我們將不得不處理文件 I/O、數(shù)據(jù)類型和一些關(guān)于如何讀取、解析和寫入數(shù)據(jù)的低級邏輯。對我來說,這是構(gòu)建和測試更多有趣程序(如機器學習模型)的必要步驟。

2.1 寫入CSV

這里,ofstream是一個“輸出文件流”。由于它派生自ostream,我們可以像對待cout一樣對待它(它也是派生自ostream)。執(zhí)行這個程序的結(jié)果是,我們在可執(zhí)行文件所在的目錄中得到了一個名為ones.csv的文件。讓我們將它封裝到write_csv()函數(shù)中。

#include <string>
#include <fstream>
#include <vector>

void write_csv(std::string filename, std::string colname, std::vector<int> vals){
    // Make a CSV file with one column of integer values
    // filename - the name of the file
    // colname - the name of the one and only column
    // vals - an integer vector of values
    
    // Create an output filestream object
    std::ofstream myFile(filename);
    
    // Send the column name to the stream
    myFile << colname << "\n";
    
    // Send data to the stream
    for(int i = 0; i < vals.size(); ++i)
    {
        myFile << vals.at(i) << "\n";
    }
    
    // Close the file
    myFile.close();
}

int main() {
    // Make a vector of length 100 filled with 1s
    std::vector<int> vec(100, 1);
    
    // Write the vector to CSV
    write_csv("ones.csv", "Col1", vec);
    
    return 0;
}

現(xiàn)在我們可以使用 write_csv() 輕松地將整數(shù)向量寫入 CSV 文件。讓我們對此進行擴展以支持多個整數(shù)向量和相應(yīng)的列名。

#include <string>
#include <fstream>
#include <vector>
#include <utility> // std::pair

void write_csv(std::string filename, std::vector<std::pair<std::string, std::vector<int>>> dataset){
    // Make a CSV file with one or more columns of integer values
    // Each column of data is represented by the pair <column name, column data>
    //   as std::pair<std::string, std::vector<int>>
    // The dataset is represented as a vector of these columns
    // Note that all columns should be the same size
    
    // Create an output filestream object
    std::ofstream myFile(filename);
    
    // Send column names to the stream
    for(int j = 0; j < dataset.size(); ++j)
    {
        myFile << dataset.at(j).first;
        if(j != dataset.size() - 1) myFile << ","; // No comma at end of line
    }
    myFile << "\n";
    
    // Send data to the stream
    for(int i = 0; i < dataset.at(0).second.size(); ++i)
    {
        for(int j = 0; j < dataset.size(); ++j)
        {
            myFile << dataset.at(j).second.at(i);
            if(j != dataset.size() - 1) myFile << ","; // No comma at end of line
        }
        myFile << "\n";
    }
    
    // Close the file
    myFile.close();
}

int main() {
    // Make three vectors, each of length 100 filled with 1s, 2s, and 3s
    std::vector<int> vec1(100, 1);
    std::vector<int> vec2(100, 2);
    std::vector<int> vec3(100, 3);
    
    // Wrap into a vector
    std::vector<std::pair<std::string, std::vector<int>>> vals = {{"One", vec1}, {"Two", vec2}, {"Three", vec3}};
    
    // Write the vector to CSV
    write_csv("three_cols.csv", vals);
    
    return 0;
}

在這里,我們將每列數(shù)據(jù)表示為 <column name, column values> 的 std::pair,并將整個數(shù)據(jù)集表示為此類列的 std::vector?,F(xiàn)在我們可以將可變數(shù)量的整數(shù)列寫入 CSV 文件。

2.2 讀取CSV文件(1)

現(xiàn)在我們已經(jīng)編寫了一些 CSV 文件,讓我們嘗試讀取它們?,F(xiàn)在讓我們假設(shè)我們的文件包含整數(shù)數(shù)據(jù)和頂部的一行列名。

#include <string>
#include <fstream>
#include <vector>
#include <utility> // std::pair
#include <stdexcept> // std::runtime_error
#include <sstream> // std::stringstream

std::vector<std::pair<std::string, std::vector<int>>> read_csv(std::string filename){
    // Reads a CSV file into a vector of <string, vector<int>> pairs where
    // each pair represents <column name, column values>

    // Create a vector of <string, int vector> pairs to store the result
    std::vector<std::pair<std::string, std::vector<int>>> result;

    // Create an input filestream
    std::ifstream myFile(filename);

    // Make sure the file is open
    if(!myFile.is_open()) throw std::runtime_error("Could not open file");

    // Helper vars
    std::string line, colname;
    int val;

    // Read the column names
    if(myFile.good())
    {
        // Extract the first line in the file
        std::getline(myFile, line);

        // Create a stringstream from line
        std::stringstream ss(line);

        // Extract each column name
        while(std::getline(ss, colname, ',')){
            
            // Initialize and add <colname, int vector> pairs to result
            result.push_back({colname, std::vector<int> {}});
        }
    }

    // Read data, line by line
    while(std::getline(myFile, line))
    {
        // Create a stringstream of the current line
        std::stringstream ss(line);
        
        // Keep track of the current column index
        int colIdx = 0;
        
        // Extract each integer
        while(ss >> val){
            
            // Add the current integer to the 'colIdx' column's values vector
            result.at(colIdx).second.push_back(val);
            
            // If the next token is a comma, ignore it and move on
            if(ss.peek() == ',') ss.ignore();
            
            // Increment the column index
            colIdx++;
        }
    }

    // Close file
    myFile.close();

    return result;
}

int main() {
    // Read three_cols.csv and ones.csv
    std::vector<std::pair<std::string, std::vector<int>>> three_cols = read_csv("three_cols.csv");
    std::vector<std::pair<std::string, std::vector<int>>> ones = read_csv("ones.csv");

    // Write to another file to check that this was successful
    write_csv("three_cols_copy.csv", three_cols);
    write_csv("ones_copy.csv", ones);
    
    return 0;
}

該程序讀取我們之前創(chuàng)建的 CSV 文件并將每個數(shù)據(jù)集寫入一個新文件,本質(zhì)上是創(chuàng)建原始文件的副本。

2.3 讀取CSV文件(2)

示例CSV文件如下所示。

在這個文件中,每行中的每個值都由逗號分隔。第一行表示列名,分別為姓名、性別和年齡。在每一行之后,都有一個換行符,該換行符存儲在內(nèi)部,在文件中不可見。文件中的每一行表示一個不同的記錄,而每個逗號分隔的值表示記錄的一個字段。

讀取 CSV 文件本質(zhì)上類似于讀取 C++ 中的所有其他文件。不同之處在于從行中提取值的方式。要讀取 CSV 文件,

  • 我們將使用C++ 庫的fstream 或 ifstream打開文件。然后,我們將使用getline()方法逐行讀取文件,因為每一行都以換行符結(jié)尾。
  • 該getline()方法將文件流作為其第一個輸入?yún)?shù),將一個字符串變量作為其第二個參數(shù)。執(zhí)行后,它將文件流的下一行存儲在字符串變量中。它還接受一個可選參數(shù)delimitor。如果我們將分隔符作為輸入?yún)?shù)傳遞,它會讀取文件直到找到分隔符。否則,它會讀取文件直到找到換行符。
  • 提取一行后,我們將使用stringstream提取該行中用逗號分隔的單詞。顧名思義,stringstream將字符串轉(zhuǎn)換為類似文件流的對象。
  • 在這里,我們將使用getline()方法來讀取由stringstream創(chuàng)建的字符串流。使用getline()時,除了字符串流和名為 word 的字符串變量外,我們還將,作為第三個參數(shù)傳遞給getline()函數(shù)。通過這種方式,getline()函數(shù)只讀取數(shù)據(jù),直到一行中的下一個逗號符號。
  • 我們將每個單詞存儲在一個名為row的向量中,每個單詞row存儲在一個名為content的二維向量中。執(zhí)行整個程序后,我們得到一個二維向量,其中每一行代表 CSV 文件中的一條記錄,每一行的每一列代表其中的數(shù)據(jù)。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
 
using namespace std;
 
int main()
{
	string fname;
	cout<<"Enter the file name: ";
	cin>>fname;
 
	vector<vector<string>> content;
	vector<string> row;
	string line, word;
 
	fstream file (fname, ios::in);
	if(file.is_open())
	{
		while(getline(file, line))
		{
			row.clear();
 
			stringstream str(line);
 
			while(getline(str, word, ','))
				row.push_back(word);
			content.push_back(row);
		}
	}
	else
		cout<<"Could not open the file\n";
 
	for(int i=0;i<content.size();i++)
	{
		for(int j=0;j<content[i].size();j++)
		{
			cout<<content[i][j]<<" ";
		}
		cout<<"\n";
	}
 
	return 0;
}

上述代碼的輸出如下所示。我們使用上面給出的 CSV 文件作為程序的輸入。

2.4 用c++讀寫二進制文件(1)

/**
 * @description - Read any ASCII,BINARY or HEX file.
 * @param - Source file name and file type.
 * @return - Returns data in tuple format,use std::get<TUPLE_ID>(TUPLE_OBJ) to get data.
 */
/*Including STD-C++ libraries*/
#include <iostream> /*For basic I/O.*/
#include <fstream> /*For basic I/O.*/
#include <sstream> /*For basic I/O.*/
#include <vector> /*For STL vector.*/
#include <tuple>  /*For packing multi data.*/

using std::string;

#define BINARY_FILE 0
#define ASCII_FILE 1
#define HEX_FILE 2
std::tuple<std::vector<uint8_t>, string, string> ReadFile(string, int);
bool WriteFile(string file_name, string, int);

/*
Example of binary file:
	auto file_type = ReadFile("user_data.dat", BINARY_FILE);
	auto file_data = std::get<BINARY_FILE>(file_type);

Example of ASCII file:
	auto file_type = ReadFile("my_file.txt", ASCII_FILE);
	auto file_data = std::get<ASCII_FILE>(file_type);
*/

std::tuple<std::vector<uint8_t>, string, string> ReadFile(string file_name, int file_type)
{
	/*Buffers to store output data from file.*/
	string str_buf, hex_buf;
	std::vector<uint8_t> vec_buf;

	try {
		if (file_type == BINARY_FILE) {

			/*Open the stream in binary mode.*/
			std::ifstream bin_file(file_name, std::ios::binary);

			if (bin_file.good()) {
				/*Read Binary data using streambuffer iterators.*/
				std::vector<uint8_t> v_buf((std::istreambuf_iterator<char>(bin_file)), (std::istreambuf_iterator<char>()));
				vec_buf = v_buf;
				bin_file.close();
			}

			else {
				throw std::exception();
			}

		}

		else if (file_type == ASCII_FILE) {

			/*Open the stream in default mode.*/
			std::ifstream ascii_file(file_name);
			string ascii_data;

			if (ascii_file.good()) {
				/*Read ASCII data using getline*/
				while (getline(ascii_file, ascii_data))
					str_buf += ascii_data + "\n";

				ascii_file.close();
			}
			else {
				throw std::exception();
			}
		}

		else if (file_type == HEX_FILE) {

			/*Open the stream in default mode.*/
			std::ifstream hex_file(file_name);

			if (hex_file.good()) {
				/*Read Hex data using streambuffer iterators.*/
				std::vector<char> h_buf((std::istreambuf_iterator<char>(hex_file)), (std::istreambuf_iterator<char>()));
				string hex_str_buf(h_buf.begin(), h_buf.end());
				hex_buf = hex_str_buf;

				hex_file.close();
			}
			else {
				throw std::exception();
			}
		}

	}

	catch (std::exception const& ex) {
		string ex_str = "Error: " + file_name + ": No such file or directory";
		throw std::exception(ex_str.c_str());
	}

	auto tuple_data = make_tuple(vec_buf, str_buf, hex_buf);
	return tuple_data;
}

/**
 * @description - Write data to any ASCII,BINARY or HEX file.
 * @param - Source file name, file data and file type.
 * @return - Returns true on successfully written data otherwise returns false.
 */

bool WriteFile(string file_name, string file_data, int file_type)
{
	bool write_status = false;
	std::ofstream out_stream(file_name, (file_type == ASCII_FILE) ? std::ios::out : (file_type == BINARY_FILE || file_type == HEX_FILE) ? std::ios::binary : std::ios::out);

	if (out_stream.is_open()) {
		if (file_type == ASCII_FILE) {
			out_stream << file_data;
			write_status = true;
		}

		else if (file_type == BINARY_FILE) {
			out_stream << file_data;
			write_status = true;
		}

		else if (file_type == HEX_FILE) {
			int bin_data;
			std::stringstream ss;
			ss << std::hex << file_data;

			while (ss >> bin_data)
				out_stream.write(reinterpret_cast<const char*>(&bin_data), sizeof(char));

			write_status = true;
		}
		out_stream.close();
	}
	else {
		string ex_str = "Error: couldn't open " + file_name + " for output";
		throw std::exception(ex_str.c_str());
	}
	return write_status;
}

2.5 用c++讀寫二進制文件(2)

1.寫

用C++寫二進制文件,請使用write方法,它用于在給定流上寫入給定數(shù)量的字節(jié),從put指針的位置開始。如果put指針當前位于文件的末尾,則擴展文件。如果該指針指向文件的中間,則文件中的字符將被新數(shù)據(jù)覆蓋。如果在寫入文件期間發(fā)生了任何錯誤,則將流置于錯誤狀態(tài)。

寫方法的語法:ostream& write(const char*, int);

2.讀

要在c++中讀取二進制文件,請使用read方法。它從給定的流中提取給定數(shù)量的字節(jié),并將它們放入由第一個參數(shù)指向的內(nèi)存中。如果在讀取文件期間發(fā)生任何錯誤,則將流置于錯誤狀態(tài),隨后所有的讀取操作都將失敗。

gcount()可用于統(tǒng)計已經(jīng)讀取的字符數(shù)。然后可以使用clear()將流重置為可用狀態(tài)。

讀方法的語法:ifstream& write(const char*, int);

3.偽代碼

Begin
   Create a structure Student to declare variables.
   Open binary file to write.
   Check if any error occurs in file opening.
   Initialize the variables with data.
   If file open successfully, write the binary data using write method.
      Close the file for writing.
   Open the binary file to read.
   Check if any error occurs in file opening.
   If file open successfully, read the binary data file using read method.
      Close the file for reading.
   Check if any error occurs.
   Print the data.
End.

4.示例代碼

#include<iostream>
#include<fstream>
using namespace std;
struct Student {
   int roll_no;
   string name;
};
int main() {
   ofstream wf("student.dat", ios::out | ios::binary);
   if(!wf) {
      cout << "Cannot open file!" << endl;
      return 1;
   }
   Student wstu[3];
   wstu[0].roll_no = 1;
   wstu[0].name = "Ram";
   wstu[1].roll_no = 2;
   wstu[1].name = "Shyam";
   wstu[2].roll_no = 3;
   wstu[2].name = "Madhu";
   for(int i = 0; i < 3; i++)
      wf.write((char *) &wstu[i], sizeof(Student));
   wf.close();
   if(!wf.good()) {
      cout << "Error occurred at writing time!" << endl;
      return 1;
   }
   ifstream rf("student.dat", ios::out | ios::binary);
   if(!rf) {
      cout << "Cannot open file!" << endl;
      return 1;
   }
   Student rstu[3];
   for(int i = 0; i < 3; i++)
      rf.read((char *) &rstu[i], sizeof(Student));
   rf.close();
   if(!rf.good()) {
      cout << "Error occurred at reading time!" << endl;
      return 1;
   }
   cout<<"Student's Details:"<<endl;
   for(int i=0; i < 3; i++) {
      cout << "Roll No: " << wstu[i].roll_no << endl;
      cout << "Name: " << wstu[i].name << endl;
      cout << endl;
   }
   return 0;
}

輸出:

Student’s Details:
Roll No: 1
Name: Ram
Roll No: 2
Name: Shyam
Roll No: 3
Name: Madhu

2.6 用c++讀寫二進制文件(3)

1.問題描述

我使用以下代碼創(chuàng)建一個簡單的二進制文件。

ofstream outfile("binary.txt", ofstream::binary);
string text = "Hello cplusplus forum!";
outfile.write((char*)&text, text.size());
outfile.close();

當我打開此文件時,它是二進制文件,但每當我嘗試使用此代碼將此文件讀回程序時:

char* buffer = (char*)malloc(sizeof(string));
ifstream infile("binary.txt", ifstream::binary);
infile.read(buffer, sizeof(string));
string* elem = (string*)buffer;
cout << *elem << '\n';
infile.close();

程序和Visual Studio崩潰了。

2.解答

第一部分有幾個問題:

ofstream outfile("binary.txt", ofstream::binary);
string text = "Hello cplusplus forum!";
outfile.write((char*)&text, text.size());
outfile.close();

該代碼可能會毫無問題地運行。但是文件 binary.txt 中包含什么?對于這類工作,十六進制編輯器很有用。在 Windows 上,您可以嘗試 Hxdhttps://mh-nexus.de/en/hxd/

在我的系統(tǒng)上看到的是這樣的:TA>.$ÀÂw..>.LXH.èUH.@? 這很沒有意義。這是因為字符串對象可能不包含字符串的文本,而是包含指向堆上保存的字符串的指針,以及可能的一些其他信息。

第一步是編寫字符串本身的實際文本內(nèi)容。

可以通過替換第3行來實現(xiàn):outfile.write((char*)&text, text.size());改為outfile.write( text.c_str(), text.size());

現(xiàn)在,如果您再看一下文件的內(nèi)容,它應(yīng)該更有意義。

但這仍然留下一個問題。你將如何讀回它?如果這就是文件包含的所有內(nèi)容,這很容易,只需閱讀到文件末尾即可。但是,如果您只想讀取原始字符串,不多也不少怎么辦?

那么你可以先在文件中存儲大小。像這樣:

unsigned int size = text.size();
outfile.write(reinterpret_cast<char *>(&size), sizeof(size)  );

要讀取文件,請按相反的步驟執(zhí)行。

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
    
int main()
{   

    string text = "Hello cplusplus forum!";

    ofstream outfile("binary.txt", ofstream::binary);
    unsigned int size = text.size();                                 // get the size
    outfile.write(reinterpret_cast<char *>(&size), sizeof(size)  );  // write it to the file
    outfile.write( text.c_str(), text.size() );                      // write the actual text
    outfile.close();


    //----------------------------------------

    ifstream infile("binary.txt", ifstream::binary);
    
    // read the size
    size = 0;        
    infile.read(reinterpret_cast<char *>(&size), sizeof(size)  );
    
    // Allocate a string, make it large enough to hold the input
    string buffer;
    buffer.resize(size);
    
    // read the text into the string
    infile.read(&buffer[0],  buffer.size() );
    infile.close();    
    
    cout << "buffer = \n" << buffer << '\n';
    
}

3.C++讀寫Yaml文件

它的基本語法規(guī)則如下:

  • 大小寫敏感
  • 使用縮進表示層級關(guān)系
  • 縮進時不允許使用Tab鍵,只允許使用空格。
  • 縮進的空格數(shù)目不重要,只要相同層級的元素左側(cè)對齊即可

YAML支持的數(shù)據(jù)結(jié)構(gòu)有三種。

  • 對象:鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 數(shù)組:一組按次序排列的值,又稱為序列(sequence) / 列表(list)
  • 純量(scalars):單個的、不可再分的值

一般常用yaml-cpp和OpenCV進行解析

相比yaml-cpp,OpenCV的優(yōu)點是可以在YAML文件中存儲矩陣,讀出來就是cv::Mat格式;缺點是OpenCV要求YAML文件有一個特殊的頭,與標準的YAML文件并不兼容?;蛘咭部梢岳斫鉃镺penCV定義了一種新的YAML格式。

# 表示注釋,從這個字符一直到行尾,都會被解析器忽略。

3.1安裝yaml-cpp

https://github.com/jbeder/yaml-cpp/

編譯環(huán)境

  • Windows10
  • VS2019
  • cmake-3.19.8-win64-x64

yaml-cpp的編譯

將下載好的yaml-cpp-master.zip進行解壓,在源碼目錄下創(chuàng)建一個build文件夾并進入這個文件夾

mkdir build
cd build
cmake ..

接著將會看到在build目錄下有一個名為YAM_-CPP.sln的文件,用VS打開它

對ALL_BUILD生成解決方案,成功生成后,會在build/Debug目錄下得到y(tǒng)aml-cppd.lib文件

3.2 yaml文件的解析(1)

1)config.yaml配置文件

custom_db:
    db_domain: 10.0.0.8
    db_username: root
    db_passwd: my_passwd
    db_schema: test

redis:
    redis_domain: 10.0.0.10
    redis_passwd: 123456

hello:
    num_config: [1141studio]
    name_config: [powered, by, 1141studio]

2)config_test.cpp

#include <iostream>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include "yaml-cpp/yaml.h"
#include <vector>
const std::string DB_CONF = "config.yaml";
int main(int argc, char * argv[]) {
    /*----------------------------------- test yaml ----------------------------------------*/
    printf("hello world\n");
    std::cout << "this code is only for test yaml" << std::endl;

    /* Node conf. */
    YAML::Node conf = YAML::LoadFile(DB_CONF);
    
    /*----------------------------------- display db_config ----------------------------------------*/
    std::cout << "Database:"<< std::endl;
    std::cout << "domain:  " << conf["custom_db"]["db_domain"].as<std::string>() << std::endl;
    std::cout << "username:" << conf["custom_db"]["db_username"].as<std::string>() << std::endl;
    std::cout << "passwd:  " << conf["custom_db"]["db_passwd"].as<std::string>() << std::endl;
    std::cout << "schema:  " << conf["custom_db"]["db_schema"].as<std::string>() << std::endl;

    /*----------------------------------- display redis ----------------------------------------*/
    std::cout << "Redis" << std::endl;
    std::cout << "redis_domain: " << conf["redis"]["redis_domain"].as<std::string>() << std::endl;
    std::cout << "redis_passwd: " << conf["redis"]["redis_passwd"].as<std::string>() << std::endl;
    
    /*----------------------------------- display hello ----------------------------------------*/
    std::cout << "HelloServer" << std::endl;
    
    /* vector of name string. */
    std::vector<std::string> name_vec = conf["hello"]["num_config"].as<std::vector<std::string> >();
    if(!name_vec.empty())
      std::cout << name_vec[0] << std::endl;
    return 0;
}

3)CmakeLists.txt配置情況如下

cmake_minimum_required(VERSION 3.5.1)
project(nanodet-mnn)
SET(CMAKE_BUILD_TYPE "Release")

SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/)

# yaml-cpp的包含目錄
include_directories("/gzy_mnt/YAML_X86/include")
file(GLOB SOURCE_FILES *.cpp)
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES})

target_link_libraries (
        ${CMAKE_PROJECT_NAME}   
        pthread
        /gzy_mnt/YAML_X86/lib/libyaml-cpp.so
)

3.3 yaml文件的解析(2)

config.yaml配置文件

name: frank
sex: male
age: 18
 
skills: 
    c++: 1
    java: 1
    android: 1
    python: 1

config_demo.cpp

#include <iostream>
#include "yaml-cpp/yaml.h"
#include <fstream>
 
using namespace std;
 
int main(int argc,char** argv)
{
    YAML::Node config;
    try{
         config = YAML::LoadFile("../config.yaml");
    }catch(YAML::BadFile &e){
        std::cout<<"read error!"<<std::endl;
        return -1;
    }
    
    cout << "Node type " << config.Type() << endl;
    cout << "skills type " << config["skills"].Type() << endl;
 
    //可以用string類型作為下表,讀取參數(shù)
    string age = "age";
    cout << "age when string is label:" << config[age].as<int>() << endl;
 
    cout << "name:" << config["name"].as<string>() << endl;
    cout << "sex:" << config["sex"].as<string>() << endl;
    cout << "age:" << config["age"].as<int>() << endl;
 
    //讀取不存在的node值,報YAML::TypedBadConversion異常
    try{
        string label = config["label"].as<string>();
    }catch(YAML::TypedBadConversion<string> &e){
        std::cout<<"label node is NULL"<<std::endl;
    }//TypedBadConversion是模板類,讀取什么類型的參數(shù)就傳入什么類型
 
 
    cout << "skills c++:" << config["skills"]["c++"].as<int>() << endl;
    cout << "skills java:" << config["skills"]["java"].as<int>() << endl;
    cout << "skills android:" << config["skills"]["android"].as<int>() << endl;
    cout << "skills python:" << config["skills"]["python"].as<int>() << endl;
     // yaml-cpp 中也可以通過迭代的方式,訪問 Node 中的內(nèi)容。
    // 比如,訪問 skills 下面的各個元素。
    for(YAML::const_iterator it= config["skills"].begin(); it != config["skills"].end();++it)
    {
        cout << it->first.as<string>() << ":" << it->second.as<int>() << endl;
    }
 
    YAML::Node test1 = YAML::Load("[1,2,3,4]");
    cout << " Type: " << test1.Type() << endl;
 
    YAML::Node test2 = YAML::Load("1");
    cout << " Type: " << test2.Type() << endl;
 
    YAML::Node test3 = YAML::Load("{'id':1,'degree':'senior'}");
    cout << " Type: " << test3.Type() << endl;
 
    ofstream fout("./testconfig.yaml"); //保存config為yaml文件
 
    config["score"] = 99;//添加新元素
 
    fout << config;
 
    fout.close();
 
 
    return 0;
}

3.4 node的增刪改查

#include <fstream>
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <assert.h>
 
int main()
{
    YAML::Node node;  
    assert(node.IsNull());  //初始化的節(jié)點是Null類型
    node["key"] = "value";  //當你給它賦值鍵值對,它轉(zhuǎn)變?yōu)镸ap類型
    //node.force_insert("key", "value");//這個操作和上面等價,但是它不會檢查是否存在"key"鍵,不推薦使用
    if(node["mascot"])
        std::cout << node["mascot"].as<std::string>() << "\n";//單純的查詢操作不會增加一個key,當然上面的if不會執(zhí)行
 
    node["number"] = 255;
    assert(node.IsMap());   //node是一個Map
    node["seq"].push_back("first element");
    node["seq"].push_back("second element");//node的seq下是Sequence類型,有兩個參數(shù)
 
    YAML::Node node_2;  
    node_2.push_back("first item");//如果你不給node_2鍵值對,它是一個sequence類型
    node_2.push_back("second_item");
    node_2.push_back("third_item");
    std::vector<int> v = {1,3,5,7,9};//給node_2插入了一個Sequence
    node_2.push_back(v);
    assert(node_2.IsSequence());//當然,node_2仍然是一個Sequence
 
    assert(node_2[0].as<std::string>() == "first item");
    //對于Sequence類型,你可以使用它的下標來訪問
    //注意這里as<T>是一個模板轉(zhuǎn)換,node_2[0]的type是NodeType::Scalar
    auto it = node_2.begin();
    for(; it != node_2.end(); it++)
        std::cout << *(it) << std::endl;
    //當然,你也可以用迭代器來訪問
    //他們的類型分別是NodeType::Scalar,NodeType::Scalar,NodeType::Scalar,NodeType::Sequence
    //取值時記得使用as進行模板轉(zhuǎn)換
    node_2["key"] = "value";
    assert(node_2.IsMap());//一旦node_2接收到鍵值對,它轉(zhuǎn)變?yōu)镸ap類型
    assert(node_2[0].as<std::string>() == "first item");//此時,Sequence時的下標變?yōu)樗膋ey值
    node["node_2"] = node_2;//將node_2作為node的一個子項
    node["pointer_to_first_element"] = node["seq"][0];//你也可以給已有的node設(shè)置一個別名,類似于一個指針
    assert(node["pointer_to_first_element"].as<std::string>() == "first element");//你可以通過這個指針訪問那個node
 
    node.remove(node["seq"][0]);//你可以通過指定一個node來刪除它
    node.remove("pointer_to_first_element");//你也可以通過指定key來刪除它
}

如果你執(zhí)行std::cout<<node<<endl;

應(yīng)該會得到以下結(jié)果

key: value
number: 255
seq:
  - first element
  - second element
node_2:
  0: first item
  1: second_item
  2: third_item
  3:
    - 1
    - 3
    - 5
    - 7
    - 9
  key: value

以上就是C++讀寫文件(CSV,Yaml,二進制)的方法詳解的詳細內(nèi)容,更多關(guān)于C++讀寫文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論