文件乱码处理

文章目录

前言

在windows中处理过的文件,用linux打开时候,可能会出现乱码现象。对于我而言,这个问题偶尔出现,但由来已久。以目前的能力来看,我解决不了这个问题,但不妨整理下 。

我瞅瞅我脑子里有哪些乱码现象的记忆:很久以前,我刚接触linux那会,遇到过乱码问题;学校安排python学习那会,pycharm里面的中文字符出现过乱码;研究生会打杂的时候,我解压压缩包的时候,文件名乱码;现在,我做东哥计算机网路的作业,乱码再次出现。

是可忍孰不可忍【原意是指如果这样的事情都可以被容忍,还有什么是不能容忍的。形容不可容忍到了极点】。今天虽然灭不了“乱码问题”,但要搓搓它的锐气。知己知彼方能百战不殆【意思是对敌人的情况和自己的情况都有透彻的了解,作战就不会失败】。遇到问题,分析问题,解决问题

0. 摘要

现在已经很少发生文件内容或文件名乱码的事情了。但是,偶尔遇到这样的事情,也会让人头疼半天。下面分别分析了文件和文件名产生乱码的原因,同时给出对应的解决办法(具体的解决办法见正文)(ps文件名乱码没有分析出来_)。不是特别紧密的相关知识点,我放在附录中。

1. 分析乱码问题

1.1 乱码出现位置

这里我们不考虑linux乱码的始作俑者[因为目前我搬砖的电脑是双系统,切换系统比较麻烦]。我们仅仅考虑乱码出现在的位置。也就是说,我认为乱码是windows导致的,linux站在正义的一方,让windows来配合linux的步伐。

乱码出现的位置可以划分为两类文件名出现乱码文件内容出现乱码

《文件乱码处理》
《文件乱码处理》

《文件乱码处理》

1.2 文件内容乱码出现的原因

作为问题分析的基础,我们需要知道字符编码的基本常识字符编码笔记:ASCII,Unicode 和 UTF-8 – 阮一峰 | 搞懂编码 GBK 和 UTF8

GBK是中国标准,只在中国使用,并没有表示大多数其它国家的编码;而各国又陆续推出各自的编码标准,互不兼容,非常不利于全球化发展。于是后来国际组织发行了一个全球统一编码表,把全球各国文字都统一在一个字符集里,名为Unicode。它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。

乱码的直接原因是编辑器没有识别出文件的编码。下面,我们查看文件内容的编码方式。文件使用的是GB2312,不是 ISO-8859 – wiki 字符集。关于CLRF和LF的问题,我没有遇见过。如果遇见,我们或许可以参考:DOS 与 Linux 的断行字符 | Git 多平台换行符问题(LF or CRLF)

$ file lab11.tcl
lab11.tcl: ISO-8859 text, with CRLF line terminators

$ enca lab11.tcl
Simplified Chinese National Standard; GB2312
  CRLF line terminators
 
 # 我猜测file命令没有识别出文件编码,最后也不好意思说自己没识别出来,所报了ISO-8859
 # 因为ISO-8859-n,似乎不能显示中文

我用gedit打开这个文件,没有乱码;然而,我用vim打开同样的文件,出现乱码啦。

《文件乱码处理》
《文件乱码处理》

换句话说,gedit识别出文件的编码方式,但是vim没有。那么问题来了:gedit是如何识别出文件的编码方式,vim如何添加自动识别文件编码的功能。

2. 解决文件内容乱码问题

2.1 gedit文本编辑器的配置

这是一个比较有意思的问题。我google了下,看到gedit 配置 系列的文章。这样的文章是不能让我满意的。因为文中没有告诉我gsettings是东东。接着搜索,找到两篇不错的介绍:GNOME (简体中文) – Archwki | Gedit中文乱码 – ubuntu wiki

gnome 包含基本的桌面环境和一些集成良好的应用程序Gedit是一个应用集成在gnome中。

GNOME 系统设置面板(gnome-control-center)和 GNOME 应用使用 dconf 配置系统存储设置。

我们可以使用 gsettingsdconf 命令行工具直接访问 dconf 数据库。

