// 把Unicode编码的文件另存为Ansi编码的文件
// 未考虑文件名为Unicode的情况,因为没有这样的文件,不知如何判断。
function FileUnideToAnsi(UnicodeFileName,AnsiFileName : String) : Boolean;
var
  aFileStream : TFileStream;
  ReturnValue,BuffSize,AnsiLen : Int64;
  Buffer : array of Byte;
  aWideString : WideString;
  PtmpStr : PChar;
  errCode : Cardinal;
begin
Result := False;
  if not FileExists(UnicodeFileName) then exit;  aFileStream := TFileStream.Create(UnicodeFileName,fmOpenRead);
  memo1.Lines.add('文件流大小:' + intTostr(aFileStream.Size));  afileStream.Position := 0;
  BuffSize := 2;
  setLength(Buffer,BuffSize);
  if afileStream.Read(Buffer[0],BuffSize) <> BuffSize then exit;
  memo1.Lines.add('读标志返回:' + intToHex(Buffer[0],2) + intToHex(Buffer[1],2));
  if intToHex(Buffer[0],2) + intToHex(Buffer[1],2) <> 'FFFE' then exit; // 不是Unicode文本  afileStream.Position := 2; // 前面的标志不读
  BuffSize := (afileStream.Size -2);
  setLength(aWideString,BuffSize);
  ReturnValue := afileStream.Read(PWideString(aWideString),BuffSize);
  memo1.Lines.add('读流返回字节数:' + intToStr(ReturnValue));
  memo1.Lines.add('aWideString大小:' + intTostr(length(aWideString))); // 在这里报错,为什么?  AnsiLen := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), BuffSize, PtmpStr,  0, Nil, Nil); //这个调用方法,有问题吗?
  memo1.Lines.add('转换后的字符串大小:' + intTostr(AnsiLen));
  getMem(PtmpStr,AnsiLen + 1);
  try
    ReturnValue := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), BuffSize, PtmpStr,  AnsiLen , Nil, Nil);    errCode := getLastError;
    if errCode = NOERROR then
      memo1.Lines.add('转换成功')
    else if errCode = ERROR_INSUFFICIENT_BUFFER then
      memo1.Lines.add('错误:ERROR_INSUFFICIENT_BUFFER')
    else if errCode = ERROR_INVALID_FLAGS then
      memo1.Lines.add('错误:ERROR_INVALID_FLAGS')
    else if errCode = ERROR_INVALID_PARAMETER then
      memo1.Lines.add('错误:ERROR_INVALID_PARAMETER')
    else
      memo1.Lines.add('未知错误值:' + intToStr(errCode));
    if ReturnValue = 0 then exit; //转换不成功    memo1.Lines.add('返回值:' + intTostr(ReturnValue));
    memo1.Lines.Add(strpas(PtmpStr));
    aFileStream.NewInstance; //用free不行,用这个也有问题,该怎么用?
    If not FileExists(AnsiFileName) then
      Fileclose(FileCreate(AnsiFileName));
    aFileStream.Create(AnsiFileName,fmOpenWrite);
    aFileStream.Write(PtmpStr,ReturnValue);
    result := True;
  finally
    aFileStream.Free;
   freeMem(PtmpStr,AnsiLen + 1);
  end;
end;

