我们项目比较奇葩, ui用cocostudio做, 这项光荣的任务由美术接手.
这个美术是个新手, 经过我长时间的观察, 她似乎不用怎么画画. 至少在很长一段时间里, 她很悠闲, 只管拼UI即可.
这是我们客户端噩梦的源头.
她不懂需求, 任何ui, 只要截图下来符合策划草图就算完成任务.
因此, 什么层次结构, 什么命名规范, 统统没有.
程序接手过来的ui自己要从头到尾翻新一遍, 甚至比重做花的时间更长.
于是, 一个伟大的决定诞生了, 我把她的活一起做了, 摆脱了厄运, 让我事倍功半.
两周以后, 她说她太闲了, 又把活接了过去, 从此厄运continue..
她把每一个ui都新建一个工程, 可以看到合并前有多个目录, 容量达到500M.
而且, 同一个文件, 在不同的目录就可能是不同的名字, 总之错乱不堪, 一塌糊涂.
她的杰作, 导致apk远远过150m, 直逼200m.
就在策划, 美术大呼, 节省资源的同时, 他们依然没有意识到问题出在哪里.
随着他们的呼声越来越高, 资源也越来越大.
卧槽, 彻底服了.
终于, 我忍无可忍了, 决定要彻底优化一次资源.
由于资源文件太乱, 根本无从下手, 于是我订好了目录结构, 统一了文件名, 把这个活交给了美术.
这个事情很容易完成, 因为他们只要整理文件就OK, 至于ui资源里指定的文件路径, 都是由程序各自去修改.
所以, 这个工作量是相当的小, 我以为美术一周内怎么也可以做完了...
2个月以后, 美术把文件整理好了.
然后我把文件合并了, 有效资源居然只有22m.
1 #include <Windows.h> 2 #include <windowsx.h> 3 4 #include <string> 5 #include <memory> 6 #include <utility> 7 #include <vector> 8 #include <fstream> 9 #include <list> 10 #include <iterator> 11 #include <functional> 12 #include <iostream> 13 #include <thread> 14 #include <regex> 15 16 #define LOG(param) {std::wcout << param << std::endl;} 17 18 size_t getFileSize(std::wifstream &ifile) 19 { 20 ifile.seekg(0, std::ios::end); 21 auto pos = (size_t)ifile.tellg(); 22 ifile.seekg(0, std::ios::beg); 23 return pos; 24 } 25 26 // 获得目录. 27 inline std::wstring getDirectoryName(const std::wstring &fullName) 28 { 29 auto pos = fullName.find_last_of(L'\\'); 30 return pos != std::wstring::npos ? fullName.substr(0, pos) : L""; 31 } 32 // 获得文件名. 33 inline std::wstring getFileName(const std::wstring &fullName) 34 { 35 auto pos = fullName.find_last_of(L'\\'); 36 return pos != std::wstring::npos ? fullName.substr(pos + 1) : L""; 37 } 38 // 获取后缀. 39 inline std::wstring getFileExtName(const std::wstring &fullName) 40 { 41 auto pos = fullName.find_last_of(L'.'); 42 return pos != std::wstring::npos ? fullName.substr(pos + 1) : L""; 43 } 44 45 class Project { 46 public: 47 std::wstring directoryName; 48 std::wstring directoryPath; 49 std::wstring jsonPath; 50 std::wstring projectName; 51 std::vector<std::wstring> jsonList; 52 }; 53 54 bool handleFileList(const std::wstring &rootDirectory, const std::wstring &outDirectory, const std::vector<std::wstring> &fileList) 55 { 56 auto result = false; 57 LOG("handleFileList"); 58 std::vector<Project> projectList; 59 60 { 61 Project project; 62 for (auto &fullName : fileList) 63 { 64 auto directoryPath = getDirectoryName(fullName); 65 auto fileName = getFileName(fullName); 66 auto extName = getFileExtName(fileName); 67 68 if (extName == L"ui" && directoryPath != project.directoryPath) 69 { 70 // 记录路径. 71 if (!project.directoryPath.empty()) 72 { 73 projectList.push_back(project); 74 } 75 project = Project(); 76 project.directoryPath = directoryPath; 77 project.directoryName = getFileName(directoryPath); 78 project.jsonPath = directoryPath + L"\\Json"; 79 } 80 81 // 记录项目文件名. 82 if (extName == L"ui") 83 { project.projectName = fileName; } 84 85 // 记录项目的json文件名. 86 if ( getFileName(directoryPath) == L"Json" && extName == L"json") 87 { 88 project.jsonList.push_back(fileName); 89 } 90 } 91 } 92 93 // 生产新的项目. 94 { 95 // cat json file. 96 std::wstring jsonList; 97 98 CreateDirectory( (outDirectory + L"\\Json").c_str(), nullptr ); 99 CopyFile(L"null_project\\Json\\null_project_1.json", (outDirectory + L"\\Json\\null_project_1.json").c_str(), FALSE); 100 101 for (auto &project : projectList) 102 { 103 for (auto &json : project.jsonList) 104 { 105 auto name = project.directoryName + L"_" + json; 106 auto inName = project.jsonPath + L"\\" + json; 107 auto outName = outDirectory + L"\\Json\\" + name; 108 auto copy = CopyFile(inName.c_str(), outName.c_str(), FALSE); 109 jsonList.append(L"<string>" + name + L"</string>\n"); 110 LOG(L"copy " << inName << L", " << outName << L" | " << copy); 111 } 112 LOG(L"copy resources."); 113 wchar_t commandLine[1024] = { 0 }; 114 auto inName = project.directoryPath + L"\\Resources"; 115 auto outName = outDirectory + L"\\Resources"; 116 wsprintf(commandLine, L"/c xcopy %s\\*.* %s\\ /E /Y", inName.c_str(), outName.c_str()); 117 ShellExecute(nullptr, L"open", L"cmd", commandLine, nullptr, SW_SHOW); 118 } 119 120 do { 121 // 写入 project. 122 std::wifstream ifile(L"null_project\\null_project.xml.ui", std::ios::binary | std::ios::in); 123 if (!ifile) 124 { 125 break; 126 } 127 auto fileSize = getFileSize(ifile); 128 auto templateBuffer = std::wstring(fileSize, L'\0'); 129 ifile.read(&templateBuffer[0], fileSize); 130 ifile.close(); 131 132 auto writeStr = std::regex_replace( 133 templateBuffer, std::wregex(L"JsonList_Replace"), jsonList); 134 std::wfstream ofile(outDirectory + L"\\project.xml.ui", std::ios::binary | std::ios::out); 135 ofile.write(writeStr.c_str(), writeStr.size()); 136 ofile.close(); 137 } while (0); 138 139 140 141 result = true; 142 } 143 return result; 144 } 145 146 bool run(const std::wstring &rootDirectory, const std::wstring &outDirectory) 147 { 148 auto result = false; 149 150 do { 151 { 152 wchar_t commadBuffer[256]; 153 wsprintf(commadBuffer, 154 L"/c " 155 L"%c:&" 156 L"cd %s&" 157 L"del config.txt&" 158 L"for /R %%i in (*) do (echo %%i>>%s\\config.txt)", 159 rootDirectory[0], rootDirectory.c_str(), rootDirectory.c_str()); 160 ShellExecute(nullptr, L"open", L"cmd", commadBuffer, nullptr, SW_SHOW); 161 LOG(L"Wait 10 Seconds..."); 162 std::this_thread::sleep_for(std::chrono::milliseconds(10000)); 163 } 164 165 // 打开文件 166 std::wifstream ifile(rootDirectory + L"\\config.txt"); 167 168 // 读取文件列表. 169 std::vector<std::wstring> fileList; 170 if (ifile) 171 { 172 LOG(L"open config.txt."); 173 do { 174 std::wstring fileName; 175 std::getline(ifile, fileName); 176 fileList.push_back(fileName); 177 } while (!ifile.eof()); 178 ifile.close(); 179 LOG(L"init file list."); 180 } 181 182 if (!fileList.empty()) 183 { 184 result = handleFileList(rootDirectory, outDirectory, fileList); 185 } 186 } while (0); 187 188 return result; 189 } 190 191 int main() 192 { 193 std::locale::global(std::locale("chs")); 194 195 std::wifstream ifile(L"config.txt"); 196 if (ifile) 197 { 198 std::wstring rootDirectory = L"X:\\Output\\office\\UI\\11月新版UI"; 199 std::wstring outDirectory = L"X:\\Output\\test_out"; 200 std::getline(ifile, rootDirectory); 201 std::getline(ifile, outDirectory); 202 203 std::wcout 204 << L"rootDirectory: " << rootDirectory << L"\n" 205 << L"outDirectory: " << outDirectory << std::endl; 206 std::wcout << (run(rootDirectory, outDirectory) ? L"done." : L"failed."); 207 } 208 std::wcout << L"\n===========================end.===========================\n"; 209 std::cin.get(); 210 return 0; 211 }
思路比较简单, 效果看起来很高端有没有.
一堆的控制台弹窗.