Tool Class Library Series (iv)-csvreader

Source: Internet
Author: User
Tags bool readline reserved first row

Fourth Tool class: Csvreader


Csvreader is used to support reading CSV tables.


CSV format is actually a fixed format of txt, a row of each column in English ', ' separated


There are many game static tables in the game project. The plan provides a CSV form that can be easily edited with Excel. Client unity also tends to read CSV tables, plain text, simple format, easy to read


Then for the sake of reading more convenient, we have defined the CSV first 3 lines of content has special significance, the following figure is an example


Column name for each of the first row

Each column of the second row is of type

Each column in the third row contains a description of the name in Chinese

Line four starts with the actual data


Specify the supported column types

4 Basic types:

U: corresponds to unsigned int

I: corresponding int

F: corresponds to float

S: corresponding std::string

substructure: If the column is a sub-structure, specify the field name and field type of the sub-structure, in English semicolon '; ' Segmentation

As shown above in the structid;u; Structnum;i; Structfloat;f; Strucename;s:

Indicates that the substructure has 4 fields: structid,unsigned int type, structnum,int type, structfloat,float type, Strucename, String type

Segmentation of the actual data between the neutron structure fields in English and the operator ' & '

As in the figure above, 1&-2&3.4&AAA:

Represents STRUCTID=1,STRUCTNUM=-2,STRUCTFLOAT=3.4F,STRUCENAME=AAA, {1,-2, 3.4f, "AAA"}


Qualified type of column type:

K: Indicates that the column is a primary key and is used as an index

Supports up to 3 column primary keys, or 3 columns combined to determine a unique row of records

The primary key is not necessarily in the first 3 columns, you can use some of the middle columns

The type of the primary key is qualified as an integer, that is, the column type after k is I or u

LST: Indicates that the column is a variable-length array

As listed above, Lst:u:

Indicates that the column is an array of unsigned int, which corresponds to std::vector<unsigned int>

As in the above example, lst:structid;u; Structnum;i; Structfloat;f; Strucename;s:

An array that indicates that the column is a sub-structure

The actual data in the array between the elements and elements in English semicolon '; ' Segmentation

As in the example above 1&-2&3.4&AAA;5&-6&7.8&BBB:

Indicates that the sub-structure array has 2 elements, the first element is {1,-2, 3.4f, "AAA"}, the second element is {5,-6, 7.8f, "BBB"}


K or LST followed by the English colon ":" followed by the specific column type


The above is a man-made rule


So for a table like this, the structure that reads into memory corresponds to the following:

Class Struct
{public
:
	unsigned int m_structid;
	int m_structnum;
	float m_structfloat;
	std::string m_strucename;
};

Class Test
{public
:
	unsigned int m_id1;	Test PRIMARY key 1
	int m_id2;	Test PRIMARY key 2
	unsigned int m_id3;	Test PRIMARY Key 3
	std::string m_str;	Test string
	std::vector<unsigned int> m_uints;	Test number list
	float m_float;	Test the digital
	Struct m_struct;	Test sub-structure
	std::vector<struct> m_structlists;	Test sub-structure list
};


The csvreader of this paper is a tool class to read the corresponding class object in order to realize the CSV file which is specified in the above-described format.

The next article will write a code auto-generation tool that automatically generates code for the class object corresponding to each table

(Because the plan to modify the table structure is very frequent, the table structure once modified, the corresponding class structure will be modified, simply automatically generate trouble)


Csvreader provides several interfaces:

1, ReadLine, read a line of content, read into a cache, in CSV format reserved delimiter comma ', ', divided into the value of each column

Here is a file encoding problem, that is, under Windows, Utf8 format file has a BOM header, that is, the first 3 bytes of the file is 0XEF,0XBB,0XBF need to filter out, the line at the end of the ' \ R ', ' \ n ', need to filter out

2, Checkline, check the number of columns separated by a comma, and whether the column name of the first row is the same as the number of columns

