program-in-chinese / overview

中文编程的历史、现状和展望。issue 中进行相关问题的讨论.
https://zhuanlan.zhihu.com/codeInChinese
GNU General Public License v3.0
383 stars 34 forks source link

编码规范不统一的现状与解决方案 #193

Open nobodxbodon opened 2 years ago

nobodxbodon commented 2 years ago

源自 https://github.com/program-in-chinese/team_website/issues/27

阻碍中文编程发展的,主要是编码规范不统一的问题。

国内 Windows 系统是强制 gbk 编码(国家强制要求),国际通用是 UTF-8 编码。Linux 和 MacOS 是 UTF-8 编码。

即使国家取消强制 GBK 编码,Windows 也会因沉重的历史兼容性包袱不能轻易改成 UTF-8,因为那样会使许多旧软件出现问题。

用 utf-8 编码编写的 c/c++ 源码,进行编译后,在 Linux 控制台输出正常。但同一份源码,在国内 Windows 编译后,控制台的输出中文就是乱码。

如果用 GBK 编码保存源码,在国内 win 输出可以正常,但同一份源码在 Linux 下编译后, Linux 控制台输出中文就是乱码。

总之,由于两种编码冲突,输出中文乱码现象很严重,难以保证同一份源代码在所有系统上都输出正确的中文,甚至是不能识别正确的中文输入、中文路径。

一些文件元数据存储文字也跟随 win 系统,windows 使用 gbk,例如 CSV 的默认格式就是 GBK,如果读取 UTF-8 的 CSV 文件,就会有乱码。

在国内 Windows 系统上为照片修改元数据、标签,就是以 GBK 储存,许多国际软件(例如 exiftool exiv2)都只做了 utf-8 支持,读取的结果就出现了乱码。​

另外,有的软件读取目录,使用 UTF-8 编码,但 Windows 给它传递 GBK 编码,结果就找不到文件。典型:pngquant

如果在源文件名中使用了中文,GCC 的 C++ 编译器也无法正常工作。

nobodxbodon commented 2 years ago

@HaujetZhao 早先遇到过一个编码问题,见前文:都市传说: "部分"中文出现乱码

不妨探讨一下各种原因和可能的解决方案。比如,是由中文字符串还是中文命名标识符引起的、是否需要控制台编码设置,以及如果无法规避的话是否可以开发相关工具链解决(编辑器、运行环境等等)。

HaujetZhao commented 2 years ago

无法解决,这是历史问题。在文件中使用中文变量命名,没问题。

但是输出中文字符串、使用中文路径、读取文件有含有中文的元数据,就有问题。

有绕弯子的办法,使用第三方库进行编码转换。exiftool exiv2 开发者都搞了,说太难,搞不动。

编译器是要把常量处理成字节码的,如何处理,已经由源码编码决定了,还能有什么办法?只能搞中间拓展层。有能力搞、搞得出来、搞出来各个系统都能用、搞了别人愿意用,这都是难题。

计算机世界本就是不完美的,只能接受这个设定。

C 和 C++ 都是底层最接近汇编、硬件的,历史包袱很重,对他们不太期待完善的中文处理了。我目前也就敢在 Python 这样的解释语言中肆意用中文。

tch1121 commented 2 years ago

之前ffmpeg打印带有中文的元数据内容也是乱码,后来不知道什么版本起在 chcp 936chcp 65001 都能正常显示中文 所以我认为编码问题是能解决的

HaujetZhao commented 2 years ago

之前ffmpeg打印带有中文的元数据内容也是乱码,后来不知道什么版本起在 chcp 936chcp 65001 都能正常显示中文 所以我认为编码问题是能解决的

其时间和精力成本无法普及到大多数程序员所写的程序上。

nobodxbodon commented 2 years ago

个人认为,技术终归是为需求服务而且不断进步的。用中文的多了,迟早会有辅助或者解决方案出现。IDE的中文补全辅助插件就是个最近的例子。

想当初,上世纪七十年代还有专家认为 ”汉字无法进入电脑“ 呢。

liuxilu commented 2 years ago

汉字路径,汉字文件名,Dev-C++ 5.11 (minGW GCC 4.9.2) UTF-8文件,或GBK文件+编译参数-finput-charset=GBK 在Windows控制台 CP936 & CP65001 都没有乱码

#include <stdio.h>
#include <locale.h>
int main(void) {
    setlocale(LC_ALL, "");
    wprintf(L"你好");
}
tch1121 commented 2 years ago

Windows编码问题比较多 ANSI

// nodejs
spawnSync('pwsh', ['-c', 'Get-Clipboard'])
liuxilu commented 2 years ago

require('child_process').spawnSync('powershell', ['-c', '[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;Get-Clipboard'], { encoding: 'UTF-8' } )

farteryhr commented 1 day ago

中文编码,史诗巨坑【

当然如果把范围划定为“易用通行的,写代码用用,但别指望它覆盖一切汉字高级需求的”,则直接unicode。

就是要记住,不要认为unicode能完全解决汉字应用的一切需求,不要认为所有字符串数据必须得用unicode。

既然是这个主题,就把我整的大活也发上来【 http://farter.cn/zzdm 字理组字汉字编码,从头开始的汉字编码

普通软件unicode就罢了,如果要做的是处理人名地名古籍等,可能冒出中华文化博大精深的汉字的软件,记得给未来可能使用别的编码方式留门,比如GB13080-2022,比如big5,比如敝编码【