用c ++更改文件内容

时间:2013-09-23 12:52:40

标签: c++

考虑以下文件内容

[channels]
usecallerid=yes
cidsignalling=dtmf 
cidstart=dtmf


;group=0
usecallerid=yes
context=pstn-channels
channel=>5

;group=0
usecallerid=yes
context=pstn-channels
channel=>6

;group=0
usecallerid=yes
context=pstn-channels
channel=>7

;group=1
context=phone-channels
channel=>1-4

我只是想搜索一个频道,用c ++改变该频道的一些属性。关键是每个通道的属性都写在“channel”关键字之上。 例如,我需要将频道5的上下文属性更改为phone。 我怎么能这样做?

编辑:

所以我终于找到了办法。我逐行读取文件,查找“group”关键字,在到达此关键字后,我开始将每一行推回到字符串向量,直到我到达包含“channel”关键字的行。然后我用“=”分隔符分割最后一行并将单元格号1与“portNumber”进行比较,然后如果它们匹配,我搜索字符串向量(以“group”开头并以“channel”关键字结束的数据块)对于用户想要更改它的属性,在找到此属性后,我计算适当的偏移量以使用seekg函数更改文件的指针位置,然后我写入数据。 但事情是每条线都有有限数量的字符,即在插入较长线的情况下,其他线错过了。考虑下面的第三行块

;group=0
usecallerid=yes
context=pstn-channels
channel=>131

如果我想将此行更改为“context = phone-channels”,结果将为

;group=0
usecallerid=n
context=phone-channels
channel=>130

你可以看到第二行得到了错误的值。我认为在编辑之前在每行的末尾添加一些空格会很有用,但是我觉得这不是一个有效的解决方案。所以你怎么看?我希望你能清楚问题和问题......

这是代码

bool changeConfigFiles(string addr, int portNumber, string key, string value)
{
    //
    char cmd[200];
    fstream targetFile(addr.c_str());
    string lines;
    int offset=0,pPosition;
    vector<string> helper,anotherHelper;
    vector<string> contentsBlock;
    //
    if (!targetFile.is_open())
    {
        return false;
    }
    //
    while(getline(targetFile, lines))
    {
        if(lines.find("group") != string::npos)
        {
            pPosition = targetFile.tellg();
            pPosition -= lines.length();
            contentsBlock.push_back(lines);
            while(getline(targetFile, lines))
            {
                if(lines.find("=>") != string::npos)
                {
                    helper = explode("=>",lines);
                    contentsBlock.push_back(lines);
                    break;
                }
                contentsBlock.push_back(lines);
            }
        }
        //
        if(helper.size() !=0 && strToInt(helper[1]) == portNumber)
        {
            for(int i=0;i<contentsBlock.size();i++)
            {
                if(contentsBlock[i].find(key) != string::npos)
                {
                    anotherHelper = explode("=",contentsBlock[i]);
                    targetFile.seekg(pPosition+offset-1);
                    targetFile << endl << anotherHelper[0] << "=" << value << endl;
                }
                offset += contentsBlock[i].length();
            }
            //
            helper.clear();
            targetFile.seekg(pPosition+offset);
        }
    contentsBlock.clear();
    }
    targetFile.close();
    return true;
}

1 个答案:

答案 0 :(得分:0)

假设您拥有此文件的已知数据布局,我将回答这个问题,好像它是“我如何解析此文件”问题。在C ++中,fstream是一种原生解析文件的简单方法。请考虑以下内容(假设您有一个字符串拆分和一个字符串IndexOf方法,这两个方法都非常容易编写):

char** SplitString( _In_ char* string, _In_ char token, _Out_ int* tokenCount );
int IndexOf( _In_ char* string, _In_ char* search, _Out_ int* count, _Out_ int length );

CustomFileType* ParseFile( char* filename )
{
    int bufferSize = 10000;
    auto buffer = new char[ bufferSize];
    memset( buffer, 0, bufferSize);

    ifstream file( filename );

    file.read( buffer, bufferSize );

    file.close( );

    int blockCount = 0;
    auto blocks = SplitString( buffer, ';', &blockCount );

    CustomFileType* file = new CustomFileType( );

    for( int blockIndex = 0; blockIndex < blockCount; blockIndex++ )
    {
        Block* b = new Block( );
        b.PropertyX = GetValueOf( buffer, "PropertyX=" );
        b.PropertyY = GetValueOf( buffer, "PropertyY=" );   
        file.Blocks.Add( b );                     
    }
}

char* GetValueOf( char* buffer, char* key )
{
    int count = 0;
    int length = 0;
    int index = IndexOf( buffer, key, &count, &length );

    if( length == 0 || count == 0 ) return nullptr;

    auto output = new char[ length ];
    memcpy( output, &buffer[ index ], length );
    return output;
}

这大致涵盖了解析的想法。将文件分成块,读取每个块的每个元素,检索与每个键相关的每个值,转换为数据类型(上面未显示)并分配给相关属性。

要更改文件的值,您可以简单地(我称之为)解析它,将数据结构转换回其格式。因此,使用解析器读取对象,更改值,然后解析它(或对其进行编码,无论您喜欢哪个术语)。

要更改值并将其写回文件,请考虑手头的实际问题。您已将文本解析为对象,并且您知道文件格式。所以现在需要替换对象上的值并将它们写回文件。您的文件结构看起来遵循以下格式:

[标题信息]

[组]

其中组以分号分隔,并且标题信息和组都由键值对(x = y)的集合定义。所以说,你需要一个知道如何编写键值对的方法(这应该是微不足道的),然后是另一个理解标题/组布局的方法,并且可以接受一个对象(可能是CustomFileType,如前面的例子所用)并且可以读取该对象并将其值转换为您的文件格式。如果没有为你编写解析器和编写器,这可能是我解释它的最好方法。