[软件]_[Windows]_[参考NSUserDefaults自定义Windows的BASUserDefaults]


场景:

1. 在Mac下Cocoa开发,可以使用NSUserDefaults很容易的存储配置信息,而且它还支持基本类型的NSDictionary,NSArray等复杂类型. 我们使用这个类来存储运行时配置,

 比如多语言选项, 检查更新选项, 快捷键设置等等.这个信息自动存储在bundleid的相关位置.

参考: http://blog.csdn.net/yepeng2014/article/details/49003753

这种配置很方面, 如果是Windows的话唯一可以和它相提并论的是注册表了, 但是注册表不容易直观的通过路径查看到, 比较麻烦. 

这点Windows的SDK真的可以参考Cocoa做好点,提供方便开发人员开发常规软件的API.


2. 这里模仿了NSUserDefaults的接口写了Windows版本的,目前只能简单的存储和读取字符串类型,原始类型,对象类型的话返回void*, 这是因为C++并没有id类型.

3. 这里主要是使用了rapidjson 来作为存储格式, 相对NSUserDefaults 的XML格式稍微简单些, 因为Json读写非常快.

4. 和软件无关,可以跨产品使用.


bas_user_defaults.h:

#ifndef __BAS_USER_DEFAULTS_H
#define __BAS_USER_DEFAULTS_H

#include "bas_exp.h"

#include <Windows.h>

// 使用json来表达内容.
class LIB_BASIC BASUserDefaults
{
public:
	~BASUserDefaults();
	static void InitStandardUserDefaults(const wchar_t* brand,const wchar_t* product);
	static BASUserDefaults* StandardUserDefaults();

	static void InitUserDefaults(const char* name,const wchar_t* path);
	static BASUserDefaults* GetUserDefaults(const char* name);
	
	void SetString(const char* key,const char* value);
	void SetInt(const char* key,int value);

	const char* GetString(const char* key);
	//1.返回rapidjson::Value对象.
	void* GetValueObject(const char* key);

	int GetInt(const char* key);
	DWORD GetRGB(const char* key);
	void WriteAll();

private:
	BASUserDefaults(const char* name,const wchar_t* path);
	void ReadAll();
	
	char* name_;
	wchar_t* path_;
	void* document_;
	
};

#endif

bas_user_defaults.cpp:

#include "basic/bas_user_defaults.h"

#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <stdio.h>

#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filestream.h"
#include "rapidjson/stringbuffer.h"

#include "basic/bas_utility_sys.h"

static const char* gUserDefaultName = "UserDefault";
static wchar_t* gUserDefaultBrand = NULL;
static wchar_t* gUserDefaultProduct = NULL;

static std::map<std::string,BASUserDefaults*> gNameToDefault;

static rapidjson::Document* GetDocument(void* data)
{
	return (rapidjson::Document*)data;
}

BASUserDefaults::~BASUserDefaults()
{
	free(name_);
	free(path_);

}

void BASUserDefaults::InitStandardUserDefaults(const wchar_t* brand,const wchar_t* product)
{
	gUserDefaultBrand = wcsdup(brand);
	gUserDefaultProduct = wcsdup(product);

	wchar_t* appdata = BASUtilitySys::GetAppDataDir();
	wcscat(appdata,gUserDefaultBrand);
	::CreateDirectory(appdata,NULL);

	wcscat(appdata,L"\\");
	wcscat(appdata,gUserDefaultProduct);
	::CreateDirectory(appdata,NULL);
	wcscat(appdata,L"\\");

	wcscat(appdata,L"Preferences.json");
	InitUserDefaults(gUserDefaultName,appdata);

	free(appdata);
}

void BASUserDefaults::InitUserDefaults(const char* name,const wchar_t* path)
{
	gNameToDefault[name] = new BASUserDefaults(name,path);
}

