C++ read, write, modify, delete local file content

In the process of writing a program, sometimes it is necessary to read, store and modify some parameters or variables in the program locally, so it is necessary to master some operations of C++ on local files.

1. Read local files:

C++ is quite simple for reading and writing local files, mainly in the form of data streams, and the read strings are arranged in rows, and then detailed distinctions are made according to your own needs, such as strings Convert numbers, string splits, etc. A simple string reading function can probably be written like this:

void local_file_process::ReadLoaclFile()
{
    
    
    ifstream fin;  
    string file_path = "xxx";
    fin.open(file_path.c_str());
    string linestr;
    if(fin.is_open())//确认文本存在,is_open()用于确认该文本是否打开
    {
    
    
    	while (getline(fin, linestr))//行遍历
    	{
    
    
        //在这里进行你需要的数据处理     
    	}
    }
    else{
    
    
        ROS_ERROR("can not find locat file,check file path");
    }
    fin.close();
}

What needs to be noted here is that it is best to add a fin.is_open() judgment, because without this judgment, even if your path is incorrect, it will not report an error, but will not be able to read anything, which may lead to subsequent The entire processing of is wrong.

The second question is about opening the path here, I wrote it above:

    string file_path = "xxx";
    fin.open(file_path.c_str());

In fact, it can be written directly as:

	fin.open("xxx");

But notice that sometimes we may process local files in more than one place, so it will be troublesome and easy to miss later if we write them directly, so the best way is to use a global variable, so we only need to change One place is enough to ensure the stability and convenience of the code. But why is it not written here:

 	string file_path = "xxx";
    fin.open(file_path);

How about this?
This is due to the problem of the referenced open function. The open function is passed as open(const char* filepath). If you compile directly to the string type, no error will be reported, but the address cannot be found at runtime. Can be written like this:

 	const char* s;
    s = file_path.c_str();
    fin.open(s);  
    或者
    fin.open(file_path.c_str());
    c_str()生成一个const char *指针,指向字符串的首地址

But you must not give the string directly. Although the case of directly giving the address does look a lot like passing in a string.

2. Write local files:

The writing method is roughly similar to the reading method, just refer to the reference code for details:

void local_file_process::AddLoaclFile(vector<string> msg)
{
    
    
    //写入到文本最后面
    std::ofstream out(file_path.c_str(),std::ios::app);
    int len = msg.size();
    for(int i=0;i<len;i++)
    {
    
    
        out<<msg[i]<<endl;
    }
    out.close();
}

The code is very simple, you need to pay attention to one parameter: std::ios::app. Here you can choose std::ios::app and std::ios::ate. ios::app only writes at the end, but ios::ate reads and writes at the end by default. Also ios::ate can search freely in the file, but no matter what position you set for the write pointer, ios ::app will always be written last. So when executing here, I will put the newly entered parameters at the end of the file.

3. Modify the local file:

For example, I have a local file now, and I want to modify a certain line, what should I do? In C++, it seems that there is no function of line replacement for text, but we can solve this problem with a long string:

The idea is as follows: Create an empty string, read the text file line by line, save the lines that do not need to be modified in the string in the original order, and save the new line to the string when the line that needs to be modified is read , the original data is discarded. Then continue to save the following content until the entire text is read. Then clear the text and save the new string. This completes the modification of a certain line.

code show as below:

void local_file_process::ModifyLoaclFile(vector<string> msg)
{
    
    
    ifstream fin;  
    fin.open(file_path.c_str());
    string linestr;
    string strFileData = "";//暂存新的数据的地方
    int file_line = 0;
    int line = 1;
    int line_2 = 1;
    //查找需要修改的id是哪一个
    while (getline(fin, linestr))
    {
    
    
        file_line ++;
        if(linestr == msg[1])
            break;
        line++;
    }
    fin.close();
    //如果id存在,这里应相等
    if(file_line != line)
    {
    
    //如果说目前的库位信息中没有这个id信息,新增一个新的库位信息
        AddLoaclStorage(msg);
        return;
    }
    ifstream in;  
    in.open(file_path.c_str());
    //将需要修改的四行内容保存为新的msg。其他的行不变,暂存到strFileData
    while (getline(in, linestr))
    {
    
    
        if(line_2 == line-1)
        {
    
    
            strFileData += msg[0];
            strFileData += "\n";
        }
        else if(line_2 == line)
        {
    
    
            strFileData += msg[1];
            strFileData += "\n";
        }
        else if(line_2 == line+1)
        {
    
    
            strFileData += msg[2];
            strFileData += "\n";
        }
        else if(line_2 == line+2)
        {
    
    
            strFileData += msg[3];
            strFileData += "\n";
        }
        else
        {
    
    
            strFileData += linestr;
            strFileData += "\n";
        }
        line_2++;
    }
    in.close();
    ofstream out;
    out.open(file_path.c_str());
    out.flush();//清空file内容
    out<<strFileData;//写入修改后的数据
    out.close();
}