If not, the actual data, especially the string type of the column, there is a comma in English, but the comma is a CSV file reserved delimiter

So if there is a comma in the actual data, there is no way to determine which column corresponds to which column.

3, Name2index, according to the column name, returns the column is the first column, the top 0

4, GetValue, read the value of column of single field type (non-array)

5, Getvaluelist, reading the value of the array column

6, LoadFile, load the specified file, and process the first 3 lines of content, identify the column name, and the number of columns


For sub-structures, the substructure overload assignment operator is required and the argument is a string, as

xxx& operator = (const std::string &other) for parsing a string like "1&-2&3.4&aaa" in the previous example


It also uses the previously mentioned Stringtool, which is used for string segmentation, and whether the checksum is a valid number


On the Code

CsvReader.h

#ifndef __csvreader_h__ #define __CSVREADER_H__ #include <string> #include <vector> #include <map> #in Clude <fstream> #include "StringTool.h" namespace common{namespace tool{class Csvreader {public:csv
			Reader ();

			~csvreader ();

			CSV file opens bool OpenFile (const std::string& file_path_name);

			CSV file opens and processes the first 3 rows of data bool LoadFile (const std::string& file_path_name);

			Reads a row of data (the first line to the BOM, the end of each line line newline character) size_t ReadLine (bool Firstline = false);

			After reading a row of data, get the original contents of each column const std::vector<std::string>& GetLine ();

			Check whether the number of columns matches the number of column names bool Checkline ();

			The column number is obtained according to the column name, the first column is numbered 0 size_t name2index (const std::string& name); Take the value of a column of the current row bool Getvaluelist (size_t index, std::vector<std::string>& values, const std::string& split)

			;

			BOOL GetValue (size_t index, std::string& value);

			BOOL Getvaluelist (size_t index, std::vector<unsigned int>& values, const std::string& split);BOOL GetValue (size_t index, unsigned int& value);

			BOOL Getvaluelist (size_t index, std::vector<int>& values, const std::string& split);

			BOOL GetValue (size_t index, int& value);

			BOOL Getvaluelist (size_t index, std::vector<float>& values, const std::string& split);

			BOOL GetValue (size_t index, float& value); Template <class t> bool Getstructlist (size_t index, std::vector<t>& values, const std::string& SPLI

			T);

		Template <class t> bool Getstruct (size_t index, t& value);

			Private://File input stream Std::ifstream m_file;
			Column name <-> column subscript mapping table std::map<std::string, size_t> m_names;
		The value of each column of the current row std::vector<std::string> m_values;

		}; Template <class t> bool Csvreader::getstructlist (size_t index, std::vector<t>& values, const Std::strin
				g& split) {if (Index < m_values.size ()) {std::vector<std::string> tempstrs; Stringtool:: Splitstr2list (M_values[index], split, tempstrs);
						for (size_t i = 0; i < tempstrs.size (); i++) {if (tempstrs[i].length () > 0) {t tempt;
						tempt = Tempstrs[i];
					Values.push_back (tempt);
			}} return true;
			} else {return false; }} template <class t> bool Csvreader::getstruct (size_t index, t& value) {if (Index < M_VALUES.S
				Ize ()) {value = M_values[index];
			return true;
			} else {return false; }}} #endif


CsvReader.cpp