解决方案 »

  1.   

    在公司有的,不现在在宿舍,重头输入,苦:(// unicode文本都是以FF FE开头的。
    function isUnicode(filename: string): boolean;
    var
      f: file of byte;
      b1, b2: Byte;
    begin
      result := false;
      try
        AssignFile(F, filename);
        Reset(f);
        Read(f, b1);
        Read(f, b2);
        if (b1 = $FF) and (b2 = $FE) then
          Result := true;
      finally
        CloseFile(f);
      end;
    end;function UnicodeFileToString(FileName, newfilename: string): boolean;
    const
      iUnicodeLen = 4;
    var
      p: Pointer;
      ms: TMemoryStream;
      i: integer;
    begin
      result := false;
      if not isUnicode(FileName) then
        exit;
      ms := nil;
      ms := TMemoryStream.Create;
      try
        ms.LoadFromFile(FileName);
        i := integer(ms.memory);
        p := nil;
        p := Ptr(i - iUnicodeLen); // 前4个这字节不是需要的内容。
        WideCharLenToString(p, ms.Size - iUnicodeLen);
        ms.SaveToFile(newfilename);
        result := true;
      finally
        ms.Free;
      end;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
    // WideCharToMultiByte()
    //  WideCharLenToString();
      if UnicodeFileToString(Edit1.Text, 'c:\a.txt') then
        showmessage('ok');
    end;
      

  2.   

    错处较多,无时间排错,现在可转换可以了,但还有错,自己找找吧,帮不了那么多// 把Unicode编码的文件另存为Ansi编码的文件
    // 未考虑文件名为Unicode的情况,因为没有这样的文件,不知如何判断。
    function FileUnideToAnsi(UnicodeFileName,AnsiFileName : String) : Boolean;
    var
      aFileStream : TFileStream;
      ReturnValue,BuffSize,AnsiLen : Int64;
      Buffer : array of Byte;
      aWideString : WideString;
      PtmpStr : PChar;
      errCode : Cardinal;
    begin
      with form1 do
      begin
      Result := False;
        if not FileExists(UnicodeFileName) then exit;
        aFileStream := nil; //
    //    aFileStream := TFileStream.Create(UnicodeFileName,fmOpenRead);
        aFileStream := TFileStream.Create(UnicodeFileName,fmOpenRead or fmsharedenywrite);
        mmo1.Lines.add('文件流大小:' + intTostr(aFileStream.Size));    afileStream.Position := 0;
        BuffSize := 2;
        setLength(Buffer,BuffSize);
        if afileStream.Read(Buffer[0],BuffSize) <> BuffSize then exit;
        mmo1.Lines.add('读标志返回:' + intToHex(Buffer[0],2) + intToHex(Buffer[1],2));
        if intToHex(Buffer[0],2) + intToHex(Buffer[1],2) <> 'FFFE' then exit; // 不是Unicode文本    afileStream.Position := 2; // 前面的标志不读
        BuffSize := (afileStream.Size -2);
        setLength(aWideString,BuffSize);
    //    ReturnValue := afileStream.Read(PWideString(aWideString),BuffSize);
        ReturnValue := afileStream.Read(PWideString(aWideString)^, BuffSize); // 读到变量内存,所以要是变量的值。
        mmo1.Lines.add('读流返回字节数:' + intToStr(ReturnValue));
        mmo1.Lines.add('aWideString大小:' + intTostr(length(aWideString))); // 在这里报错,为什么?//    AnsiLen := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), BuffSize, PtmpStr,  0, Nil, Nil); //这个调用方法,有问题吗?
        PtmpStr := nil;
        AnsiLen := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), -1, PtmpStr,  0, Nil, Nil); //这个调用方法,有问题吗?
          ShowMessage(SysErrorMessage(GetLastError));
        mmo1.Lines.add('转换后的字符串大小:' + intTostr(AnsiLen));
        getMem(PtmpStr,AnsiLen + 1);
        try
    //      ReturnValue := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), BuffSize, PtmpStr,  AnsiLen, Nil, Nil);
          ReturnValue := WideCharToMultiByte(CP_ACP, 0, PWideChar(aWideString), -1, PtmpStr,  AnsiLen, Nil, Nil);
          ShowMessage(SysErrorMessage(GetLastError));
    //      if ReturnValue = 0 then exit; //转换不成功      mmo1.Lines.add('返回值:' + intTostr(ReturnValue));
          PtmpStr[ReturnValue] := #0;
          mmo1.Lines.Add(strpas(PtmpStr));
    //      aFileStream.NewInstance; //用free不行,用这个也有问题,该怎么用?
          aFileStream.Free;
    //      If not FileExists(AnsiFileName) then
    //        Fileclose(FileCreate(AnsiFileName));
    //      aFileStream.Create(AnsiFileName,fmOpenWrite);
          aFileStream := TFileStream.Create(AnsiFileName,fmOpenWrite);
    //      aFileStream.Write(PtmpStr, ReturnValue);
          aFileStream.Write(PtmpStr^, ReturnValue);
          result := True;
        finally
          aFileStream.Free;
        freeMem(PtmpStr,AnsiLen + 1);
        end;
      end; // with
    end;
      

  3.   

    转载我也没用过
    Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串.int MultiByteToWideChar(    UINT CodePage, // code page 
        DWORD dwFlags, // character-type options 
        LPCSTR lpMultiByteStr, // address of string to map 
        int cchMultiByte, // number of characters in string 
        LPWSTR lpWideCharStr, // address of wide-character buffer 
        int cchWideChar  // size of buffer 
       );uCodePage参数用于标识一个与多字节字符串相关的代码页号。dwFlags参数用于设定另一个控件,
    它可以用重音符号之类的区分标记来影响字符。这些标志通常并不使用,而在dwFlags参数
    中则传递0。pMultiByteStr参数用于设定要转换的字符串,cchMultiByte参数用于指明
    该字符串的长度(按字节计算)。如果你为cchMultiByte参数传递-1,那么该函数用于
    确定源字符串的长度。转换后产生的Unicode版本字符串将被写入内存中的缓存,其地址
    由pWideCharStr参数指定。你必须在cchWideChar参数中设定该缓存的最大值(以字符为
    计量单位)。如果你调用MultiByteToWideChar,给cchWideChar参数传递0,那么该参数
    将不执行字符串的转换,而是返回为使转换取得成功所需要的缓存的值。通过下列步骤
    将多字节字符串转换成Unicode等价字符串:1. 调用MultiByteToWideChar函数,为pWideCharStr参数传递NULL,为cchWideChar
    参数传递0。
    2. 分配足够的内存块,用于存放转换后的Unicode字符串。该内存块的大小值由前面的对MultByteToWideChar的调用返回。
    3. 再次调用MultiByteToWideChar,这次将缓存的地址作为pWideCharStr参数来传递,并传递第一次调用MultiByteToWideChar时返回的缓存大小值,作为cchWidechar参数。
    4. 使用转换后的字符串。
    5. 释放Unicode字符串占用的内存块。