首页
关于
Search
1
git lg彩色显示日志
28 阅读
2
在 Ubuntu 22.04 LTS 中安装 Docker
19 阅读
3
CentOs/Ubuntu搭建上网x-ui
18 阅读
4
git使用多个源和多个分支
15 阅读
5
清理Windows臃肿程序
15 阅读
默认分类
网站搭建
Windows
Linux
Docker
OpenWrt
Hackintosh
Git
Python
Web开发
JavaScript
FFmpeg
Demo
工具
刷机
油猴脚本
Excel
Chrome Extension
登录
Search
标签搜索
Pandas
读取
时区
Chrome
centos8
求和
Nginx
Typecho
404
csv
国际站
询盘导出
油猴脚本
bbr
Ubuntu
远程桌面
日志
log
数据清洗
打印机
野生程序猿
累计撰写
153
篇文章
累计收到
0
条评论
首页
栏目
默认分类
网站搭建
Windows
Linux
Docker
OpenWrt
Hackintosh
Git
Python
Web开发
JavaScript
FFmpeg
Demo
工具
刷机
油猴脚本
Excel
Chrome Extension
页面
关于
搜索到
153
篇与
的结果
2025-12-27
一次讲清:宽字节、多字节、UTF-8、GBK、Unicode、代码页(从原理到 Windows/VC6 实战)
这篇文章的目标只有一个:建立不再被“乱码”反复折磨的工程级认知模型。全文从“字符是什么”讲到“Windows 为什么会乱”,再落到 VC6/老项目的可执行结论,一次性讲清,不靠零散记忆,不靠运气。一、乱码的本质只有一句话乱码不是字符错了,而是“同一串字节,被用错了规则去解释”。任何文本问题,都可以还原成下面这条链路:字符含义 → 字符集 → 编码方式 → 字节序列 → 再被解释只要编码方式和解释方式不一致,就一定乱码。二、字符集(Character Set):先规定“有哪些字”字符集解决的是:世界上有哪些字符,以及它们的编号是什么。常见字符集包括:ASCII、GB2312、GBK、GB18030,而现代世界几乎都以 Unicode 为核心。Unicode 的本质不是编码,它只是一个全球统一的编号表(Code Point):“中” → U+4E2D“国” → U+56FD😀 → U+1F600Unicode 只负责“编号”,不负责怎么存成字节。三、编码方式(Encoding):把编号变成字节编码方式解决的是:Unicode 编号如何存储成二进制字节。UTF-8Unicode 的一种编码方式1~4 字节变长完全兼容 ASCII网络和跨平台事实标准例:“中” Unicode:U+4E2D UTF-8:E4 B8 AD(3 字节)UTF-16Unicode 的另一种编码方式2 或 4 字节Windows 内部原生使用C/C++ 中对应 wchar_t例:“中” UTF-16LE:2D 4EGBK中文本地编码1 或 2 字节不是 Unicode强依赖“解释环境”例:“中” GBK:D6 D0四、宽字节 vs 多字节(这是 Windows 语境)这是Windows 编程术语,不是编码学术概念。多字节(MBCS)使用 char*一个字符占用字节数不固定GBK、UTF-8、Shift-JIS 都是多字节多字节 ≠ UTF-8宽字节(Wide)使用 wchar_t*Windows 下固定为 UTF-16一个 wchar_t = 2 字节五、ANSI 是什么(99% 乱码根源)ANSI 不是一种编码。在 Windows 里:ANSI = “当前系统代码页下的多字节解释规则”所有 xxxA API 的真实行为都是:char* → 按当前代码页(CP_ACP) → 转 Unicode → 再处理六、代码页(Code Page):解释字节的“字典”代码页决定:char* 到底按什么规则被解释。常见代码页:936:GBK(简体中文)65001:UTF-81252:西欧CP_ACP 表示当前 ANSI 代码页,由系统区域设置决定。七、Windows 并不存在“UTF-8 进程”这是一个非常重要的纠正点。Windows 内部统一使用 UTF-16(W API)。 所谓“UTF-8 系统”,只是:把 CP_ACP 改成了 65001让 所有 A API 按 UTF-8 解释 char*W API 永远不受影响。八、VC6 / 老项目乱码的形成公式源码保存编码 ≠ 运行时 CP_ACP ≠ API 解释规则↓乱码典型炸点包括:源码是 GBK,系统 CP_ACP = 65001源码是 UTF-8,系统 CP_ACP = 936DLL 被不同宿主进程加载使用 MessageBoxA / CreateFileA / RegSetValueExA九、为什么 UTF-8 Beta 会“突然把老程序搞炸”Windows 的 “Beta: 使用 Unicode UTF-8 提供全球语言支持” 会:把 CP_ACP 改成 65001所有 A API 改为按 UTF-8 解 char*但老程序仍在传 GBK 字节,于是必然乱码。系统没错,是老程序的隐含假设错了。十、工程级铁律(记住这 4 句就够)char* 没有编码,只有字节编码信息存在于“解释方”,不在字符串本身A API = 按代码页猜W API = 唯一确定行为十一、VC6 / 老项目的最终正确路线在不重构整个项目的前提下,唯一长期稳定方案是:内部 char* 统一 UTF-8与系统交互全部使用 W API在边界做明确转换(MultiByteToWideChar / WideCharToMultiByte)不再依赖 CP_ACP不再关心宿主是 GBK 还是 UTF-8这套方案不靠系统设置、不靠用户环境、不靠运气。十二、结语乱码从来不是“中文太复杂”,而是规则被混用了。 只要你在工程中做到:一处确定、处处确定,乱码问题会从此消失。这篇文章本质上是在帮你建立一个判断标准:“这串字节,是谁、按什么规则,在解释它?”一旦这个问题你能随时回答,乱码就再也不是问题。
2025年12月27日
1 阅读
0 评论
0 点赞
2025-12-18
深入理解 Git rebase:如何把“私有补丁”永久叠加在 dev 之上
Git 实战:持续合并 dev 更新,并让私有代码始终位于最后提交在实际开发中,我们经常会遇到这样一种场景:dev 分支在持续更新(主线开发)我们基于 dev 派生了一个 定制分支 / 魔改分支 / 私有功能分支该分支中存在 dev 分支永远不会合入的私有代码需求是:持续同步 dev 的最新更新,但始终保证私有代码位于提交历史的最后,不被 dev 覆盖这种需求在以下场景中非常常见:OEM 定制版本客户专用功能分支内部增强版 / 魔改版长期维护的补丁分支本文将介绍一种 Git 原生、稳定、可长期使用 的解决方案。一、问题本质分析我们先抽象一下分支结构:dev: A -- B -- C -- D \ feature: E -- F (私有代码)我们的目标是:dev 每增加新提交(D → E → F → G…)feature 能持续同步 dev同时满足:私有提交 始终在最末尾提交历史尽量保持线性、干净二、核心思路:把私有代码当成“补丁”Git 中有一个非常适合这个需求的命令:rebaserebase 的本质语义是:将一组提交重新应用到另一个基点之上因此我们可以把整个问题理解为:dev 是不断前进的“主线”私有代码是一组需要长期叠加在主线之上的“补丁”三、推荐方案:使用 rebase 固定私有提交在最后适用前提当前分支可以 rebase(个人分支 / 约定可改历史)私有代码与 dev 的修改边界相对清晰1️⃣ 拉取 dev 最新代码git fetch origin2️⃣ 找到 dev 与当前分支的分叉点git merge-base feature origin/dev该命令会输出一个 commit hash,记为:<BASE_COMMIT>它是 feature 与 dev 的最后一个公共祖先。3️⃣ 核心命令:将私有提交重放到 dev 之上git rebase --onto origin/dev <BASE_COMMIT> feature这条命令做了什么?等价于:将 feature 分支中从 <BASE_COMMIT> 之后的所有提交重新应用到 origin/dev 的最新提交之上4️⃣ rebase 后的分支结构dev: A -- B -- C -- D \ feature: E' -- F'📌 私有提交始终位于最后四、以后 dev 再更新,怎么同步?如果私有代码始终只存在于 feature 分支中,后续同步将非常简单:git checkout feature git fetch origin git rebase origin/devGit 会自动:先对齐最新的 dev再把你的私有提交 重新应用到最后五、冲突会发生在哪里?这是该方案的一个重要优势:冲突 只会发生在私有提交中dev → dev 的提交之间不会产生冲突冲突范围清晰、可控非常适合 长期维护型分支。六、注意事项(重要)⚠️ 1. rebase 会改写提交历史请确保:当前分支是个人维护分支或团队已明确约定该分支可以 rebase如果已经推送过远程,需要使用:git push --force-with-lease⚠️ 2. 私有代码应尽量拆分成独立提交建议实践:一个私有功能一个 commit不要把私有代码与 dev 修改混在同一个提交中这样可以:降低 rebase 冲突概率提高长期可维护性七、不能 rebase 的替代方案(补充)在以下场景中,rebase 可能不适用:多人同时在该分支协作分支已被下游依赖,不能改历史此时可以使用:merge + 固定“补丁提交”策略约定规则:feature 分支最后一个提交永远是私有补丁同步流程:git checkout feature git fetch origin git merge origin/dev如遇冲突,可优先保留当前分支:git checkout --ours . git commit缺点是:提交历史不够线性merge commit 较多但在受限条件下依然可用。八、进阶工程实践:私有代码独立分支模型在企业级项目中,常见如下结构:origin/dev | feature-base (仅同步 dev,不写私有代码) | feature-private (只包含私有功能)同步流程:git checkout feature-base git rebase origin/dev git checkout feature-private git rebase feature-base该模式适合:OEM / 客户定制长期多版本维护私有代码体量较大场景九、总结Git 完全可以做到:dev 持续更新私有代码永远位于最后提交历史清晰、冲突可控核心思想只有一句话:把私有代码当成“补丁”,用 rebase 永远叠加在 dev 之上如果你有需要,也可以把这套流程封装成脚本,实现 一键同步 dev,非常适合长期项目维护。
2025年12月18日
1 阅读
0 评论
0 点赞
2025-09-11
自动把 requirements.txt 中的库锁死版本
在 Python 项目中,开发完成后直接部署,如果不锁定依赖版本,很可能因为底层库升级导致代码出错。因此,写死依赖版本是保证可重复部署的最佳实践。问题假设你的 requirements.txt 里有:requests numpy pandas如果不指定版本:pip install -r requirements.txt当库发布新版本时,部署环境可能与开发环境不一致可能出现 API 不兼容或行为改变的问题Python 脚本(跨平台)import subprocess # 读取原始 requirements.txt with open("requirements.txt") as f: lines = [line.strip() for line in f if line.strip() and not line.startswith("#")] # 获取当前环境已安装库及版本 installed = subprocess.run(["pip", "freeze"], capture_output=True, text=True).stdout.splitlines() installed_dict = dict(line.split("==") for line in installed if "==" in line) # 更新版本,只锁定文件中已有库 new_lines = [] for pkg in lines: pkg_name = pkg.split("==")[0] version = installed_dict.get(pkg_name) if version: new_lines.append(f"{pkg_name}=={version}") else: new_lines.append(pkg) # 未安装的保持原样 # 写回 requirements.txt with open("requirements.txt", "w") as f: f.write("\n".join(new_lines) + "\n") print("requirements.txt 已更新为锁定版本!")Linux / macOS 一行命令(bash)while read pkg; do v=$(pip show $pkg | grep Version | awk '{print $2}') if [ -n "$v" ]; then echo "$pkg==$v" else echo "$pkg" fi done < requirements.txt > requirements.locked.txt && mv requirements.locked.txt requirements.txt
2025年09月11日
2 阅读
0 评论
0 点赞
2025-09-08
利用静态路由与去 NAT 实现主路由OpenClash统一分流
主路由设置静态路由表把各子路由中 WiFi 的 IP 段对应设置到该子路由的 WAN 口 IP。静态路由保证了主路由能正确把返回的包发回去,不会丢包。启用 OpenClash 并基于 SRC-IP-CIDR 分流主路由能识别每个终端的真实源 IP。不同子路由、不同设备,可以按 IP 段实现精确分流。子路由设置WAN 口设置静态地址,网关指向主路由 IP 地址,保证所有流量都经过主路由转发。防火墙 WAN 关闭动态伪装 (MASQUERADE),让设备的真实 IP 直接暴露给主路由,避免 NAT 隐藏源地址。效果主路由统一跑 OpenClash,所有子设备的访问请求都能被精确识别和分流。子路由只负责下挂设备的接入和网段隔离,不再做 NAT 出口。
2025年09月08日
3 阅读
0 评论
0 点赞
2025-09-06
使用 GOST 实现内网 VLESS 代理的反向代理方案
使用场景内网主机:运行 VLESS 代理服务,监听在 10808 端口。公网主机:有固定公网 IP,可作为中转。目标:让外部用户通过公网主机访问到内网 VLESS 服务,并以内网主机的 IP 作为代理出口。配置步骤内网主机配置./gost -L rtcp://:8080/:10808 -F socks5://11.22.33.44:8443说明:-L rtcp://:8080/:10808:建立反向 TCP 隧道,将本地 10808 端口(VLESS 服务)映射到远程。-F socks5://11.22.33.44:8443:连接到公网服务器上的 socks5 监听端口。公网主机配置./gost -L socks5://:8443?bind=true说明:-L socks5://:8443?bind=true:启动一个支持反向连接的 socks5 服务,等待内网主机回连。工作原理公网主机通过 8443 端口开启一个可被绑定的 socks5 服务。内网主机主动连接公网主机的 8443,并建立反向隧道。外部用户访问公网主机时,请求会通过该隧道转发到内网主机的 10808(VLESS 服务)。最终,用户的出口 IP 显示为内网主机的公网出口 IP。
2025年09月06日
1 阅读
0 评论
0 点赞
1
2
...
31