一、前言
撸主本来想用引用Tinyxml第三方库来做xml文件的读写,后来发现确实有点麻烦了,不如UE4的XmlParser模块中提供的两个类(FastXML、FXmlFile),本例使用FXmlFile。
编译环境:UnrealEngine 4.15.3、 Visual Studio 2015、 Windows 10 x64
创建项目
创建一个空的C++项目,撸主的命名是“TinyxmlTest”, 由于要使用XmlParser模块和JSON模块,所以在.Build.cs文件中添加相应模块:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "XmlParser", "JSON" });
接下来的调试将在GameModeBase中声明定义BlueprintCallable函数,然后在蓝图中通过按键调用函数进行测试。
二、XML
读写函数实现
在TinyxmlTestGameModeBase.h中添加#include “XmlParser.h”,之后添加函数声明:
//创建并写入xml文件
UFUNCTION(BlueprintCallable, Category = "Xml")
void CreateXmlParser();
//读取xml文件
UFUNCTION(BlueprintCallable, Category = "Xml")
void ReadXmlParser(const FString &_XmlPath);
在TinyxmlTestGameModeBase.cpp中,实现读写函数定义:
void ATinyxmlTestGameModeBase::CreateXmlParser()
{
//创建的xml文件内容,需要符合xml的规则,不符合则无法写入
const FString _XmlContent = "<DocumentElement>\n<Infor>\n< ID>01 </ID >\n<Name>AB</Name>\n<Content>BCD</Content>\n</Infor>\n</DocumentElement>";
//以Buffer的方式创建一个XmlFile对象
FXmlFile* _WriteXml = new FXmlFile(_XmlContent, EConstructMethod::ConstructFromBuffer);
//创建XmlFile对象失败
if (_WriteXml == nullptr)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("创建xml文件失败!"));
return;
}
//保存xml文件到当前工程
_WriteXml->Save(FPaths::GameDir() + "write01.xml");
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Blue, TEXT("创建xml文件成功!"));
}
void ATinyxmlTestGameModeBase::ReadXmlParser(const FString &_XmlPath)
{
//创建一个XmlFile对象
FXmlFile* _XmlFile = new FXmlFile(_XmlPath);
//得到_XmlFile的根节点
FXmlNode* _RootNode = _XmlFile->GetRootNode();
//得到根节点下的所有节点
const TArray<FXmlNode*> _AssetNodes = _RootNode->GetChildrenNodes();
for (FXmlNode* node : _AssetNodes)
{
//得到_AssetNodes下的所有子节点
const TArray<FXmlNode*> _ChildNodes = node->GetChildrenNodes();
FString _AssetContent = node->GetContent();
//打印_AssetNodes内容
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, _AssetContent);
for (FXmlNode* node : _ChildNodes)
{
FString _ChildContent = node->GetContent();
//打印_ChildNodes内容
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Blue, _ChildContent);
}
}
}
调试
在UE4 Editor中,创建GameModeBase的蓝图类:
打开蓝图类,添加节点:
创建并写入函数
我们的创建xml函数执行之后会在当前项目目录下生成一个名为write01.xml的文件,测试结果如下:
读取函数
按下R键开始读取,此处我是新建了一个名为xxxml的xml文件,内容如下:
执行结果如下:
三、JSON
读写函数实现
在TinyxmlTestGameModeBase.h中添加#include “Json.h”,并添加读写成员函数和JsonStr成员变量声明:
public:
ATinyxmlTestGameModeBase();
//读取Json文件
UFUNCTION(BlueprintCallable, Category = "Json")
void ReadJson();
//写Json文件
UFUNCTION(BlueprintCallable, Category = "Json")
void WriteJson(FString author, int32 age);
private:
//Json字符串数据
FString JsonStr;
此处我们还要实现GameModeBase的构造函数,在其中初始化JsonStr。
在TinyxmlTestGameModeBase.cpp中实现函数定义:
ATinyxmlTestGameModeBase::ATinyxmlTestGameModeBase()
{
//简单Json格式字符串示例
JsonStr = "[{\"author\":\"Jack\"},{\"age\":\"100\"}]";
}
void ATinyxmlTestGameModeBase::ReadJson()
{
//创建用于存储Json对象的数组
TArray< TSharedPtr<FJsonValue> > JsonParsed;
//读取Json字符串
TSharedRef< TJsonReader<TCHAR> > JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonStr);
//解析Json到数组JsonParsed中
if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
{
//解析结果打印
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Blue, TEXT("解析Json成功!"));
FString FStringAuthor = JsonParsed[0]->AsObject()->GetStringField("author");
FString FStringAge = JsonParsed[1]->AsObject()->GetStringField("age");
FString tempString = "author = " + FStringAuthor + " ,age = " + FStringAge;
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, tempString);
}
else
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("解析失败!"));
}
void ATinyxmlTestGameModeBase::WriteJson(FString author, int32 age)
{
TSharedRef< TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR> > > JSonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR> >::Create(&JsonStr);
//写入Json数据开始
JSonWriter->WriteArrayStart();
JSonWriter->WriteObjectStart();
FString newAuthor = "Tom";
JSonWriter->WriteValue(TEXT("author"), author);
JSonWriter->WriteObjectEnd();
JSonWriter->WriteObjectStart();
JSonWriter->WriteValue(TEXT("age"), age);
JSonWriter->WriteObjectEnd();
JSonWriter->WriteArrayEnd();
JSonWriter->Close();
//写入结束
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("写入Json成功!"));
}
需要注意的是Json的格式问题,此处的Json字符串初始化和读写都是实现了一个2对象数组的Json数据。
不论是读写函数,都分为数组、对象和值,若是格式不符合则会出现无法读取的情况,由于不熟悉Json,撸主在此处卡了半天,最后还是看JSonWriter->WriteArrayStart()和JSonWriter->WriteObjectStart()的源码发现两者写入的不同的,前者会写入一个“[”,后者会写入一个”{“,因此此处写函数为了和初始化的Json字符串统一格式,实现如上。注意Start函数和End函数必须一一对应。
调试
回到我们的UE4 Editor,在之前创建的GameModeBase蓝图类中,添加蓝图节点:
接下来编译保存,我们就能在运行之后通过键盘上的J和N实现Json字符串的读写了。还能在蓝图中修改需要写入Json的值。运行结果如下:
上图是撸主分别按了J,N,J之后的结果。第一次读取了初始化的Json字符串,显示了”author = Jack, age = 100”,按下N之后显示“写入JSON成功!”,第二次按J读取了更改之后的Json字符串,显示了”author = Tom, age = 25.0”。
参考文章:
http://blog.csdn.net/cartzhang/article/details/43794409