UE4使用第三方库读写xml文件
发表于2016-12-13
在游戏开发过程中,读写xml几乎已经成为不可或缺的功能,但是由于有一点点的先入为主,当时直接选择了使用c++常用的tinyxml,于是这里就需要引用第三库,其实UE4有一个自带的XmlParser,也可以轻松读写xml。下面我们就看看这两种的方式的详细操作。
一、准备工作:
1.用UE4创建一个空模板的C++工程,命名为TinyxmlProject。
2.https://sourceforge.net/projects/tinyxml/ 在这里下载tinyxml的工程。
二、XmlParser:
1.为Build脚本添加XmlParser的模块,用vs打开当前的工程,找到并打开Source/TinyxmlProject/TinyxmlProject.Build.cs脚本,在PublicDependencyModuleNames中添加"XmlParser":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public TinyxmlProject(TargetInfo Target) { PublicDependencyModuleNames.AddRange( new string [] { "Core" , "CoreUObject" , "Engine" , "InputCore" , "XmlParser" }); PrivateDependencyModuleNames.AddRange( new string [] { }); // Uncomment if you are using Slate UI // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // Uncomment if you are using online features // PrivateDependencyModuleNames.Add("OnlineSubsystem"); // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64)) // { // if (UEBuildConfiguration.bCompileSteamOSS == true) // { // DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam"); // } // } } |
2.在TinyxmlProjectGameMode添加头文件XmlParser.h就开始写第一个功能,创建并写入xml文件,因为之前的Build.cs中添加了模块,我们可以直接在脚本中添加头文件,这里的xml内容注意符合xml的规则,如果不符合就无法写入。
1 2 3 4 5 6 7 8 9 10 11 | void ATinyxmlProjectGameMode::CreateXmlParser() { //xml的内容 const FString _XmlContent = " ; //以Buffer的方式构建一个XmlFile对象 FXmlFile* _WriteXml = new FXmlFile(_XmlContent, EConstructMethod::ConstructFromBuffer); //保存xml文件 FPaths::GameDir()表示当前工程的路径 _WriteXml->Save(FPaths::GameDir() + "test.xml" ); GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, "create success!" ); } |
3.然后在BeginPlay中调用CreateXmlParser(),并在ue4中编译运行,就会在工程路径下找到一个test.xml文件,打开就会看见写入了我们之前所输入的内容。
4.读取xml,具体注释在脚本中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | void ATinyxmlProjectGameMode::ReadXmlParser( const FString &_XmlPath) { //创建一个XmlFile的对象 FXmlFile* _XmlFile = new FXmlFile(*_XmlPath); //获取XmlFile的根节点 FXmlNode* _RootNode = _XmlFile->GetRootNode(); //获取根节点下的所有子节点 const TArray assetNodes = _RootNode->GetChildrenNodes(); for ( int i = 0; i < assetNodes.Num(); i++) { const TArray contentNodes = assetNodes[i]->GetChildrenNodes(); for ( int i = 0; i < contentNodes.Num(); i++) { //获取并打印出节点内容 FString _TContent = contentNodes[i]->GetContent(); GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Blue, _TContent); } } } |
5.继续调用编译并打印,在屏幕上就能看见我们所获取的节点内容
1 2 3 4 5 6 | void ATinyxmlProjectGameMode::BeginPlay() { //xml的路径 const FString _xmlpath = FPaths::GameDir() + "test.xml" ; ReadXmlParser(_xmlpath); } |
三、tinyxml:
1.先给一个第三方库的官方wiki,详细的步骤也可以参照这个来看:https://wiki.unrealengine.com/Linking_Static_Libraries_Using_The_Build_System
2.打开开始下载的tinyxml工程,右键打开属性,因为我这里会使用的64位的平台,需要将tinyxml的平台改为x64。
3.生成tinyxml工程,并找到生成的tinyxml.lib文件和tinystr.h、tinyxml.h两个头文件,分别复制到ue4工程目录下的TinyxmlProjectThirdPartyLibs和TinyxmlProjectThirdPartyIncludes,这里的工程下的文件夹都是新建的。
4.在ue4中找到我们最开始更改的TinyxmlProject.Build.cs脚步,我们又需要添加新的配置,这里我就直接给出整个脚本,这里的功能就是替代普通c++工程引用静态库的配置,详细看看都一个意思,只是方式不同而已。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | // Fill out your copyright notice in the Description page of Project Settings. using System.IO; using UnrealBuildTool; public class TinyxmlProject : ModuleRules { private string ModulePath { get { return ModuleDirectory; } } //第三方库的路径 private string ThirdPartyPath { get { return Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/" )); } } public TinyxmlProject(TargetInfo Target) { PublicDependencyModuleNames.AddRange( new string [] { "Core" , "CoreUObject" , "Engine" , "InputCore" , "XmlParser" }); PrivateDependencyModuleNames.AddRange( new string [] { }); //头文件目录 PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "Includes" )); //lib文件 PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyPath, "Libs" , "tinyxml.lib" )); // Uncomment if you are using Slate UI // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // Uncomment if you are using online features // PrivateDependencyModuleNames.Add("OnlineSubsystem"); // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64)) // { // if (UEBuildConfiguration.bCompileSteamOSS == true) // { // DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam"); // } // } } } |
5.静态库配置完成后,再脚本中添加tinystr.h、tinyxml.h两个头文件,我们就尝试利用tinyxml的接口读取本地xml,这里主要注意一些变量类型的转换,UE4是自己的一套变量类型,并不适用tinyxml。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | bool ATinyxmlProjectGameMode::ReadXmlFile( const FString &_XmlPath) { //将TCHAR转换char 并转UTF-8编码 int32 iLength = WideCharToMultiByte(CP_UTF8, 0, *_XmlPath, -1, NULL, 0, NULL, NULL); char * path = new char [iLength + 1]; WideCharToMultiByte(CP_UTF8, 0, *_XmlPath, -1, path, iLength, NULL, NULL); //创建一个XML的文档对象。 TiXmlDocument *myDocument = new TiXmlDocument(); if (myDocument->LoadFile(path)) { //获得根元素 TiXmlElement *RootElement = myDocument->RootElement(); //将char转为TCHAR utf-8编码 支持中文 const char * outchar = RootElement->Value(); iLength = MultiByteToWideChar(CP_UTF8, 0, outchar, strlen (outchar) + 1, NULL, 0); TCHAR * outTchar = new TCHAR [iLength + 1]; MultiByteToWideChar(CP_UTF8, 0, outchar, strlen (outchar) + 1, outTchar, iLength); GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Green, outTchar); return true ; } return false ; } |
6.再次编译调试
1 2 3 4 5 6 7 | void ATinyxmlProjectGameMode::BeginPlay() { //xml的路径 const FString _xmlpath = FPaths::GameDir() + "test.xml" ; if (!ReadXmlFile(_xmlpath)) GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, "read failed" ); } |
7.这里的操作差不多就测试完了,其他的tinyxml的操作,百度Google一下就知道了。