The function implemented by the above code is: pass in a container with four parameters: type, id, usage quantity, and total quantity. First, judge the current position that needs to be modified according to the incoming id. If there is no corresponding data in the file, add a new field. If there is, start to operate the file, find the location of the four lines of code, replace it with the new msg data, and keep the other data unchanged. This completes a modification of the local file.

4. Delete local files:

The method of deletion is the same as that of modification. Find the location to be deleted, cache other data in the string, and not store the ones that need to be deleted. Finally, empty the file and put in the new string. The simple implementation is as follows:

void local_file_process::DeleteLoaclFile(string msg)
{
    
    
    ROS_INFO("DeleteLoaclStorage");
    ifstream fin;  
    fin.open(file_path.c_str());
    string linestr;
    string strFileData = "";
    int file_line = 0;
    int line = 1;
    int line_2 = 1;
    while (getline(fin, linestr))
    {
    
    
        file_line++;
        if(linestr == msg)
            break;
        line++;
    }
    fin.close();
    if(file_line != line)
    {
    
    
        cout<<"delete "<<msg<<" failed,local storage has no this id"<<endl;
        return;
    }
    ROS_INFO("debug");
    ifstream in;  
    in.open(file_path.c_str());
    while (getline(in, linestr))
    {
    
    
        if(line_2 == line-1)
        {
    
    
            line_2++;
            continue;
        }
        else if(line_2 == line)
        {
    
    
            line_2++;
            continue;
        }
        else if(line_2 == line+1)
        {
    
    
            line_2++;
            continue;
        }
        else if(line_2 == line+2)
        {
    
    
            line_2++;
            continue;
        }
        else if(line_2 == line+3)
        {
    
    
            line_2++;
            continue;
        }
        else
        {
    
    
            strFileData += linestr;
            strFileData += "\n";
        }
        line_2++;
    }
    in.close();
    ofstream out;
    out.open(file_path.c_str());
    out.flush();
    out<<strFileData;
    out.close();
}

The function realized by the above code is: input a reference index and delete the 5 rows of data in the corresponding position. If there is no such index in the text itself, an error will be returned.

5. The header files involved:

#include "ros/ros.h"
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdio>
#include "std_msgs/String.h"
#include <boost/algorithm/string.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

6. Some other operations on strings:

6.1. String segmentation:

The boost library provides a function to split a string by a character:

	string linestr;
    vector<string> temp_sig;
	boost::split(temp_sig, linestr, boost::is_any_of( ":" ), boost::token_compress_on );

The first parameter is the storage location of the split string, a vector type container; the
second parameter is the string to be split, string type;
the third parameter is the character to split.

6.2. Convert string to number:

string temp = "123"
int numb = atoi(temp.c_str());
//或者
int numb = stoi(temp.c_str());

The stoi() function takes a string as an argument and returns its value. The atoi() function takes a character array or string literal as an argument and returns its value. atoi() is an old C style function. stoi() was added in C++11.
stoi() can take up to three arguments, the second for the starting index and the third for the base of the input number.

int stoi(const string&str , size_t* index = 0,int base = 10);

Similarly, for converting String to Double, atof() can be used. The above function returns the converted integer as an int value. It returns zero if no valid conversion can be performed.

6.3. Convert numbers to strings:

int numb = 123;
string temp = to_string(numb);

The to_string function can implement a simple operation of converting numbers to strings. In addition, itoa() can also achieve this function, but it is not as easy to use as to_string.

int n = 100;
char str2[10];
//字符串比较麻烦,所以转字符串三个参数,我是这么记得(手动滑稽) 
itoa(n,str2,10); //第一个参数为整数,第二个为字符串(char*),第三个为进制 
cout << str2 << endl;

6.4. String splicing:

To concatenate two strings, a simple "+" is fine, very convenient:

int a = 123;
string b = "id:";
string result = b + to_string(a);

This way you can get:

result = "id:123";

6.5. String search:

Search whether a string contains a certain substring or character: the find function, we can generally use it with judgment statements such as if to achieve certain conditions:

string a = "today is a good day";
if(a.find("good")==string::npos)
{
    
    
//如果没有该字符
}
else
{
    
    
//如果有该字符
}

Guess you like

Origin blog.csdn.net/YiYeZhiNian/article/details/128394165