我们通过man gsettings | gedit 配置 来耍耍,看看有gedit是如何识别出文件编码方式。

# 列出已安装的,不可重定位的schemas。 [我没去查可重定位和不可重定位]
$ gsettings list-schemas

# 过滤出和gedit相关的schemas
$ gsettings list-schemas | grep gedit

# Lists the keys in SCHEMA
$  gsettings list-keys org.gnome.gedit.preferences.encodings
candidate-encodings

# Gets the value of KEY. The value is printed out as a serialised GVariant.
# 让人很是迷惑:gedit默认编码匹配列表为空
# 剧情发展和我想的不一样啊
$ gsettings get  org.gnome.gedit.preferences.encodings candidate-encodings
['']

然后,我接着上网找啊找啊找。

看到,这个, gedit修改的diff记录。其中有两句话,比较有意思。

List of candidate encodings shown in the Character Encoding menu in the open/save file chooser.

The default value is the empty list, in which case gedit will choose good defaults depending on the country and language

在打开和保存文件的时候,显示编码选择。

默认list中为空,gedit默认会根据国际和语言,做成好的选择

+    <key name="candidate-encodings" type="as">
+      <default>['']</default>
+      <summary>Candidate Encodings</summary>
+      <description>List of candidate encodings shown in the Character Encoding menu in the open/save file chooser.
+      "CURRENT" represents the current locale encoding. Only recognized encodings are used.
+      The default value is the empty list, in which case gedit will choose good defaults depending on the country and language.</description>
+    </key>

《文件乱码处理》

目前,我不知道已选编码是如何配置上去的。深度暂时到这一步吧。

2.2 vim编码配置

这个比较容易解决:vim 官方中文文档

  • encoding 选项告诉Vim你所用的字符的编码。该选项适用于缓冲区的文本(你正在编辑的文件),寄存器,Vim脚本文件等等。你可以把’encoding’选项当作是对Vim内部运行机制的设定。

  • fileencodings 选项中的编码名称检测你在编辑哪种文件。当使用Unicode时,缺省的选项值是: “ucs-bom,utf-8,latin1,chiness”。找不见的时候,默认是简体中文编码(Unix和Windows上都可以用chinese作为编码名)。

  • fileencoding 当你开始编辑一个16位的Unicode编码,而该文件有BOM时,Vim会检测到这些并在读取文件时将其转换为utf-8编码。fileencoding选项(后面没有s)被设为检测到的值。当写入文件时,Vim会比较’fileencoding’和’encoding’的值。如果它们的值不同,文本会被转换。如果’fileencoding’的值是空的,意味着不作任何转换。这样文本就会被以’encoding’的值来编码

# ~/.vimrc
" let &termencoding = &encoding set encoding=utf-8 " 检测编辑的是哪种文件
set fileencodings=ucs-bom,utf-8,GB2312,latin1,chinese

2.3 文件内容编码转换

通过vim的方式,我们查看和编辑不同编码格式的文件,都没有问题。需要注意的是,文件原来的编码方式的方式并没有改变。

下面我们直接将文件内容改成utf-8格式。

$ enca [-L zh_CN]  # file 检查文件的编码
$ enca [-L zh_CN] -x UTF-8 file # 将文件编码转换为"UTF-8"编码
$ enca [-L zh_CN] -x UTF-8 file1 file2 # 若是不想覆盖原文件能够这样
$ enca -x utf-8 * # 转换多个文件的编码
# 批量转换
# default为批量转换的目录名,转换的之后的文件存储在utf目录中
$ find default -type d -exec mkdir -p utf/{ } \; 
$ find default -type f -exec iconv -f GBK -t UTF-8 { } -o utf/{ } \;

3. 分析并解决文件名乱码问题

3.1 分析文件名乱码的原因

这是一个比较有意思的问题。下面是我的推测,没有验证出来。

推测:目录项文件中,存储的内容,使用了不同的编码方式

文件名存储在目录项中[如果不明白文件和目录的关系,可以参考这篇]。我们直接vim 目录,查看内容。

