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 :
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 :
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
Partager