#include "CsvReader.h" #include <string.h> namespace common{namespace tool{const unsigned int maxlinelen = 1
		0240;

		Const std::string csvsplit = ",";
			Csvreader::csvreader () {m_names.clear ();
		M_values.clear ();
			} csvreader::~csvreader () {m_names.clear ();

			M_values.clear ();
			if (m_file) {m_file.close ();
				}} size_t Csvreader::readline (bool firstline) {if (m_file) {char Line[maxlinelen];
				memset (line, 0x00, sizeof (char) * maxlinelen);
				M_file.getline (line, Maxlinelen);

				size_t len = strlen (line);
							Remove first line BOM if (3 <= len) {if (firstline) {if (0xEF = = (unsigned char) line[0] && 0xBB = = (unsigned char) line[1] && 0xBF = = (unsigned char) line[2] {memcpy (line, line + 3, l
							En + 1-3);
						len = len-3; }}}//Remove the end of each line \ r \ n while (1 <= len) {if (' \ r ' = = Line[len-1] | |
					' \ n ' = = Line[len-1]) {	Line[len-1] = ' + ';
					len = len-1;
					} else {break;
					}} if (0 < len) {m_values.clear ();
				Stringtool::splitstr2list (line, Csvsplit, m_values);
			} return len;
			} else {return 0;
		}} const std::vector<std::string>& Csvreader::getline () {return m_values;
			} bool Csvreader::checkline () {if (m_values.size () = = M_names.size ()) {return true;
			} else {return false; }} bool Csvreader::openfile (const std::string& file_path_name) {M_file.open (File_path_name.c_str (), std::i
			Os::in);
			if (M_file) {return true;
			} else {return false; }} bool Csvreader::loadfile (const std::string& file_path_name) {M_file.open (File_path_name.c_str (), std::i
			Os::in);
				if (m_file) {//Read column name ReadLine (TRUE); Save column names, use for field validation, and subscript for column names for (size_t i = 0; i < m_values.size (); i++) {M_names[stringtool:: Upcasefirstchar (m_values[i])] = i;

				}//Read column type ReadLine ();

				Read comment ReadLine ();
			return true;
			} else {return false;  }} size_t Csvreader::name2index (const std::string& name) {std::map<std::string, size_t>::iterator it
			= M_names.find (name);
			if (it = M_names.end ()) {return it->second;
			} else {return-1; }} bool Csvreader::getvaluelist (size_t index, std::vector<std::string>& values, const std::string& SPL It) {if (Index < m_values.size ()) {if (0 < M_values[index].length ()) {stringtool::splitstr2l
				IST (M_values[index], split, values);
			} return true;
			} else {return false; }} bool Csvreader::getvalue (size_t index, std::string& value) {if (Index < m_values.size ()) {VA
				Lue = M_values[index];
			return true;
			} else {return false; }} bool Csvreader::getvaluelist (size_t index, STD::Vector<unsigned int>& values, const std::string& split) {if (Index < m_values.size ()) {if (0
				< M_values[index].length ()) {return stringtool::splitstr2list (M_values[index], split, values);
			} return true;
			} else {return false; }} bool Csvreader::getvalue (size_t index, unsigned int& value) {if (Index < m_values.size ()) {I 
					F (Stringtool::isuint (M_values[index])) {value = static_cast<unsigned int> (atoi (M_values[index].c_str ()));
				return true;
				} else {return false;
			}} else {return false;
			}} bool Csvreader::getvaluelist (size_t index, std::vector<int>& values, const std::string& split) { if (Index < m_values.size ()) {if (0 < M_values[index].length ()) {return Stringtool::splitstr2li
				St (M_values[index], split, values);
			} return true;
			} else {return false; }} bool CSvreader::getvalue (size_t index, int& value) {if (Index < m_values.size ()) {if (Stringtool::isint (m_v
					Alues[index]) {value = Atoi (M_values[index].c_str ()));
				return true;
				} else {return false;
			}} else {return false;
		}} bool Csvreader::getvaluelist (size_t index, std::vector<float>& values, const std::string& split) {if (Index < m_values.size ()) {if (0 < M_values[index].length ()) {return STRINGTOOL::SPLITSTR2
				List (M_values[index], split, values);
			} return true;
			} else {return false; }} bool Csvreader::getvalue (size_t index, float& value) {if (Index < m_values.size ()) {if (stri
					Ngtool::isfloat (M_values[index])) {value = Static_cast<float> (Atof (M_values[index].c_str ()));
				return true;
				} else {return false;
			}} else {return false; }
		}

	}
}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.