作者jayzhuang (Jay)
看板C_and_CPP
標題[問題] C++ 儲存XML多筆資料的問題
時間Tue Aug 20 14:37:33 2019
開發平台(Platform): (Ex: Win10, Linux, ...)
Win10
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
vs2019
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
問題(Question):
上次感謝大家提醒我透過secedit轉檔的格式,改成ini;
並使用ini parser,讓我找到:GetPrivateProfileString/WritePrivateProfileString
目前我的Pwdword.ini,可透過這兩個去做讀取後,再存入到XML格式的檔案中。
但是我一個奇怪狀況,之前明明可以直接在顯示多筆資料的,
現在顯示卻永遠都顯示最後一筆資料.....
餵入的資料(Input):
我將Pwdword.ini內,三個項目等號的資料透過GetPrivateProfileString,
取得之後,一個一個測試,確認有資料入:
(下圖為Pwdword.ini的內容,紅色框框圈起三個資料是我抓取的)
https://imgur.com/PALPOII
下列程式碼是三筆資料的格式轉檔後,透過程式碼給儲存xml的Function
Sleep(10000);
//把要回傳的LGPO_xml細項內容儲存到這
string LGPO_XML_FilePath = GetFilePath() + "LGPO_Item.xml";
//寫入LGPO項目的內容
Save_LGPO_Item LGPO_Item_Content;
LGPO_Item_Content.LGPO_class = 1;
char Pw01[] = "MinimumPasswordAge";
char Pw02[] = "MaximumPasswordAge";
char Pw03[] = "MinimumPasswordLength";
char Pw04[] = "PasswordComplexity";
char Pw05[] = "PasswordHistorySize";
char Pw06[] = "ClearTextPassword";
char Pw07[] = "LockoutBadCount";
char Pw08[] = "LockoutDuration";
char Pw09[] = "ResetLockoutCount";
char Pw10[] = "ForceLogoffWhenHourExpire";
char Pw11[] = "NewAdministratorName";
char Pw12[] = "NewGuestName";
//宣告要資料類型名稱與,透過GetPrivateProfileString去抓取名稱後面的資料
CString MinimumPasswordAge_value;
::GetPrivateProfileString(_T("System Access"), _T("MinimumPasswordAge"), 0, MinimumPasswordAge_value.GetBuffer(MAX_PATH), MAX_PATH, _T("C:\\LGPO\\Pwdword.ini"));
MinimumPasswordAge_value.ReleaseBuffer();
//之後要把CString 轉成string的資料類型,方可回傳。
std::string MinimumPasswordAge_string(CW2A(MinimumPasswordAge_value.GetString()));
CString MaximumPasswordAge_value;
::GetPrivateProfileString(_T("System Access"), _T("MaximumPasswordAge"), 0, MaximumPasswordAge_value.GetBuffer(MAX_PATH), MAX_PATH, _T("C:\\LGPO\\Pwdword.ini"));
MaximumPasswordAge_value.ReleaseBuffer();
std::string MaximumPasswordAge_string(CW2A(MaximumPasswordAge_value.GetString()));
CString NewAdministratorName_value;
::GetPrivateProfileString(_T("System Access"), _T("NewAdministratorName"), 0 , NewAdministratorName_value.GetBuffer(MAX_PATH),MAX_PATH, _T("C:\\LGPO\\Pwdword.ini"));
NewAdministratorName_value.ReleaseBuffer();
std::string NewAdministratorName_string(CW2A(NewAdministratorName_value.GetString()));
LGPO_Item_Content.Item_name = Pw01;
LGPO_Item_Content.Item_value = MinimumPasswordAge_string;
LGPO_Item_Content.Item_name = Pw02;
LGPO_Item_Content.Item_value = MaximumPasswordAge_string;
LGPO_Item_Content.Item_name = Pw11;
LGPO_Item_Content.Item_value = NewAdministratorName_string;
Save_LGPO_XML(&LGPO_Item_Content, LGPO_XML_FilePath);
預期的正確結果(Expected Output):
(下圖是三筆資料的顯示)
https://imgur.com/c6CvK5k
錯誤結果(Wrong Output):
(結果永遠都只有一筆)
https://imgur.com/OvhZGsW
程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔)
這是我把資料存入XML的Funcion,我把回傳值得Function與Save_XML的Function分開兩種
--------------------回傳值的Funcion-------------------------
//宣告XML資料型別,是要傳入的值
class Save_LGPO_Item
{
public:
int LGPO_class; //本機群組原則類別的代號:(1)安全性設定-密碼原則
string Item_name; //細項的名稱
string Item_value; //細項的設定值
};
---------------------------------------------------------------
------------------存入XML的Function---------------------------
void Save_LGPO_XML(Save_LGPO_Item*LGPO_Item,string file)
{
//建立一個XML的文件物件
TiXmlDocument* LGPO_Document = new TiXmlDocument();
//XML檔案格式
TiXmlDeclaration* LGPO_Decl = new TiXmlDeclaration("1.0", "UTF-8", "yes");
//寫入第一行XML的資料格式
LGPO_Document->LinkEndChild(LGPO_Decl); // <?xml version="1.0" encoding="UTF-8"?>
//建立一個根元素並連線
TiXmlElement* RootElement = new TiXmlElement("Root");
LGPO_Document->LinkEndChild(RootElement);
//建立第一個節點LGPO元素並連線
TiXmlElement* LGPO_Element = new TiXmlElement("LGPO");
RootElement->LinkEndChild(LGPO_Element);
//設定第一個節點LGPO元素的屬性
LGPO_Element->SetAttribute("class", LGPO_Item->LGPO_class);
//建立子節點:Item項目,以及屬性內的:名稱、數值 ,並連線
TiXmlElement* ItemElement = new TiXmlElement("Item");
LGPO_Element->LinkEndChild(ItemElement);
ItemElement->SetAttribute("name", LGPO_Item->Item_name.c_str());
ItemElement->SetAttribute("value", LGPO_Item->Item_value.c_str());
//建立xml文件,並把項目存入
LGPO_Document->SaveFile(file.c_str());
}
補充說明(Supplement):
PS:我自己額外寫的直接把資料丟入到我寫的Save_XML 的Function
上星期測試明明會有顯示,但現在連這方法都不行了....
搞不懂為什麼? 是我修改的時候,刪除到某段程式碼? 還是我少做了什麼?
//把要寫入的LGPO_xml細項內容儲存到這
string LGPO_XML_FilePath = GetFilePath() + "LGPO_Item.xml";
//寫入LGPO項目的內容
Save_LGPO_Item LGPO_Item_Content;
LGPO_Item_Content.LGPO_class = 1;
LGPO_Item_Content.Item_name = "MinimumPasswordAge";
LGPO_Item_Content.Item_value = 1;
LGPO_Item_Content.Item_name = "MaximumPasswordAge";
LGPO_Item_Content.Item_value = 90;
https://imgur.com/CQ4BMVS
希望有人能幫我看看是我缺少了什麼嗎?
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 218.161.102.123 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1566283055.A.1EE.html
→ firejox: 不宣告3個嗎? 08/20 17:14
因為我要儲存的資料是2個以上(甚至10~100個都有可能)
但我現在連2~3個都無法顯示.... 所以才再找我Save_XML的Function問題在哪....
※ 編輯: jayzhuang (218.161.102.123 臺灣), 08/20/2019 18:07:14
→ firejox: 你TiXmlElement("Item")只有1個,傳入的也只有1個 08/20 19:09
→ firejox: 當然顯示一個 08/20 19:09
這樣啊.... 那該怎麼改壓? 因為我想要的是
Item資料來多少,它就會一直逐一往下新增。
要宣告一個Data變數好像也不對,因為資料量客戶那邊無法估計多少
我這邊用12個只是預設的.....
※ 編輯: jayzhuang (218.161.102.123 臺灣), 08/20/2019 19:23:38
噓 joechen1008: 伸手牌? 08/20 23:45
→ firejox: 你要傳多個,用陣列或stl container 都行 08/21 00:01
請問,用陣列或STL,那是要放在Save_XML的Function?
還是要放在主頁寫資料那邊好?
(研究整個早上@@.....還沒搞懂....)
※ 編輯: jayzhuang (218.161.102.123 臺灣), 08/21/2019 12:41:52
→ firejox: 都說傳多個了,放在Save_XML沒意義 08/22 01:56
我覺得應該是我Save_XML的Function無法做一次存取全部的值.....
我可能要再改一次.....
Vector的方式我大致上了解,但我得要想想的問題
(1)如何回傳全部的數值
(2)可以讓數值作全部儲存,或是連續存取/複寫
※ 編輯: jayzhuang (218.161.102.123 臺灣), 08/23/2019 11:54:08