本文整理自网络,侵删。
utf-8编码的文本文档,有的带有BOM (Byte Order Mark, 字节序标志),即0xEF, 0xBB,0xBF,有的没有。用Windows的notepad编辑的文本保存是会自动添加BOM,我们常用UE编辑器在保存utf-8编码的时候也会自动添加BOM,Notepad++默认设置中保存utf-8编码时是无BOM的。其它文本编辑器就没有尝试过,有兴趣的可以自己试试。 utf-8是一种多字节编码的字符集,表示一个Unicode字符时,它可以是1个至多个字节。即在文本全部是ASCII字符时utf-8是和ASCII一致的(utf-8向下兼容ASCII)。utf-8字节流如下所示:
1字节:0xxxxxxx 2字节:110xxxxx 10xxxxxx 3字节:1110xxxx 10xxxxxx 10xxxxxx
按照utf-8编码规则进行验证,例如: 第一个字符的第一个字节的第一个bit为0,说明是个ANSII字符。继续查看第二个字符,若第一个比特是1,则查看第二个比特,若第二个比特为1,如果不为1说明这不是一个utf-8编码的文本。如果第二个比特为1,则查看第三个比特为0,不为0则说明不是utf-8编码,如果是0则说明该字符肯能是2字节的utf-8。查看该字符的第二个字节,如果前两个比特符合10则说明这是一个utf-8编码的字符。依次类推,若一旦有一个bit不满足UTF-8编码要求,就判定文本为ANSI(GBK),若直到文本结束都符合utf-8编码规则,则说明文本是UTF-8编码的。 由上述描述可知字符的第一个字节如果介于0x80与0xC0之间或大于0xF0则不符合utf-8的编码规则,可直接判断不是utf-8编码的文本。如果第一个字节符合utf-8规则且小于0xC0则判断第二个字节,如果第二个字节和0xC0做与操作结果不是0x80则可判断不是utf-8编码的文本。依次类推,如果第一个字节介于0xE0、0xF0之间,且第二个字节符合规则,第三个字节与第二个字节做同样判断,如果符合规则则该字符是utf-8字符,判断下一个字符直到文本结束。具体的代码实现如下所示,这里列了Delphi及C/C++的两种语言的实现结果:
Delphi:
function IsUtf8Format(buffer: PChar; size: Int64): Boolean;var ii: Integer; tmp: Byte;begin Result := True; ii := 0; while ii < size do begin tmp := Byte(buffer[ii]); if tmp < $80 then //值小于0x80的为ASCII字符 Inc(ii) else if tmp < $C0 then //值介于0x80与0xC0之间的为无效UTF-8字符 begin Result := False; Break; end else if tmp < $E0 then //此范围内为2字节UTF-8字符 begin if ii >= size - 1 then Break; if (Byte(buffer[ii + 1]) and $C0) <> $80 then begin Result := False; Break; end; Inc(ii, 2); end else if tmp < $F0 then //此范围内为3字节UTF-8字符 begin if ii >= size - 2 then Break; if ((Byte(buffer[ii + 1]) and $C0) <> $80) or ((Byte(buffer[ii + 2]) and $C0) <> $80) then begin Result := False; Break; end; Inc(ii, 3); end else begin Result := False; Break; end; end;end;
function IsUtf8File(fStream: TFileStream): string;var fStream: TFileStream; context: string;begin fStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try SetLength(context, fStream.Size); fStream.Read(context[1], fStream.Size); if isUtf8Format(PChar(context), fStream.Size) then showMessage('是utf-8编码'); else showMessage('其它编码'); finally fStream.Free; end;end;
C/C++
function IsUtf8Format(buffer: PChar; size: Int64): Boolean;var ii: Integer; tmp: Byte;begin Result := True; ii := 0; while ii < size do begin tmp := Byte(buffer[ii]); if tmp < $80 then //值小于0x80的为ASCII字符 Inc(ii) else if tmp < $C0 then //值介于0x80与0xC0之间的为无效UTF-8字符 begin Result := False; Break; end else if tmp < $E0 then //此范围内为2字节UTF-8字符 begin if ii >= size - 1 then Break; if (Byte(buffer[ii + 1]) and $C0) <> $80 then begin Result := False; Break; end; Inc(ii, 2); end else if tmp < $F0 then //此范围内为3字节UTF-8字符 begin if ii >= size - 2 then Break; if ((Byte(buffer[ii + 1]) and $C0) <> $80) or ((Byte(buffer[ii + 2]) and $C0) <> $80) then begin Result := False; Break; end; Inc(ii, 3); end else begin Result := False; Break; end; end;end;
function Utf8StrToAnsi(fStream: TFileStream): string;var headerStr, context:string;begin fStream.Position := 0; SetLength(HeaderStr, 3); fStream.Read(HeaderStr[1], 3); if HeaderStr = #$EF#$BB#$BF then begin SetLength(context, fStream.Size - 3); fStream.Read(context[1], fStream.Size - 3); end else begin fStream.Position := 0; SetLength(context, fStream.Size); fStream.Read(context[1], fStream.Size); end; Result := Utf8ToAnsi(context);end;――――――――――――――――
原文链接:https://blog.csdn.net/zb361419953/article/details/54408488
相关阅读 >>
Delphi 2009 新增单元 character isletter、isupper、islower、isdigit、isnumber
更多相关阅读请进入《Delphi》频道 >>