zoukankan      html  css  js  c++  java
  • 记一次曲折的多资源文件拆分折腾过程(2)

    记一次曲折的多资源文件拆分折腾过程(2)

    前言

    本篇是上篇文章—— 记一次曲折的多资源文件拆分折腾过程(1) 的续篇。在上篇文章找到了导致编译报错的根本原因是 .rc 文件的编码不再是默认的 UTF-16LE-BOM 了。但是为什么 .rc 文件的编码会发生变化,并没有深究。本文继续探究一下。

    git 导致了文件编码变化?

    经过一系列的确认,确定是执行 git restore . (与 git checkout . 等价)的时候导致 .rc 文件的编码发生了变化。难道是 gitbug

    仔细回想,在设置 .gitattributes 之前一切正常,设置 .gitattributes 之后,就出问题了。为了进一步打消疑虑,我特意删除了 .gitattributes,然后再执行 git restore .,发现一切恢复正常了。

    看来,.gitattributes 的设置是导致 .rc 文件编码发生变化的罪魁祸首。

    为什么要设置 .gitattributes 呢?在上一篇文章中提到了,为了不让 git.rc.rc2 文件当成二进制文件来管理,在 .gitattributes 中把 .rc.rc2working-tree-encoding 设置成了 UTF-16。为什么我要把 .rc.rc2working-tree-encoding 设置成 UTF-16 呢?

    回顾

    在设置之前我是查看了 .gitattributes官方文档 的。文档中说,如果文件编码是 UTF-16 with BOM 的话,可以设置 working-tree-encodingUTF-16,如果文件编码是 UTF-16 little endian without BOM,可以设置 working-tree-encodingUTF-16LE。相关描述截图如下:

    gitattributes-utf16-utf16-le
    gitattributes-utf16-utf16-le

    我的注意力被红框高亮的部分吸引了,于是就在 .gitattributes 里做了如下设置。

    set-rc-as-utf-16le-in-gitattributes
    set-rc-as-utf-16le-in-gitattributes

    但是,当我使用 git add . 添加文件到暂存区的时候,报了如下错误:

    git-add-warning-and-fail
    git-add-warning-and-fail

    提示推荐使用 UTF-16。而且,在 pitfalls 的介绍里,也说 .rc.ps1 有时候会按 UTF-16 编码。描述截图如下:

    rc-is-documented-as-utf-16
    rc-is-documented-as-utf-16

    于是,我就乖乖地按照提示把 UTF16-LE 改成了 UTF-16。改完之后,果然不报错了。于是,我就掉坑里了,废了好大劲儿才爬出来。

    再看文档

    再次查看文档,细细的读了一遍关于 working-tree-encoding 的介绍。看到了下面这行至关重要的描述:

    use UTF-16LE-BOM instead of UTF-16LE if you want UTF-16 little endian with BOM.

    就在给出的两个例子中间,如下图:

    gitattributes-utf16-utf16-le
    gitattributes-utf16-utf16-le

    也就是说如果文件是 UTF-16 little endian with BOM 编码的话,working-tree-encoding 要设置为 UTF-16LE-BOM

    一般,.rc 文件是 UTF-16 little endian with BOM 的(折腾完之后才深刻意识到这一点的)。

    Bonus

    通过 working-tree-encoding 设置文件的编码来避免 git 把文件当成二进制的做法,并不是完美的。具体可以参考官方文档中的描述,如下图:

    working-tree-encoding-pitfalls
    working-tree-encoding-pitfalls

    大体意思是:

    git 会把 ASCII 编码,包括其它一些编码(例如,UTF-8,ISO-8859-1,...)的文件当成文本格式的文件对待,会把另外一些编码(例如,UTF-16) 的文件当成二进制格式的文件对待。

    如果某些文件设置了 working-tree-encoding,那么在存储到 git 内部的时候,会转换成 UTF-8 格式。当签出的时候,再从 UTF-8 转换成原来的格式。

    working-tree-encoding 是有一些缺陷的:

    1. 一些 git 实现不支持 working-tree-encoding,如果有同事使用支持 working-tree-encoding 的客户端,另外一些同事使用的是不支持 working-tree-encoding 的客户端,那么容易出问题。
    2. 一些字符集在与 UTF-8 编码来回转换的时候有问题 (not UTF-8 round trip safe),比如, SHIFT-JIS 字符集就有这方面的问题。
    3. 整个编码转换的过程中可能导致某些操作变慢(比如,git checkout, git add)。

    只有当文件不能存储成 UTF-8 格式并且希望 git 把这个文件当成文本文件的时候才使用 working-tree-encoding

    总结

    • 在设置 .gitattributes 中的 working-tree-encoding 之前,强烈建议仔细阅读官方文档!而且一定一定要仔细!
    • 设置过 working-tree-encoding 的文件,在 git 内部会以 UTF-8 格式存储,签出的时候再转换回指定的编码。
    • 一般情况下,.rc 文件的编码是 UTF-16 Little Endian with BOM,所以正确的 working-tree-encodingUTF-16LE-BOM
    • 简单总结了一张 working-tree-encoding 与文件编码的对照表,如下:
    working-tree-encoding 对应的文件编码
    UTF-16LE UTF-16 Little Endian (No BOM)
    UTF-16BE UTF-16 Big Endian (No BOM)
    UTF-16LE-BOM UTF-16 Little Endian (With BOM)
    UTF-16BE-BOM UTF-16 Big Endian (With BOM)
    UTF-16 UTF-16 Big Endian (With BOM)

    参考资料

    https://www.git-scm.com/docs/gitattributes

    未完待续

    至此,在本次折腾过程中遇到的所有问题都已经清楚了。但是这个问题“坑”我太深了,于是我又翻看了 git 源码,由于相关内容有点多,把参考源码的过程记录在了下一篇文章中,敬请期待。

    欢迎各位小伙伴指出不足,提出建议!感谢关注我的博客:)
  • 相关阅读:
    学习ASP.NET MVC3(5) Controller
    关于测试
    [JAVA SE] Java反射机制
    Windows 8 的软件开发架构
    Servlet生命周期与工作原理
    展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告(转载)
    JAVA小游戏代码(剪刀石头布)
    [JAVA SE] JSP中pageEncoding和charset区别,中文乱码解决方案
    我是工程师,不是编译器
    自己对三层架构理论的理解
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/15725877.html
Copyright © 2011-2022 走看看