Reputation: 609
File (settings.txt) to parse:
FULLSCREEN=On
V_SYNC=On [no "\n" at the end of file]
In case with no ENTER "\n" output is:
MapKey= FULLSCREEN MapValue= On
MapKey= V_SYNC MapValue= Onřřřř
With ENTER "\n" at the end of file output is correct (without "řřřř"):
MapKey= FULLSCREEN MapValue= On
MapKey= V_SYNC MapValue= On
How to change the program to work without adding new line at the end of file? Code:
#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();
}
Upvotes: 4
Views: 320
Reputation: 953
You can rewrite your code in this way:
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();
First of all you have to use the next flag: containerFile >> std::noskipws;
It allows you to use whitespaces. Tab spaces, carriage returns and blank spaces are all considered whitespaces according to documentation.
Correct string representation requires Null character in the end, so the next line buffer.push_back('\0');
adds '\0' to the end of the buffer.
Upvotes: 1