windows下文件编码和读写注意

最近写了一个小工具,主要实现自动搜索指定路径下所有文本文件内容,并替换指定字符串,记录下几个容易犯错误的地方。

1,fread读出来的buffer存放到string里,如果要搜索指定的字符串,比如“中华人民共和国”,首先要确定文件的编码格式是什么?根据文件的编码格式,对目标串进行编码转换后,才能用string.find去进行查找。

而如何判断文件的编码格式呢,windows下文本文件一般有两种字符集,unicode和gbk,根据文件的前三个字节来决定该文件的编码格式,这三个字节是 “EF BB BF”,如果前三个字节为这三个值,就默认为utf8编码的,否则默认为gbk。

题外话:当然上面的判断比较粗略,因为windows下也可以使用utf16来编码存储文件,打开记事本,另存的时候,使用unicode来编码,或者unicode big endian来编码。windows的记事本会在文件前面用BOM来存储文件的编码格式

UTF8编码的BOM为 EF BB BF

utf16编码的BOM 为FF FE

utf16 big endian为 FE FF ,

通常uft16也被叫做UCS编码,通常在windows上我们讲unicode编码,就是指utf16编码。也有一些术语称之为宽字符,因为他使用两个字节来存储文字,即便是ascii码,也使用两个字节来存储。

那么有人会问,难道单纯根据前三个字节来判断文件编码格式不会有问题,当然会有问题了,比如你用notepad新建一个文本文件,写入“联通”两个字,然后保存,再次打开,你会发现文件成乱码了。

为啥呢,因为windows记事本把它当做了utf8编码来识别了,到了这里有人会问,不是说utf8都有BOM头来标识这个是utf8编码的文件么?没错,utf8并没有强制使用BOM头,有BOM头的utf8文件,也可以转换为utf8无bom编码的格式,可以使用notpad++测试下,因此不能notepad不能单纯的依靠BOM头来判断是否是utf8编码的,而要对文件中的数据进行简单的编码分析来确定,正是这个原因,才导致识别出错。

首先来看下utf8来的编码结构,utf8是采用1-3个字节对字符进行编码,编码字节数和unicode字符集有严格的对应关系。看下面的对应关系表

Unicode 编码集                  utf8编码结构

U0001 — U007E                   0XXXXXXX

U0080 — U07FF和U0000        110XXXXX  10XXXXXX

U0800 — UFFFF                    1110XXXX 10XXXXXX

联通的gbk字符集是“C1 AA CD A8”

C1 AA 对应的二进制: 1100 0001, 1010 1010

CD AB 对应的二进制:  1100 1101,  1010 1000

请注意红色部分,它和UTF8的编码结构完全一致,因此才误将其认为是utf8无BOM编码的文件。可以使用notepad++打开来查看这个文件的编码格式

2,在windows下,换行使用的\r\n来换行,也就是 0D 0A,所以使用二进制来查看文件的时候,会看到换行的地方有很多0D 0A,但是如果fopen的时候仅仅使用 “r”标记来读文件,会读不出来0D,必须使用“rb”标记来读,同样在写文件的时候,也要用“wb”来写,才能吧0D写进去。

原文查看:http://www.seanyxie.com/windows%E4%B8%8B%E6%96%87%E4%BB%B6%E7%BC%96%E7%A0%81%E5%92%8C%E8%AF%BB%E5%86%99%E6%B3%A8%E6%84%8F/

时间: 2024-10-07 07:47:07

windows下文件编码和读写注意的相关文章

Windows下字符编码转换

有时候经常使用别人用Tabhost+其它的实现demo.单纯利用Tabhost该如何使用呢? 下面看例子: public class MainActivity extends TabActivity { public TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 获取对象 tabHost = getTabH

windows 下文件上传到fastdfs

php.ini 配置 [fastdfs]; the base pathfastdfs_client.base_path = D:/tmp; connect timeout in seconds; default value is 30sfastdfs_client.connect_timeout = 2; network timeout in seconds; default value is 30sfastdfs_client.network_timeout = 60 ; standard l

使用cwRsync实现windows下文件定时同步【转】

1.参考文献: 使用cwRsync实现windows下文件定时同步(备份) 文件同步工具CwRsync的使用方法及常用命令详解 2.背景: 当前的SCADA架构中,有1台Server,5台FE,还有1台Client.其架构如下图所示: 虽然叫法不同,但是他们的安装文件和配置文件是完全一样的.并且大多数情况下,也建议这些服务器上面的配置文件保持一致,这样只需要维护一个版本的config即可,不需要个性化定义每台服务器上面的config文件.由此也带来了一个新的问题,每当我在一台机器上面修改了配置文

使用cwRsync实现windows下文件定时同步

1.参考文献: 使用cwRsync实现windows下文件定时同步(备份) 文件同步工具CwRsync的使用方法及常用命令详解 2.背景: 当前的SCADA架构中,有1台Server,5台FE,还有1台Client.其架构如下图所示: 虽然叫法不同,但是他们的安装文件和配置文件是完全一样的.并且大多数情况下,也建议这些服务器上面的配置文件保持一致,这样只需要维护一个版本的config即可,不需要个性化定义每台服务器上面的config文件.由此也带来了一个新的问题,每当我在一台机器上面修改了配置文

linux下文件编码的查看与转换(转)

通常来说,Windows中默认的文件格式是GBK(gb2312),而Linux一般都是UTF-8,所以Linux下打开windows的文件会有乱码的情况.另外,有时要将文件进行编码转换,如将简体中文转换为繁体中文. 基于以上情况,本文将就在linux下查看和转换文件的编码进行说明. 1.查看文件的编码 1)在Vim中可以直接查看文件编码 :set fileencoding    即可显示文件编码格式. http://www.poluoluo.com/server/201011/98282.htm

linux下文件编码的查看与修改

在Linux中查看文件编码可以通过vim编辑器来查看,在vim命令模式下输入如下命令即可: :set fileencoding //在vim中查看文件编码 如果你只是想查看其它编码格式的文件或者想解决用vim查看文件乱码的问题,那么你可以在~/.vimrc 文件中添加以下内容: set encoding=utf-8 fileencodings=ucs-bom,utf-8,cp936 //在~/.vimrc配置文件中加入 这样就可以让vim自动识别文件编码(可以自动识别UTF-8或者GBK编码的文

windows下go编码转换问题

github上有两个package做编码转换,都是基于iconv,用到了cgo,在linux下没有问题,在windows下用,非常麻烦.采用mingw安装libiconv也不行,一直提示找不到libiconv方法. 最终找到一个官方实现(纯go实现):https://code.google.com/p/go/source/checkout?repo=text gbk转utf-8示例: func gbk2utf8(str byte[]) ([]byte, error) { return iouti

python 学习之Windows 下的编码处理!

问题1: 1 Non-ASCII character '\xe9' in file 问题原因:程序编码上出现问题 解决方法:在程序头部加上代码 #-*- coding: UTF-8 -*- 设置代码编码为UTF8即刻正常运行 问题2: windows 下print 乱码 错误原因:源码文件的编码格式为utf-8,但是window的本地默认编码是gbk,所以在控制台直接打印utf-8的字符串当然是乱码了! 解决方法:比较通用的解决方法  完美兼容windows 和 ubuntu import sy

Go之获取Windows下文件是否隐藏

起初,做了个小程序,用来检测磁盘中所有的文件 package main import( "fmt" "io/ioutil" "os" ) var dirpath ="D:\\" func main(){ CheckDir(dirpath) } func CheckDir(dirpath string){ dirs, err := ioutil.ReadDir(dirpath) if err !=nil{ panic("