void BASUserDefaults::ReadAll()
{
	rapidjson::Document* document = GetDocument(document_);

	FILE* file = _wfopen(path_,L"rb");
	if(file)
	{
		fseek(file,0,SEEK_END);
		long size = ftell(file);
		fseek(file,0,SEEK_SET);
		char* buf = (char*)malloc(size+1);
		memset(buf,0,size+1);
		fread(buf,size,1,file);
		buf[size] = 0;
		fclose(file);
		if(document->Parse<0>(buf).HasParseError())
		{
			std::cout << "parse error" << std::endl;
			document->SetObject();
		}
		free(buf);
	}
}

void BASUserDefaults::WriteAll()
{
	rapidjson::Document* document = GetDocument(document_);

	FILE* file = _wfopen(path_,L"wb");
	rapidjson::StringBuffer buffer;  
	rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
	document->Accept(writer); 
	std::string result = buffer.GetString();
	fwrite((void*)result.data(),result.size(),1,file);
	fclose(file);
	
	delete document;
}

BASUserDefaults::BASUserDefaults(const char* name,const wchar_t* path)
{
	name_ = strdup(name);
	path_ = wcsdup(path);

	rapidjson::Document* document = new rapidjson::Document();
	document_ = document;
	document->SetObject();

	//读取路径下的json内容.
	ReadAll();
	
}

BASUserDefaults* BASUserDefaults::GetUserDefaults(const char* name)
{
	return gNameToDefault[name];
}

BASUserDefaults* BASUserDefaults::StandardUserDefaults()
{
	return GetUserDefaults(gUserDefaultName);
}

void BASUserDefaults::SetString(const char* key,const char* temp_value)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value value(rapidjson::kStringType);
	value.SetString(temp_value,strlen(temp_value),document->GetAllocator());
	document->AddMember(key,value,document->GetAllocator());
}

int BASUserDefaults::GetInt(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	return (*document)[key].GetInt();
}

void* BASUserDefaults::GetValueObject(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value& value = (*document)[key];
	return &value;
}

void BASUserDefaults::SetInt(const char* key,int temp_value)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value value(rapidjson::kNumberType);
	value.SetInt(temp_value);
	document->AddMember(key,value,document->GetAllocator());
}

const char* BASUserDefaults::GetString(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	return (*document)[key].GetString();
}

DWORD BASUserDefaults::GetRGB(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	const char* value = (*document)[key].GetString();
	char* temp = strdup(value);
	char* t = temp;

	char* p = strchr(temp,',');
	*p = 0;
	int r = atoi(temp);
	temp = p+1;
	p = strchr(temp,',');
	*p = 0;
	int g = atoi(temp);
	int b = atoi(p+1);

	free(t);
	return RGB(r,g,b);
}


使用情况1:  类似NSUserDefaults使用默认的配置, 会根据公司名和产品名来创建默认配置文件

软件启动时:

BASUserDefaults::InitStandardUserDefaults(UiUtilityProduct::GetCorporationW().c_str(),
UiUtilityProduct::GetProductAliasW().c_str());


软件关闭时:
BASUserDefaults* user = BASUserDefaults::StandardUserDefaults();
user->WriteAll();
delete user;

使用情况2: 读取随软件打包的配置文件,只读.

wchar_t* install_dir_temp = BASUtilityApp::GetProductInstallDir();
std::wstring url_path(install_dir_temp);
url_path.append(L"Option.json");
BASUserDefaults::InitUserDefaults("url",url_path.c_str());
free(install_dir_temp);

常见的配置文件:

{
    "help": "http://www.xxx.com/online-help",
    "purchase": "http://www.xxx.com/purchase/xxx.html",
    "usupport": "http://www.xxx.com/support.html",
    "color:toolbox:background":"217,250,243",
    "color:toolbar:tab:font":"0,0,0"
}



参考:

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html

你可能感兴趣的:(windows,cocoa,mac,NSUserDefaults,rapidjson)