SOLUCION DESDE DELPHI (funcion añadida)
1. Leer el archivo como texto.
2. Detectar y eliminar el BOM si está presente.
3. Guardar el contenido como UTF-8 sin BOM.
¿Qué es el BOM?
El BOM (Byte Order Mark) en UTF-8 son los tres primeros bytes del archivo:
CÓDIGO EJEMPLO EN DELPHI
Código Delphi
[-]
procedure ConvertUTF8BOMtoUTF8NoBOM(const InputFile, OutputFile: string);
var
FileStream: TFileStream;
StringStream: TStringStream;
BOM: array[0..2] of Byte;
begin
FileStream := TFileStream.Create(InputFile, fmOpenRead or fmShareDenyWrite);
try
FileStream.ReadBuffer(BOM, 3);
if (BOM[0] = $EF) and (BOM[1] = $BB) and (BOM[2] = $BF) then
begin
StringStream := TStringStream.Create('', TEncoding.UTF8);
try
StringStream.CopyFrom(FileStream, FileStream.Size - 3);
StringStream.SaveToFile(OutputFile, TEncoding.UTF8); finally
StringStream.Free;
end;
end
else
begin
FileStream.Position := 0;
StringStream := TStringStream.Create('', TEncoding.UTF8);
try
StringStream.CopyFrom(FileStream, FileStream.Size);
StringStream.SaveToFile(OutputFile, TEncoding.UTF8); finally
StringStream.Free;
end;
end;
finally
FileStream.Free;
end;
end;
Cómo usarlo:
Código Delphi
[-]ConvertUTF8BOMtoUTF8NoBOM('C:\Ruta\archivo_original.ini', 'C:\Ruta\archivo_sin_BOM.ini');
o puedes incluso sobreescribirlo si quieres:
Código Delphi
[-]ConvertUTF8BOMtoUTF8NoBOM('C:\Ruta\mi_archivo.ini', 'C:\Ruta\mi_archivo.ini');
Esa línea:
Código Delphi
[-]if (BOM[0] = $EF) and (BOM[1] = $BB) and (BOM[2] = $BF)
lo que hace es detectar los tres primeros caracteres del archivo codificados como bytes y comprobar si coinciden con la marca BOM de UTF-8, que son estos tres bytes hexadecimales:
$EF = 239 = ï
$BB = 187 = »
$BF = 191 = ¿
Entonces, si ese BOM se interpreta como texto (por ejemplo, en un Memo.Lines.Text), lo que vas a ver es:
Esos son los caracteres raros que ves al principio de muchos archivos .ini, .txt, .json, etc., guardados como UTF-8 con BOM.