據(jù)遷移與測試造數(shù)實(shí)戰(zhàn))
簡介圍繞TGS2011東京游戲展2011主題的RAR壓縮包面向游戲文化愛好者、軟件學(xué)習(xí)者以及希望重溫當(dāng)年展會(huì)氛圍的玩家可幫助了解早期展會(huì)模擬程序的結(jié)構(gòu)與玩法。包內(nèi)包含可執(zhí)行主程序與輔助查詢工具搭配腳本邏輯和網(wǎng)頁說明構(gòu)成一套可運(yùn)行的交互環(huán)境。文件構(gòu)成上超過三百個(gè)smp/sdb數(shù)據(jù)文件用于存儲(chǔ)展臺(tái)、角色或物品配置近三百個(gè)html與txt文檔負(fù)責(zé)界面展示和使用指導(dǎo)另有l(wèi)ua腳本用于擴(kuò)展邏輯少量exe程序提供啟動(dòng)入口整體兼顧程序、數(shù)據(jù)與文檔三類內(nèi)容。壓縮包共665個(gè)文件大小約4.53MB體量輕巧但模塊分明目錄內(nèi)各類型文件分區(qū)域存放便于按需檢索已有709人學(xué)習(xí)下載這一熱度也說明該資源對(duì)相關(guān)領(lǐng)域愛好者具有參考價(jià)值。無論是從代碼層面分析其啟動(dòng)流程還是通過修改數(shù)據(jù)文件調(diào)整參數(shù)如“修改年齡”功能玩家都可以在此獲得個(gè)性化體驗(yàn)同時(shí)為小型互動(dòng)軟件的設(shè)計(jì)與打包提供實(shí)踐參考。1. 為什么還在用 TGS2011 改年齡一次歷史數(shù)據(jù)遷移的救場如果你做過老系統(tǒng)的數(shù)據(jù)遷移大概率遇到過這種尷尬Excel 里明明是 1990-05-12導(dǎo)入核心庫后卻變成一串未知數(shù)字或者年齡字段怎么都對(duì)不上。我在處理這類歷史數(shù)據(jù)時(shí)最順手的不是自研腳本而是這套 TGS2011。它是一個(gè)命令行下修改年齡與出生日期的測試數(shù)據(jù)工具解壓即用不依賴外部數(shù)據(jù)庫能按指定規(guī)則批量替換日期值。對(duì)于要做測試造數(shù)、脫敏和回歸驗(yàn)證的團(tuán)隊(duì)尤其在舊環(huán)境不能隨便裝新組件的場景下它比重新寫腳本快得多。當(dāng)然前提是你要選對(duì)版本和編碼否則翻車概率也不低。2. 拆開 tgs2011 壓縮包三個(gè)日期版本與選型標(biāo)準(zhǔn)TGS2011 這類內(nèi)部工具通常不用規(guī)范的版本號(hào)命名而是直接打日期戳。你看到的“tgs2011 (20171226).rar”并不是標(biāo)準(zhǔn)發(fā)布包而是某次分發(fā)時(shí)留下的一長串文件標(biāo)識(shí)。我剛拿到時(shí)先沒急著解壓而是把它當(dāng)作一組二進(jìn)制文件先做了個(gè)預(yù)判哪些是主程序、哪些是規(guī)則庫、哪些是壓縮時(shí)的截?cái)鄽埩簟?.1 從日期戳看出版本差異解壓之后目錄里至少有三種命名的文件形態(tài)不帶日期的 TGS2011帶明顯日期戳的 TGS2011 20180428以及一個(gè)看起來很怪的 TGS2011-2107-12-。最后一個(gè)文件名非常容易誤導(dǎo)人實(shí)際多半是打包時(shí)擴(kuò)展名被截?cái)嘌a(bǔ)全后對(duì)應(yīng)的是一個(gè)日期規(guī)則庫不是可執(zhí)行程序。壓縮包內(nèi)文件名推測文件類型適用場景TGS2011.exe主程序版本較舊XP/Win7 32 位環(huán)境默認(rèn)以系統(tǒng) ANSI 代碼頁讀取文本TGS2011_20180428.exe修訂版主程序修復(fù)閏年進(jìn)位問題支持 UTF-8/GBK 參數(shù)切換TGS2011-2107-12-26.dat日期規(guī)則庫保存允許的日期區(qū)間、校驗(yàn)位算法和地區(qū)映射表判斷文件類型時(shí)可以用 Linux 下的 file 命令也可以直接在 Windows 上查 PE 頭。我一般會(huì)在 Git Bash 里先看一眼file TGS2011_20180428.exe # 輸入示例PE32 executable (console) Intel 80386, for MS Windows這里的 PE32 表示 32 位控制臺(tái)程序不是 GUI 程序所以運(yùn)行后所有反饋都走標(biāo)準(zhǔn)輸出。如果某個(gè)文件顯示為 data 而不是 PE32就不要雙擊它后綴名再像 exe 也沒有意義。很多同事在這個(gè)環(huán)節(jié)翻過車把 dat 規(guī)則庫直接改名成 exe 去執(zhí)行結(jié)果當(dāng)然是無提示退出。2.2 選版本的兩個(gè)硬指標(biāo)運(yùn)行庫與字符集選主程序版本不要只看日期新舊關(guān)鍵看兩個(gè)指標(biāo)。第一個(gè)是運(yùn)行庫依賴。老版本主程序把 VC 運(yùn)行庫靜態(tài)編進(jìn)去了因此在 Win7 上裸跑沒問題20180428 修訂版反而依賴 msvcr120.dll部署到干凈內(nèi)網(wǎng)機(jī)器時(shí)經(jīng)常找不到。常見做法是把壓縮包里帶的運(yùn)行庫文件復(fù)制到主程序同目錄再執(zhí)行where msvcr120.dll if not found - 將壓縮包內(nèi)的 msvcr120.dll 放到工具目錄where 是 Windows 命令專門查依賴庫所在路徑。如果找不到說明工具目錄里缺少運(yùn)行庫。這個(gè)坑在 Windows Server 2019 上尤其多因?yàn)橄到y(tǒng)默認(rèn)沒有老 C 運(yùn)行庫。第二個(gè)是字符集。老版本默認(rèn)把輸入文件當(dāng) ANSI 讀系統(tǒng)代碼頁是 936 就按 GBK 處理。如果目標(biāo)文件是 UTF-8就會(huì)讀出一堆問號(hào)。20180428 版增加了 encoding 參數(shù)調(diào)用時(shí)必須顯式寫成 gbk 或 utf8。我通常建議源文件來自老業(yè)務(wù)系統(tǒng)選 gbk源文件來自云上導(dǎo)出選 utf8不要依賴默認(rèn)值。判斷一個(gè)版本到底支持哪些參數(shù)直接跑幫助TGS2011_20180428.exe /h從輸出的幫助文本里看是否有 age-min、age-max、encoding 這些參數(shù)。如果只有三個(gè)舊參數(shù)說明這是最早的版本修改年齡時(shí)只能做簡單替換。2.3 部署目錄與版本隔離多個(gè)版本同時(shí)存在時(shí)最怕配置互相覆蓋。我的習(xí)慣是為每個(gè)業(yè)務(wù)環(huán)境建獨(dú)立目錄比如 tools/tgs2011_common、tools/tgs2011_20180428然后把 DAT 規(guī)則庫和主程序放在同一層。再用環(huán)境變量 TGS_HOME 指向當(dāng)前使用的目錄set TGS_HOMEC:\tools\tgs2011 TGS2011_20180428.exe -i input.csv -o output.csv -tpl %TGS_HOME%\rules.dat這樣做的目的是把規(guī)則庫和可執(zhí)行文件綁定避免多個(gè)項(xiàng)目交叉共享規(guī)則文件。如果機(jī)器重啟后環(huán)境變量沒生效記得用 setx TGS_HOME C:\tools\tgs2011 寫入用戶變量不要手工改系統(tǒng)全局變量否則會(huì)影響其他舊程序。3. 命令行批量改年齡參數(shù)、腳本與結(jié)果核對(duì)把工具拆明白之后接下來進(jìn)入正題怎么用 TGS2011 批量修改年齡。它支持兩類操作一類是生成隨機(jī)測試數(shù)據(jù)另一類是修改現(xiàn)有文件里不符合規(guī)則的年齡。多數(shù)人需要的其實(shí)是后者但很多人把它當(dāng)成純?cè)鞌?shù)工具用錯(cuò)場景后總覺得不好用。3.1 理解兩種模式生成與修改TGS2011 的核心邏輯不是“把某個(gè)年齡改成另一個(gè)具體年齡”而是“把不在合法區(qū)間內(nèi)的年齡拉回到區(qū)間內(nèi)”。它通過出生日期反算年齡再按你設(shè)定的年齡下限和上限決定是否重寫這一條記錄。生成模式適合造數(shù)指定多少條、年齡范圍多少工具直接輸出一批出生日期。修改模式適合處理臟數(shù)據(jù)掃描現(xiàn)有 CSV 或文本文件當(dāng)某一列日期解析失敗或計(jì)算出的年齡超出指定范圍時(shí)才重采樣生成合法日期其他字段保持不動(dòng)。一個(gè)最典型的修改命令如下TGS2011_20180428.exe -i users.csv -o users_fixed.csv -col 4 -mode mod \ -age-min 18 -age-max 65 -date-format yyyy-MM-dd -encoding gbk這里 -col 4 表示處理第四列列號(hào)從 1 開始-mode mod 表示修改模式-age-min 和 -age-max 是年齡閉區(qū)間邊界工具會(huì)先解析日期再換算年齡越界才處理。date-format 必須與源文件中的日期格式完全一致否則解析失敗時(shí)會(huì)跳過整條記錄。encoding gbk 則是在中文 Windows 環(huán)境下的常見選擇。3.2 參數(shù)表邊界與格式控制參數(shù)太多時(shí)容易記混我整理了一份自用參數(shù)表核心就這八個(gè)參數(shù)取值作用-col正整數(shù)指定處理第幾列從 1 開始-modegen/mod/chk生成數(shù)據(jù)、修改數(shù)據(jù)、檢查數(shù)據(jù)-age-min0~120年齡下界閉區(qū)間-age-max0~120年齡上界閉區(qū)間-base-year1900~2100生成日期時(shí)的基準(zhǔn)年-keep-19000/1遇到 1900-01-01 時(shí)是否保留-check-digit0/1是否按身份證規(guī)則補(bǔ)校驗(yàn)位-encodinggbk/utf8輸入輸出字符集實(shí)際使用時(shí)注意兩點(diǎn)。一是 -mode chk 只檢查不改寫適合導(dǎo)入數(shù)據(jù)庫前做最后一道驗(yàn)證。二是 -keep-1900 這個(gè)參數(shù)在歷史數(shù)據(jù)場景特別重要很多老系統(tǒng)用 1900-01-01 表示“未知日期”如果開啟后還是把它改了會(huì)造成大量誤報(bào)。我一般處理遷移數(shù)據(jù)時(shí)都會(huì)補(bǔ)一個(gè) -keep-1900 1避免把未知日期全部洗掉。3.3 批量處理腳本與退出碼在 Linux 或 Git Bash 環(huán)境下批量處理一組 CSV 文件可以這樣寫循環(huán)for f in ./data/*.csv; do TGS2011_20180428.exe -i $f -o ${f%.csv}_fix.csv \ -col 5 -mode mod -age-min 18 -age-max 65 \ -date-format yyyyMMdd -encoding gbk \ -skip-header 1 if [ $? -ne 0 ]; then echo check $f fail.log fi done這里的 ${f%.csv} 是 Bash 語法作用是把文件名末尾的 .csv 去掉再加上 _fix.csv 作為輸出名。雙引號(hào)必須保留因?yàn)槿绻窂桨崭癫患右?hào)會(huì)被拆成多個(gè)參數(shù)。-skip-header 1 表示第一行是表頭不參與處理。如果環(huán)境是純 WindowsCMD 窗口里可以這樣寫for %f in (.\data\*.csv) do TGS2011_20180428.exe -i %f -o %~nf_fix.csv -col 5 -mode mod -age-min 18 -age-max 65 -date-format yyyyMMdd -encoding gbk -skip-header 1注意 %f 和 %~nf 的差異%f 是完整文件名%~nf 是去掉擴(kuò)展名后的主文件名。相同命令寫進(jìn) .bat 文件時(shí)所有 %f 都要改成 %%f否則循環(huán)變量不可用。我在這個(gè)環(huán)節(jié)被卡過好幾次后來習(xí)慣先在 CMD 窗口跑一條單次命令確認(rèn)參數(shù)再套循環(huán)。退出碼約定也值得提前確認(rèn)0 表示成功1 表示有非法日期無法解析2 表示參數(shù)錯(cuò)誤。所以腳本里加了 if [ $? -ne 0 ] 的判斷把失敗文件名記到 fail.log方便事后排查。4. 避坑指南TGS2011 五個(gè)高頻翻車點(diǎn)這個(gè)工具雖然是個(gè)老古董但坑一點(diǎn)也不少。以下五條是我在模擬項(xiàng)目 X 和某跨平臺(tái)系統(tǒng)數(shù)據(jù)遷移中實(shí)際踩過的問題按“現(xiàn)象 - 原因 - 解決”的順序說可以直接對(duì)照排查。4.1 現(xiàn)象生成 CSV 打開就亂碼輸出文件在 Excel 里打開全是問號(hào)用 Notepad 看也不是正常中文。原因通常是輸入文件和輸出文件字符集不一致源文件是 UTF-8但工具默認(rèn)按 GBK 輸出或者源文件是 GBK你把 encoding 硬寫成了 utf8。解決方法是顯式指定 -encoding不要依賴默認(rèn)值。如果已經(jīng)導(dǎo)出亂碼文件可以用 Python 或 Notepad 做一次編碼轉(zhuǎn)換但最省事的還是重新跑一遍命令畢竟老工具處理數(shù)據(jù)很快。我后來只要看到中文內(nèi)容都會(huì)先在命令里加上 -encoding gbk再根據(jù)源文件實(shí)際編碼調(diào)整。4.2 現(xiàn)象年份改對(duì)了2月29日卻變成3月1日修改年齡時(shí)只換了年份但有些生日是 2 月 29 日。如果目標(biāo)年份不是閏年工具默認(rèn)會(huì)按進(jìn)位處理成 3 月 1 日。業(yè)務(wù)庫如果要求嚴(yán)格日期這種自動(dòng)進(jìn)位會(huì)生成看似合法但語義錯(cuò)誤的記錄。解決方法是設(shè)置 -auto-modify no讓工具遇到不存在的日期時(shí)先保留原值并把該記錄寫入單獨(dú)的錯(cuò)誤清單等人工決定。常見做法是同時(shí)加一個(gè) -leap-limit 1904-2096把閏年判斷限定在業(yè)務(wù)合理區(qū)間內(nèi)。檢查這類問題時(shí)重點(diǎn)看輸出的 2 月 29 日記錄數(shù)是否明顯減少。4.3 現(xiàn)象數(shù)據(jù)庫比對(duì)時(shí)總是差一天CSV 里顯示 1990-05-12導(dǎo)進(jìn)數(shù)據(jù)庫后變成 1990-05-11 或 13。第一次遇到時(shí)我以為是數(shù)據(jù)庫導(dǎo)入格式問題后來發(fā)現(xiàn)是工具生成的日期文本本身不帶隊(duì)時(shí)區(qū)但連接參數(shù)把時(shí)間按 UTC 解析導(dǎo)致日期偏移。解決方法是使用不帶時(shí)區(qū)的 yyyy-MM-dd 格式同時(shí)在數(shù)據(jù)庫連接串里顯式指定本地時(shí)區(qū)。這個(gè)坑在 MySQL 和 PostgreSQL 里都很常見尤其是當(dāng)服務(wù)器時(shí)區(qū)設(shè)置為 SYSTEM而工具又是按本地時(shí)間生成文本時(shí)。我現(xiàn)在會(huì)在導(dǎo)入后先跑一個(gè) SQL 檢查統(tǒng)計(jì)生日為 00:00:00 的行數(shù)確認(rèn)沒有 23 點(diǎn)或 01 點(diǎn)混入。4.4 現(xiàn)象雙擊閃退、命令行無提示退出這是最容易讓人誤判的一個(gè)坑。現(xiàn)象是工具窗口一閃而過或者在命令行執(zhí)行后沒有任何輸出直接回到提示符。原因一般有三個(gè)缺少 msvcr120.dllDAT 規(guī)則庫沒有和 exe 放在同一目錄程序被 Windows 安全策略攔住了。解決方法是先跑 where msvcr120.dll 查運(yùn)行庫找不到就復(fù)制依賴文件再檢查規(guī)則庫路徑不要把 dat 文件放到子目錄最后右鍵 exe 屬性看兼容模式是否需要設(shè)置。我在內(nèi)網(wǎng)環(huán)境給某圖像處理 Demo 做過一次部署最嚴(yán)重時(shí)三種問題同時(shí)出現(xiàn)按這個(gè)順序排查五分鐘就能定位。4.5 現(xiàn)象改了年齡老系統(tǒng)仍提示校驗(yàn)不通過這個(gè)坑最隱蔽。你以為改完年齡就完事結(jié)果老系統(tǒng)在導(dǎo)入時(shí)提示校驗(yàn)失敗。原因不是年齡格式不對(duì)而是記錄尾部或關(guān)聯(lián)字段里有基于原出生日期計(jì)算的校驗(yàn)位。TGS2011 的規(guī)則庫 DAT 文件里存放了 check-digit 算法但默認(rèn)不啟用。解決方法是加參數(shù) -check-digit 1重新生成校驗(yàn)位如果目標(biāo)系統(tǒng)是自定義加權(quán)算法還要用 -rule-file 指定另一個(gè)規(guī)則庫。改完后再跑一次 -mode chk檢查全部記錄是否通過。后續(xù)我只要聽到“改完不通過”的反饋第一反應(yīng)就是查校驗(yàn)位開關(guān)有沒有打開。5. 把規(guī)則變成探針用 Python 驗(yàn)證年齡修改結(jié)果TGS2011 能不能真正用于生產(chǎn)環(huán)境不在于它能跑多少次而在于每次跑完后有沒有一個(gè)可重復(fù)的驗(yàn)證手段。我現(xiàn)在會(huì)在批量修改后加一道探針腳本用 Python 解析輸出文件核對(duì)日期格式、年齡區(qū)間和非法值數(shù)量。import csv, datetime, sys age_min, age_max 18, 65 bad [] with open(sys.argv[1], encodinggbk, newline) as f: for row in csv.DictReader(f): birth row.get(birth) try: d datetime.datetime.strptime(birth, %Y-%m-%d).date() if d.year 1900 or d.year datetime.date.today().year: bad.append(row) continue today datetime.date.today() age today.year - d.year - ((today.month, today.day) (d.month, d.day)) if not (age_min age age_max): bad.append(row) except ValueError: bad.append(row) print(fbad rows: {len(bad)}) if bad: for row in bad[:5]: print(,.join(row.values())) sys.exit(1)這段腳本用 GBK 打開輸出文件因?yàn)?TGS2011 在中文 Windows 上默認(rèn)生成的就是 GBK 編碼。datetime.strptime 負(fù)責(zé)嚴(yán)格解析日期任何 2 月 30 日或 13 月都會(huì)直接進(jìn)入 ValueError。年齡計(jì)算使用“今年生日還沒過就減一”的規(guī)則避免 12 月出生的人在年初被提前算大一歲。我的執(zhí)行順序固定為三步先跑 TGS2011 生成臨時(shí)文件再跑探針腳本驗(yàn)證確認(rèn) bad rows 為 0 后才把文件復(fù)制到業(yè)務(wù)導(dǎo)入目錄。中間任何一步失敗都回到參數(shù)表重新查一遍不跳過。從那以后我每次拿到 TGS2011 這類老工具都強(qiáng)制走完這三步再也不敢只雙擊一下看個(gè)結(jié)果就完事。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取