我在用Delphi做一个项目,其中用到一个Unicode文本,要其中含中文的行,转化为GB2312。
文件下载: http://www.chrsoft.com/download/UnicodeTExt.rar
在该文件中,第一行的第一段是索引,根据索引我知道那一行是不是中文,但:
1。我有第一段的ANSI的字符串,要找出第一段是相应UNICODE码的那个字符串的行
2。找到后,把那一行转化为GB2312,并做进一步处理。
我的做法:
  把文件读到流中,去掉最前面的FFFE,然后做 unicode2GB2312的操作
结果:
乱码。
有给出解决方案的,我付出我的所有分.

解决方案 »

  1.   

    刚才看了一下,在UNICODE文件中中文的“你好”的编码为:60 4f 7d 59
    然后用我自己写的一个函数将UNICODE的“你好”转成普通字符为:4F60597D,(正好高位低位反了反,这个好处理),感觉用我的程序将其读入(得到的是WideString),直接赋给AnsiString应该就可以了,这两个函数:{$IFDEF UNICODE}
    function EncodeWideString(Value:WideString):String;
    //encode the widestring to saveable string
    //2003.03.04
    var
      I:Integer;
    begin
      Result:='';
      for I:=1 to Length(Value) do begin
        Result:=Result+IntToHex(WORD(Value[I]) shr 8,2);
        Result:=Result+IntToHex(WORD(Value[I]) and $00ff,2);
      end;
    end;function DecodeWideString(Value:String):WideString;
    //decode the string to widestring
    //2003.03.04
    var
      I:Integer;
    begin
      Result:='';
      for I:=0 to (Length(Value) div 4)-1 do begin
        Result:=Result+WChar(StrToInt('$'+Value[I*4+1]+Value[I*4+2]) shl 8
            + StrToInt('$'+Value[I*4+3]+Value[I*4+4]));
      end;
    end;
    {$ENDIF}另,以上两个函数做成的UNICODE转换程序可以到:
    http://www.tonixsoft.com/component/tlmpack/utlmpack_Delphi.exe
    下载。
      

  2.   

    下载GB2312-Unicode的Map-table(对应表)
    把Unicode编码文本读入内存然后对文件里面的Unicode字符进行判断如果为GB2312编码的 则保存在一个字符串中输出字符串
      

  3.   

    function unicode2gb(unicodestr: string): string;
    var
      SourceLength      : integer;
      DoneLength        : integer;
      AscNo             : integer;
      Byte1, Byte2, Byte3: integer;
      GbStr             : string;
    begin
      GbStr := '';
      if Trim(unicodestr) = '' then
        exit;  SourceLength := Length(UnicodeStr);
      DoneLength := 1;  repeat
        AscNo := ord(UnicodeStr[DoneLength]);
        case (AscNo and $E0) of
          $E0:
            begin
              Byte1 := (AscNo and $0F) shl 12;
              Inc(DoneLength);
              if DoneLength > SourceLength then
                break;
              AscNo := ord(UnicodeStr[DoneLength]);
              Byte2 := (AscNo and $3F) shl 6;
              Inc(DoneLength);
              if DoneLength > SourceLength then
                break;
              AscNo := ord(UnicodeStr[DoneLength]);
              Byte3 := AscNo and $3F;
            end;
          $C0:
            begin
              Byte1 := (AscNo and $1F) shl 6;
              Inc(DoneLength);
              if DoneLength > SourceLength then
                break;
              AscNo := ord(UnicodeStr[DoneLength]);
              Byte2 := (AscNo and $3F);
              Byte3 := 0;
            end;
          0..$BF:
            begin
              Byte1 := AscNo;
              Byte2 := 0;
              Byte3 := 0;
            end;
        end;                                //case;
        GbStr := GBStr + widechar(Byte1 + Byte2 + Byte3);
        Inc(DoneLength);
        if DoneLength > SourceLength then
          break;
      until DoneLength >= SourceLength;
      result := GbStr;end;  s := unicode2gb(SourceStr);
      

  4.   

    谢谢 tonylk和S.F.!
    我看了tonylk的资料,虽然没能直接用来解决问题,但在看的时候触发我的灵感:原来我的问题不在于不会转化,而在于没有做好Delphi的内存管理!
    研究了相关资料后,问题就解决了。
      S.F. 的转码的方法应该是好的,有利于提高效率,但我觉得在我的项目上这点效果不明显。所以先收着,下次再用到时,好好测试一下,就能大发神威了。
      因为都不是完整的解决方案,所以我就不会给出我的所有了。
      就此结帖。
      

  5.   

    文本文件的开头是 FFFE
    表示你的这是一个Small Endian的unicode文本,它和x86处理器上面的unicode正好相反,需要交换每个word的高字和低字才行,交换完了用一个string(xxxx) 就成了gb2312了