《文件乱码处理》

可以看到文件名是乱码状态。termencoding是终端使用的编码方式。termencoding缺省的时候,和encoding保持一致。查看了下,此时我的encoding为utf-8。

我修改termencoding=gbk,有不对的效果。可以看到,乱码的位置以不同的方式乱码了

《文件乱码处理》

3.2 解决文件名乱码的问题

# 网上搜索,基本是这个操作
$ convmv -f cp936 -t utf-8 -r --notest  cp936文件名
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/╩╡╤Θ╦╡├≈.txt
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab23/Ad Hoc═°┬τ┬╖╙╔╨¡╥Θ╨º╣√╖╓╬÷.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab13/TCP Vegas║═Reno ╘╦╨╨╬╩╠Γ╖╓╬÷.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab13/all╕▒▒╛.jpg
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab22/╥■▓╪╜ß╡π╙δ▒⌐┬╢╜ß╡π.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab12/NewReno╙δSACK▒╚╜╧.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab11/Tahoe╙δReno▒╚╜╧.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ/lab26/╬▐╧▀═°┬τ╡─┤½╩Σ╬╩╠Γ╠╜╠╓-╨º╣√╥∞│ú.doc
Skipping, already UTF-8: 计算机网络-实验/╕▀╡╚╝╞╦π╗·═°┬τ-╩╡╤Θ
Skipping, already UTF-8: ./计算机网络-实验
Ready! I converted 0 files in 0 seconds.

# 提示已经是UTF-8类型,跳过
# 使用ubuntu自带的归档器解压的时候,归档器做了什么
# File Roller地址:https://wiki.gnome.org/Apps/FileRoller

# 我在网上搜索了一圈没有找到答案,仅仅找到解决办法
$ unzip -O cp936 计算机网络-实验.zip
Archive:  计算机网络-实验.zip
   creating: 高等计算机网络-实验/
   creating: 高等计算机网络-实验/lab11/
  inflating: 高等计算机网络-实验/lab11/lab11.tcl  
  inflating: 高等计算机网络-实验/lab11/Tahoe与Reno比较.doc

或许去底层查看它的编码方式可以知道答案。

4. 其他

4.1 file命令查看文件信息和类型

file命令:Linux file命令 – c语言中文网 | Linux file命令 – 鸟哥私房菜 | man file

对于 的大佬来说,遇到不清楚的地方可以直接去看file 源码 。我这个小菜鸡最高级的操作莫过于看man手册啦。

file会测试每个参数以尝试对其进行分类。 有三组测试,按此顺序执行:文件系统测试,魔术测试和语言测试。 第一个成功的测试导致打印文件类型。

可打印的类型通常包含以下单词之一:text(文件仅包含打印字符和一些常用控制字符,并且可能在ASCII终端上可以安全读取),executable ( 一种对于某些UNIX内核或其他UNIX内核可理解的形式,或表示其他含义的数据),data(数据通常是“二进制”或不可打印的)。 例外是众所周知的文件格式(核心文件,tar存档),其中包含二进制数据。 将本地定义添加到/ etc / magic时,请确保保留这些关键字。

如果文件与魔术文件中的任何条目都不匹配,那么将检查该文件是否似乎是文本文件。 ASCII,ISO-8859-x,非ISO 8位扩展ASCII字符集(例如在Macintosh和IBM PC系统上使用的字符集),UTF-8编码的Unicode,UTF-16编码的Unicode和EBCDIC字符集都可以 区别在于构成每个集合中可打印文本的字节的不同范围和顺序。 如果文件通过了这些测试中的任何一个,则报告其字符集。 ASCII,ISO-8859-x,UTF-8和扩展ASCII文件被标识为“文本”,因为它们几乎可以在任何终端上读取; UTF-16和EBCDIC只是“字符数据”,因为尽管它们包含文本,但这些文本需要翻译才能被读取。 此外,文件将尝试确定文本类型文件的其他特征。如果文件的行以CR,CRLF或NEL而不是Unix标准LF终止,则报告输出。 包含嵌入式转义序列或过分敲击的文件也将被识别。

