C++ 从语言文件创建JSON对象
我有一个翻译文件,如下所示:C++ 从语言文件创建JSON对象,c++,json,file,c++11,C++,Json,File,C++11,我有一个翻译文件,如下所示: #: this is just some comment msgid "" "this is a line.\n" "this is a newline.\n" "this is another newLine". msgstr "" "this can be filled in.\n" "or left blank." #: just another comment msgid "Pizza" msgstr "" [ { "msgid":
#: this is just some comment
msgid ""
"this is a line.\n"
"this is a newline.\n"
"this is another newLine".
msgstr ""
"this can be filled in.\n"
"or left blank."
#: just another comment
msgid "Pizza"
msgstr ""
[
{
"msgid": ""
},
{
"msgstr": ""
},
{
"msgid": "Pizza"
},
{
"msgstr": ""
}
]
std::ifstream input(findFile("language.po").string());
std::string msgid, msgstr;
std::string *field = NULL;
std::string::size_type start, end;
Json::Value jsonRoot = Json::arrayValue;
for( std::string line; std::getline( input, line ); )
{
if (line.compare(0, 1, "#") == 0)
continue;
if (line.compare(0, 6, "msgid ") == 0)
{
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
msgid.clear();
msgstr.clear();
field = &msgid;
start = 6;
}
else if (!field)
{
continue;
}
else if (line.compare(0, 7, "msgstr ") == 0)
{
field = &msgstr;
start = 7;
}
else
{
start = 0;
}
start = line.find('\"', start);
if (start == std::string::npos)
continue;
++start;
end = line.find('\"', start);
if (end != std::string::npos)
*field += line.substr(start, end-start);
else
*field += line.substr(start);
}
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
如您所见,msgid
可以是多行或单行。这同样适用于msgstr
我所有的翻译文件都是这样的。如何使用上述数据示例创建包含两个键的json对象:
[
{
"msgid": "this is a line.\nthis is a newline.\nthis is another newLine.",
"msgstr": "this can be filled in.\n or left blank."
},
{
"msgid": "Pizza",
"msgstr": ""
}
]
我可以访问一个json库,我知道如何使用它。我正在为通过数据的for(each)循环而挣扎
目前我有一段代码:
std::ifstream input(findFile("language.po"));
Json::Value jsonRoot = Json:arrayValue;
for( std::string line; getline( input, line ); )
{
Json::Value Translation = Json::objectValue;
if(line.find("msgid") == 0) {
//messageId found
Translation["msgid"] = line;
} else if(line.find("msgstr") == 0) {
//translated string was found
Translation["msgstr"] = line;
}
jsonRoot.append(Translation);
}
然而,这为我不想要的每一行创建了一个新的json数组
此时,电流输出(未测试)应如下所示:
#: this is just some comment
msgid ""
"this is a line.\n"
"this is a newline.\n"
"this is another newLine".
msgstr ""
"this can be filled in.\n"
"or left blank."
#: just another comment
msgid "Pizza"
msgstr ""
[
{
"msgid": ""
},
{
"msgstr": ""
},
{
"msgid": "Pizza"
},
{
"msgstr": ""
}
]
std::ifstream input(findFile("language.po").string());
std::string msgid, msgstr;
std::string *field = NULL;
std::string::size_type start, end;
Json::Value jsonRoot = Json::arrayValue;
for( std::string line; std::getline( input, line ); )
{
if (line.compare(0, 1, "#") == 0)
continue;
if (line.compare(0, 6, "msgid ") == 0)
{
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
msgid.clear();
msgstr.clear();
field = &msgid;
start = 6;
}
else if (!field)
{
continue;
}
else if (line.compare(0, 7, "msgstr ") == 0)
{
field = &msgstr;
start = 7;
}
else
{
start = 0;
}
start = line.find('\"', start);
if (start == std::string::npos)
continue;
++start;
end = line.find('\"', start);
if (end != std::string::npos)
*field += line.substr(start, end-start);
else
*field += line.substr(start);
}
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
我将编写一个简单的状态机:
enum class State { INIT, ID, STR } state = State::INIT;
std::string buffer;
while (!end_of_file()) {
auto s = get_next_line();
if (is_comment(s)) {
// do nothing
} else if (is_msgid(s)) {
if (state != State::STR) {
buffer += s; // depending on how you read a line, you may have to add EOL here
} else {
put_msgid_into_json(buffer);
buffer = s;
}
state = State::ID;
} else if (is_msgstr(s)) {
if (state != State::ID) {
buffer += s; // depending on how you read a line, you may have to add EOL here
} else {
put_msgstr_into_json(buffer);
buffer = s;
}
state = State::STR;
}
}
if (state == State::ID) {
put_msgid_into_json(buffer);
} else if (state == State::STR) {
put_msgstr_into_json(buffer);
}
循环正在将每一行添加到数组中,而不考虑每一行的内容。您需要的是一个状态机,因此您只需将完成的对象添加到数组中,您需要将延续行附加到前面的行,直到到达下一个字段开始,并且您需要解析这些行以删除行前缀和引号 尝试类似以下内容:
#: this is just some comment
msgid ""
"this is a line.\n"
"this is a newline.\n"
"this is another newLine".
msgstr ""
"this can be filled in.\n"
"or left blank."
#: just another comment
msgid "Pizza"
msgstr ""
[
{
"msgid": ""
},
{
"msgstr": ""
},
{
"msgid": "Pizza"
},
{
"msgstr": ""
}
]
std::ifstream input(findFile("language.po").string());
std::string msgid, msgstr;
std::string *field = NULL;
std::string::size_type start, end;
Json::Value jsonRoot = Json::arrayValue;
for( std::string line; std::getline( input, line ); )
{
if (line.compare(0, 1, "#") == 0)
continue;
if (line.compare(0, 6, "msgid ") == 0)
{
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
msgid.clear();
msgstr.clear();
field = &msgid;
start = 6;
}
else if (!field)
{
continue;
}
else if (line.compare(0, 7, "msgstr ") == 0)
{
field = &msgstr;
start = 7;
}
else
{
start = 0;
}
start = line.find('\"', start);
if (start == std::string::npos)
continue;
++start;
end = line.find('\"', start);
if (end != std::string::npos)
*field += line.substr(start, end-start);
else
*field += line.substr(start);
}
if (!msgid.empty())
{
Json::Value Translation = Json::objectValue;
Translation["msgid"] = msgid;
Translation["msgstr"] = msgstr;
jsonRoot.append(Translation);
}
你能在你的问题中包括这个例程的当前输出状态吗?@Quirk我已经这样做了。现在打印的内容不多,因为我只检查字符串是否以
“msgid”
或“msgstr”开头
您实际使用的JSON库是哪4行?我想OP正在使用。我正在使用ubuntuI上的包:libjsoncpp dev
,请参见第5行缺少一个双精度的:
,不知何故,我可能无法使用来自boost的findFile和ifstream<代码>错误:调用'std::basic_ifstream::basic_ifstream(boost::filesystem::path)时没有匹配的函数,我已经将.c_str()
添加到路径中,它工作了:)因为ifstream需要字符串:)嗯,现在让我们查看结果:D@Baklap4:ifstream的ifstream
声明是从您的示例复制的,您说该示例已经在运行,只是没有执行您想要的操作。在ycase中,你不是指代替c_str()
?没有c_str()
方法。虽然它使用c_str()
@Baklap4:Nevermind编译和运行,但很奇怪,我正在查看旧的boost文档。我现在看到了最新的文档。