读取文件内容时未定义的字符,文件末尾没有新行

时间:2017-01-10 01:02:51

标签: c++ parsing ifstream getline istringstream

要解析的文件(settings.txt):

FULLSCREEN=On
V_SYNC=On [no "\n" at the end of file]

如果没有ENTER“\ n”输出是:

MapKey= FULLSCREEN      MapValue= On
MapKey= V_SYNC  MapValue= Onřřřř

使用ENTER“\ n”在文件输出结束时是正确的(没有“řřřř”):

MapKey= FULLSCREEN      MapValue= On
MapKey= V_SYNC  MapValue= On

如何在不在文件末尾添加新行的情况下更改程序?代码:

#include<iostream>
#include<fstream>
#include<sstream>
#include<vector>
#include<cstdint>
#include<memory>


int main()
{
    std::vector<std::pair<std::string, std::string>> container;
    std::ifstream containerFile("settings.txt", std::ifstream::binary);
    containerFile.seekg(0, containerFile.end);
    std::uint64_t fileSize = containerFile.tellg();
    containerFile.seekg(0);
    std::unique_ptr<char> fileBuffer(new char[fileSize]);
    containerFile.read(fileBuffer.get(), fileSize);

    std::istringstream fileContent(fileBuffer.get());
    std::string fileLine;
    while (std::getline(fileContent, fileLine))
    {
        std::istringstream bufferLine(fileLine);
        std::string option;
        if (std::getline(bufferLine, option, '='))
        {
            std::string value;
            if (std::getline(bufferLine, value))
            {
                container.emplace_back(make_pair(option, value));
            }
        }
    }
    for (auto &element : container)
    {
        std::cout << "MapKey= " << element.first << "   MapValue= " << element.second << std::endl;
    }
    containerFile.close();
}

1 个答案:

答案 0 :(得分:1)

您可以这样重写代码:

std::vector<std::pair<std::string, std::string>> container;
std::ifstream containerFile("settings.txt");
containerFile.seekg(0, containerFile.end );
std::uint64_t fileSize = containerFile.tellg();
containerFile.seekg(0);

/* Changed code. Begin*/
containerFile >> std::noskipws;
std::vector<char> buffer;
buffer.reserve(fileSize);
std::copy(std::istream_iterator<char>(containerFile), std::istream_iterator<char>(), std::back_inserter(buffer));
buffer.push_back('\0');
std::istringstream fileContent(&buffer.front());
/* Changed code. End*/

std::string fileLine;
while (std::getline(fileContent, fileLine))
{
    std::istringstream bufferLine(fileLine);
    std::string option;
    if (std::getline(bufferLine, option, '='))
    {
        std::string value;
        if (std::getline(bufferLine, value))
        {
            container.emplace_back(make_pair(option, value));
        }
    }
}
for (auto &element : container)
{
    std::cout << "MapKey= " << element.first << "   MapValue= " << element.second << std::endl;
}
containerFile.close();

首先,你必须使用下一个标志:containerFile >> std::noskipws; 它允许您使用空格。制表符空格,回车符和空格都被视为空格according to documentation

正确的字符串表示最后需要Null character,因此下一行buffer.push_back('\0');会添加&#39; \ 0&#39;到缓冲区的末尾。