一旦文件确定了文本类型文件中使用的字符集,它将尝试确定文件以哪种语言编写。 语言测试将查找可出现在文件前几个块中任何位置的特定字符串(参见<names.h>)。 例如,关键字.br表示该文件很可能是troff(1)输入文件,就像关键字struct表示C程序一样。 这些测试不如前两组可靠,因此最后执行。 语言测试例程还测试某些杂项(例如tar(1)存档)。

第一次查看文件编码的时候,我想都没想敲了一个file命令。file命令用于查看查看文件信息或类型。比如我想查看一个shell脚本的文件信息,它会输出如下内容。此时,我好奇file命令每次会输出哪些关于文件信息的内容,所以 查了file命令的man文档。

$ file create-image.sh
create-image.sh: Bourne-Again shell script, UTF-8 Unicode text executable

4.2 x windows 介绍

上面2.1中介绍gedit的时候,提到GNOME,那么不得不提x windows。

下面我复制鸟哥内容过来,详细见:第二十四章、 X Window 配置介绍

X Window system 是个利用网络架构的图形使用者介面软件,那到底这个架构可以分成多少个组件呢? 基本上是分成 X Server 与 X Client 两个组件而已喔!其中 X Server 在管理硬件,而 X Client 则是应用程序。 在运行上,X Client 应用程序会将所想要呈现的画面告知 X Server ,最终由 X server 来将结果透过他所管理的硬件绘制出来! 整体的架构我们大约可以使用如下的图示来作个介绍

《文件乱码处理》

上面的图示非常有趣喔!我们在用户端想要取得来自服务器的图形数据时,我们用户端使用的当然是用户端的硬件设备啊, 所以,X Server 的重点就是在管理用户端的硬件,包括接受键盘/鼠标等设备的输入资讯, 并且将图形绘制到萤幕上 (请注意上图的所有组件之间的箭头指示)。但是到底要绘制个啥东西呢? 绘图总是需要一些数据才能绘制吧?此时 X Client (就是 X 应用程序) 就很重要啦!他主要提供的就是告知 X Server 要绘制啥东西。那照这样的想法来思考,我们是想要取得远程服务器的绘图数据来我们的计算机上面显示嘛! 所以罗,远程服务器提供的是 X client 软件啊!

X Window Manager:特殊的 X Client ,负责管理所有的 X client 软件

刚刚前面提到,X Client 的主要工作是将来自 X Server 的数据处理成为绘图数据,再回传给 X server 而已, 所以 X client 本身是不知道他在 X Server 当中的位置、大小以及其他相关资讯的。这也是上面我们谈到的, X client 彼此不知道对方在萤幕的哪个位置啊!为了克服这个问题,因此就有 Window Manager (WM, 窗口管理员) 的产生了。 窗口管理员也是 X client ,只是他主要在负责全部 X client 的控管,还包括提供某些特殊的功能,例如:

  • 提供许多的控制元素,包括工作列、背景壁纸的配置等等;
  • 管理虚拟壁纸 (virtual desktop);
  • 提供窗口控制参数,这包括窗口的大小、窗口的重叠显示、窗口的移动、窗口的最小化等等。

我们常常听到的 KDE, GNOME, XFCE 还有簡易到爆的 twm 等等,都是一些窗口管理员的专案计画啦! 这些专案计画中,每种窗口管理员所用以开发的显示引擎都不太相同,所著重的方向也不一样, 因此我们才会说,在 Linux 底下,每套 Window Manager 都是独特存在的,不是换了壁纸与显示效果而已, 而是连显示的引擎都不会一样喔!底下是这些常见的窗口管理员全名与连结:

  • GNOME (GNU Network Object Model Environment):http://www.gnome.org/
  • KDE (K Desktop Enviroment):http://kde.org/
  • twm (Tab Window Manager):http://xwinman.org/vtwm.php
  • XFCE (XForms Common Environment):http://www.xfce.org/

《文件乱码处理》

    原文作者:大1234草
    原文地址: https://blog.csdn.net/sinat_38816924/article/details/109828767
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