初版-带一个进度条
This commit is contained in:
249
sources/Resource.cpp
Normal file
249
sources/Resource.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
#include "Resource.h"
|
||||
#include "EzUI.h"
|
||||
namespace ezui {
|
||||
//判断文件是否存在
|
||||
bool DirectoryExists(const UIString& directoryNme) {
|
||||
DWORD dwAttr = GetFileAttributesW(directoryNme.unicode().c_str());
|
||||
if (dwAttr == DWORD(-1)) {
|
||||
return false;
|
||||
}
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//寻找指定目录以及目录下的所有文件
|
||||
void FindFilesRecursively(const std::wstring& path, std::list<std::wstring>* result) {
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE findHandle = FindFirstFileW((path + L"/*").c_str(), &findData);
|
||||
if (findHandle == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
if (findData.cFileName[0] == L'.') {
|
||||
continue;
|
||||
}
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// 如果是目录,递归查找该目录
|
||||
std::wstring newPath = path + L"/" + findData.cFileName;
|
||||
FindFilesRecursively(newPath, result);
|
||||
}
|
||||
else {
|
||||
std::wstring newPath = path + L"/" + findData.cFileName;
|
||||
result->push_back(newPath);
|
||||
}
|
||||
} while (FindNextFileW(findHandle, &findData));
|
||||
FindClose(findHandle);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ezui {
|
||||
Resource::ReadStream::ReadStream(HRSRC hRsrc) {
|
||||
this->m_ptr = (char*)::LoadResource(ezui::__EzUI__HINSTANCE, hRsrc);
|
||||
this->m_count = ::SizeofResource(ezui::__EzUI__HINSTANCE, hRsrc);
|
||||
}
|
||||
Resource::ReadStream::ReadStream(const UIString& fileName) {
|
||||
this->m_ifs = new std::ifstream(fileName.unicode(), std::ios::binary);
|
||||
this->m_ifs->seekg(0, std::ios::end);
|
||||
this->m_count = m_ifs->tellg();
|
||||
this->m_ifs->seekg(0);
|
||||
}
|
||||
void Resource::ReadStream::seekg(std::streampos pos) {
|
||||
if (m_ifs) {
|
||||
m_ifs->seekg(pos);
|
||||
}
|
||||
else {
|
||||
this->m_pos = pos;
|
||||
}
|
||||
}
|
||||
void Resource::ReadStream::read(char* buf, std::streamsize count) {
|
||||
if (m_ifs) {
|
||||
m_ifs->read(buf, count);
|
||||
}
|
||||
else {
|
||||
::memcpy(buf, m_ptr + m_pos, count);
|
||||
this->m_pos += count;
|
||||
}
|
||||
}
|
||||
std::streampos Resource::ReadStream::tellg() {
|
||||
if (m_ifs) {
|
||||
return m_ifs->tellg();
|
||||
}
|
||||
else {
|
||||
return m_pos;
|
||||
}
|
||||
}
|
||||
const std::streamsize Resource::ReadStream::size() {
|
||||
return this->m_count;
|
||||
}
|
||||
Resource::ReadStream::~ReadStream() {
|
||||
if (m_ifs) {
|
||||
delete m_ifs;
|
||||
}
|
||||
if (m_ptr) {
|
||||
::FreeResource((HGLOBAL)m_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool Resource::Package(const UIString& dir, const UIString& outFile, const std::function<void(const UIString&, int, int)>& packCallback) {
|
||||
if (dir.empty() || !DirectoryExists(dir)) {
|
||||
std::wstring err = UIString("Error: Invalid directory: \"%s\"\n").format(dir.c_str()).unicode();
|
||||
OutputDebugStringW(err.c_str());
|
||||
ASSERT(!"Invalid directory !");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<Entry> items;
|
||||
std::list<std::wstring> files;
|
||||
FindFilesRecursively(dir.unicode(), &files);
|
||||
std::streamsize headOffset = sizeof(std::streamsize);
|
||||
std::ofstream ofs(outFile.unicode(), std::ios::binary);
|
||||
ofs.seekp(headOffset);
|
||||
for (auto& file : files) {
|
||||
//读取文件大小
|
||||
std::ifstream ifs(file, std::ios::binary);
|
||||
ifs.seekg(0, std::ios::end);
|
||||
auto size = ifs.tellg();
|
||||
//读取文件
|
||||
UIString data;
|
||||
data.resize(size);
|
||||
ifs.seekg(0);
|
||||
ifs.read((char*)data.c_str(), size);
|
||||
//记录文件名称,偏移,大小
|
||||
Entry item;
|
||||
item.Name = file;
|
||||
item.Size = size;
|
||||
item.Offset = headOffset;
|
||||
ofs.write(data.c_str(), data.size());
|
||||
headOffset += data.size();
|
||||
items.push_back(item);
|
||||
}
|
||||
//将偏移文件头偏移信息写入到文件初始位置
|
||||
ofs.seekp(0);
|
||||
ofs.write((char*)(&headOffset), sizeof(headOffset));
|
||||
//设置到文件条目位置
|
||||
ofs.seekp(headOffset);
|
||||
//处理路径
|
||||
UIString root = dir + "/";
|
||||
root = root.replace("\\", "/");
|
||||
root = root.replace("//", "/");
|
||||
if (root[root.size() - 1] == '/') {
|
||||
root.erase(root.size() - 1, 1);
|
||||
}
|
||||
size_t pos = root.rfind("/");
|
||||
if (pos != std::string::npos) {
|
||||
root = root.substr(0, pos + 1);
|
||||
}
|
||||
int index = 0;
|
||||
for (auto& item : items) {
|
||||
//写入文件偏移位置
|
||||
ofs.write((char*)(&item.Offset), sizeof(headOffset));
|
||||
//写入文件大小
|
||||
ofs.write((char*)(&item.Size), sizeof(headOffset));
|
||||
//文件路径名称
|
||||
UIString name = item.Name;
|
||||
name = name.replace("\\", "/");
|
||||
name = name.replace("//", "/");
|
||||
name = name.replace(root, "", false);
|
||||
ofs.write(name.c_str(), name.size() + 1);
|
||||
if (packCallback) {
|
||||
packCallback(name, index, items.size());
|
||||
}
|
||||
index++;
|
||||
}
|
||||
//首位呼应
|
||||
ofs.write((char*)(&headOffset), sizeof(headOffset));
|
||||
ofs.flush();
|
||||
ofs.close();
|
||||
return ofs.good();
|
||||
}
|
||||
|
||||
void Resource::UnPackage() {
|
||||
m_isGood = false;
|
||||
std::list<Entry>& items = (std::list<Entry>&)this->Items;
|
||||
auto& ifs = *(this->m_rStream);
|
||||
if (ifs.size() < sizeof(std::streamsize) * 2) {
|
||||
//不是标准的资源文件 不执行解析
|
||||
ASSERT(!"error resource");
|
||||
return;
|
||||
}
|
||||
//读取记录文件位置的偏移
|
||||
ifs.seekg(0);
|
||||
std::streamsize headOffset;
|
||||
ifs.read((char*)&headOffset, sizeof(headOffset));
|
||||
//读取末尾
|
||||
ifs.seekg(ifs.size() - sizeof(headOffset));
|
||||
std::streamsize endValue;
|
||||
ifs.read((char*)&endValue, sizeof(headOffset));
|
||||
if (headOffset != endValue) {
|
||||
//不是标准的资源文件 不执行解析
|
||||
ASSERT(!"error resource");
|
||||
return;
|
||||
}
|
||||
m_isGood = true;
|
||||
//开始读取文件剩余条目
|
||||
ifs.seekg(headOffset);
|
||||
std::streampos endPos = ifs.size() - sizeof(headOffset);
|
||||
while (ifs.tellg() < endPos)
|
||||
{
|
||||
//读取到文件偏移位置
|
||||
std::streamsize fileOffset;
|
||||
ifs.read((char*)&fileOffset, sizeof(headOffset));
|
||||
//读取文件大小
|
||||
std::streamsize fileSize;
|
||||
ifs.read((char*)&fileSize, sizeof(headOffset));
|
||||
//读取文件名称
|
||||
std::vector<char> buf(32768);
|
||||
for (int i = 0; i < buf.size(); i++)
|
||||
{
|
||||
char ch;
|
||||
ifs.read((char*)&ch, 1);
|
||||
buf[i] = ch;
|
||||
if (ch == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Entry item;
|
||||
item.Offset = fileOffset;
|
||||
item.Size = fileSize;
|
||||
item.Name = buf.data();
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
Resource::Resource(const UIString& resFile) {
|
||||
this->m_rStream = new ReadStream(resFile);
|
||||
this->UnPackage();
|
||||
}
|
||||
Resource::Resource(HRSRC hRsrc) {
|
||||
this->m_rStream = new ReadStream(hRsrc);
|
||||
this->UnPackage();
|
||||
}
|
||||
Resource:: ~Resource() {
|
||||
if (m_rStream) {
|
||||
delete m_rStream;
|
||||
}
|
||||
}
|
||||
bool Resource::GetFile(const UIString& fileName, std::string* out) {
|
||||
for (const auto& it : this->Items) {
|
||||
if (it.Name == fileName) {
|
||||
out->resize(it.Size);
|
||||
m_rStream->seekg(it.Offset);
|
||||
m_rStream->read((char*)out->c_str(), it.Size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Resource::IsGood() {
|
||||
return m_isGood;
|
||||
}
|
||||
void Resource::GetFile(const Entry& item, std::string* out) {
|
||||
out->resize(item.Size);
|
||||
m_rStream->seekg(item.Offset);
|
||||
m_rStream->read((char*)out->c_str(), item.Size);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user