J'ai eu récemment à faire ce petit exercice pour un collègue aussi je pense que ça pourrait en intéresser d'autres, à savoir une fonction capable de recopier un fichier encodé en ANSI vers un fichier Unicode.

Voici la bête :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// psFileSourceName : le nom + chemin du fichier source
// psFileDestName : le nom + chemin du fichier destination
// BOM : un tableau d'octets permettant d'inclure un BOM en début de fichier
procedure FileAnsiToUnicode( const psFileSourceName, psFileDestName: String; const BOM: Array of Byte );
var
 StreamSource, StreamDest: TMemoryStream;
 BufferSource: PChar;
 BufferSourceSize: Int64;
 BufferDest: PWideChar;
begin
 // lire le fichier source
 StreamSource := TMemoryStream.Create;
 try
  StreamSource.LoadFromFile( psFileSourceName );
  StreamSource.Seek( 0, soFromBeginning );
  BufferSourceSize := StreamSource.Size;
  GetMem( BufferSource, BufferSourceSize );
  StreamSource.ReadBuffer( BufferSource^, BufferSourceSize );
 
 finally
  StreamSource.Free;
 end;
 
 // allouer la chaîne Unicode de destination faisant le double de la chaîne ANSI source
 // + 1 caractère pour inclure le NULL en fin de chaîne
 GetMem( BufferDest, BufferSourceSize * 2 + 1 );
 try
  // convertir l'ANSI en Unicode (string -> WideString)
  StringToWideChar( BufferSource, BufferDest, BufferSourceSize * 2 + 1 );
 
  // écrire dans le fichier de destination
  StreamDest := TMemoryStream.Create;
  try
   StreamDest.Seek( 0, soFromBeginning );
   // ajouter un BOM (Byte Order Marker) pour signaler que le fichier est Unicode
   StreamDest.WriteBuffer( BOM, SizeOf( BOM ) );
   // copier la chaîne Unicode dans la Stream de destination
   StreamDest.WriteBuffer( BufferDest^, BufferSourceSize * 2 );
   StreamDest.SaveToFile( psFileDestName );
 
  finally
   StreamDest.Free;
  end;
 
 finally
  FreeMem( BufferSource );
  FreeMem( BufferDest );
 end;
 
end;
Et un exemple d'utilisation :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
FileAnsiToUnicode( 'MonFichierSource', 'MonFichierCible', [$FF, $FE] );
Le code précédent inclut le BOM pour UTF-16 Little Endian mais il est également possible de ne pas inclure de BOM en passant tout simplement [] comme paramètre à la procédure.

Je suis sûr que ce code peut être amélioré voire qu'il y ait des cas d'erreurs que je n'ai pas prévu, aussi n'hésitez pas à proposer vos améliorations ou remarques