【delphi】判断文件的编码方式(ANSI、Unicode、UTF8、UnicodeBIG)

本文介绍如何通过编程实现文件编码的自动判断和转换,包括判断文件的ANSI、Unicode和UTF-8编码,提供实用的函数代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开发中,经常会碰到文件编码格式不正确,有时也需要进行编码转换,具体的编码原理可以自行查找,这里记录下我的处理方式。根据这个原理稍加修改即可实现编码转换和自动判断。

{判断文件的编码方式,可以实现编码转化
 sensor
 2018-08-02
}
unit uCODE_Convert;

interface
uses
  Winapi.Windows,
  System.SysUtils,
  System.Variants,
  System.Classes;

type
  TCODE_TYPE = (ctANSI,ctUnicode,ctUTF8,ctUnicodeBIG);


//判断一个文件的编码格式
//入口参数:FieName文件名称
//出口参数:文件类型
function Get_FileCode_TYPE(FileName : string) : TCODE_TYPE;

//判断一个文件是不是ANSI编码,判断标准是 大于$80的字节必须偶数出现,
//内容中不能出现$00 否则肯定不是,如果全部是,则表示是ANSI编码
//入口:文件字节流
//出口:True 表示时ANSI编码,否则不是ANSI编码
function is_ANSI_CODE(M : TMemoryStream) : Boolean;

//判断是否是UTF8
function is_UTF8_CODE(BB : TBytes) : Boolean;

function GetEncodingType(code: TCODE_TYPE): Tencoding;

function GetFileEncoding(FileName : string) : Tencoding;

implementation

function GetFileEncoding(FileName : string) : Tencoding;
var
  code: TCODE_TYPE;
begin
  code := Get_FileCode_TYPE(FileName);
  result := GetEncodingType(code);
end;

function GetEncodingType(code: TCODE_TYPE): Tencoding;
begin
  case code of
    ctANSI:
      result := TEncoding.ANSI;
    ctUnicode:
      result := TEncoding.Unicode;
    ctUTF8:
      result := TEncoding.UTF8;
    ctUnicodeBIG:
      result := TEncoding.BigEndianUnicode
    else
      result := TEncoding.ANSI;
  end;
end;

//判断一个文件的编码格式
function Get_FileCode_TYPE(FileName : string) : TCODE_TYPE;
var
  MF : TMemoryStream;
  MB : TBytes;
  B  : Byte;
  Position,Len,i : Int64;
  D80 : Int64;
  isANSI : Boolean;
begin
  //首先打开文件
  if not FileExists(FileName) then Exit(ctANSI);
  MF := TMemoryStream.Create;
  MF.LoadFromFile(FileName);
  MF.Position := 0;
  Len := MF.Size;
  SetLength(MB,Len);
  MF.Read(MB[0],Len);       //读取数据到内存表中
  MF.Free;
  try
     //1. 首先根据标志判断 FF FE?
     if (MB[0] = $FF) and (MB[1] = $FE) then Exit(ctUnicode);   //Unicode
     //2. 首先根据标志判断 FE FF?
     if (MB[0] = $FE) and (MB[1] = $FF) then Exit(ctUnicodeBIG);   //ctUnicodeBIG
     //3. 首先根据标志判断 EF BB BF?
     if (MB[0] = $EF) and (MB[1] = $BB) and (MB[2] = $BF) then Exit(ctUTF8);   //ctUTF8

     //下面判断是否是UTF8
     if is_UTF8_CODE(MB) then exit(ctUTF8);
     //下面判断是否是ANSI ,同时又确认Unicode
     isANSI := True;
     for i := 0 to Len - 1 do
       begin
         B := MB[i];
         if B = 0 then
           if (Len Mod 2) = 0 then  //说明是Unicode ,此时需要判断是不是 Big
            begin
              if i = 0 then Exit(ctUnicodeBIG);   //第一个就是0,并且是偶数字节,可以确定是ctUnicodeBIG
              if MB[i - 1] < $80 then
                 Exit(ctUnicode)             //第一个$00的前面是小于$80,说明是Unicode, 否则是UnicodeBig
              else
                 Exit(ctUnicodeBIG)
            end
           else
            begin
              isANSI := False;
              Break;   //出现0字符,长度又不是偶数字节,可以确定表示不是ANSI
            end;
       end;

     if isANSI then Exit(ctANSI);

  finally
   // MF.Free;
  end;

end;


function is_ANSI_CODE(M : TMemoryStream) : Boolean;
var
  MB : TBytes;
  B : Byte;
  Position,Len,i : Int64;
  D80 : Int64;
begin
  Result := False;
  Len := M.Size;       //文件长度
  M.Position := 0;     //从第一个开始
  D80 := 0;              //默认$80数
  SetLength(MB,Len);
  M.Read(MB[0],Len);     //读取到内存中
  for i := 0 to Len - 1 do
    begin
      B := MB[i];
      if B = 0 then Exit(False);  //出现0字符,表示不是ANSI
      if B >= $80 then
        D80 := D80 + 1
      else
        if (D80 mod 2) = 0 then
          D80 := 0
        else
          Exit(False);
    end;
  Result := True;
end;


//判断是否是UTF8
function is_UTF8_CODE(BB : TBytes) : Boolean;
var
  B : Byte;
  Position,Len,i : Int64;
  D80 : Int64;
begin
  Result := True;
  Len := Length(BB);
  i := 0;
  while (i < Len - 1) do
    begin
      B := BB[i];
      if B < $80 then
        begin
          i := i + 1;
          Continue;
        end;
      if B < $C0 then  // (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符
        begin
          Exit(False);
        end;

      if B < $E0 then  // (11100000): 此范围内为2字节UTF-8字符
        begin
          if i >= (Len - 1) then  Exit(False);
          if (BB[ i + 1 ] and $C0) <> $80 then Exit(False);
          i := i + 2;
        end;

      if B < $F0 then  // (11110000): 此范围内为3字节UTF-8字符
        begin
          if i >= (Len - 1 - 1) then  Exit(False);
          if ((BB[ i + 1 ] and $C0) <> $80) and ((BB[ i + 2 ] and $C0) <> $80) then Exit(False);
          i := i + 3;
        end
      else
        Exit(False);
    end;

end;

end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海纳老吴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值