Tenemos el hallazgo a este dilema, o por lo menos eso creemos. Si tienes preguntas puedes dejarlo en el apartado de comentarios, para nosotros será un gusto ayudarte
Solución:
No existe una forma 100% segura de reconocer la codificación ANSI (por ejemplo, Windows-1250) de la codificación UTF-8. Ahí son archivos ANSI que no poder ser UTF-8 válido, pero cada un archivo UTF-8 válido también podría ser un archivo ANSI diferente. (Sin mencionar los datos solo ASCII, que son ambas cosas ANSI y UTF-8 por definición, pero eso es puramente un aspecto teórico).
Por ejemplo, la secuencia C4 8D podría ser el carácter “č” en UTF-8, o podría ser “ÄŤ” en Windows-1250. Ambos son posibles y correctos. Sin embargo, por ejemplo, 8D 9A puede ser “Ťš” en Windows-1250, pero no es un UTF-8 válido string.
Tienes que recurrir a algún tipo de heurística, por ejemplo
- Si el archivo contiene una secuencia que no puede ser un UTF-8 válido, asuma que es ANSI.
- De lo contrario, si el archivo comienza con UTF-8 BOM (EF BB BF), asuma que es UTF-8 (sin embargo, es muy improbable que un archivo ANSI de texto sin formato comience con tales caracteres).
- De lo contrario, suponga que es UTF-8. (O pruebe con más heurísticas, tal vez utilizando el conocimiento del idioma del texto, etc.)
Véase también el método utilizado por el Bloc de notas.
Si el archivo UTF comienza con la marca de orden de bytes (BOM) UTF-8, esto es fácil:
function UTF8FileBOM(const FileName: string): boolean;
var
txt: file;
bytes: array[0..2] of byte;
amt: integer;
begin
FileMode := fmOpenRead;
AssignFile(txt, FileName);
Reset(txt, 1);
try
BlockRead(txt, bytes, 3, amt);
result := (amt=3) and (bytes[0] = $EF) and (bytes[1] = $BB) and (bytes[2] = $BF);
finally
CloseFile(txt);
end;
end;
De lo contrario, es mucho más difícil.
Si nosotros veraneardespués:
- La mejor solución para básico el uso es usar desactualizado (si usamos IsTextUnicode (););
- La mejor solución para avanzado el uso es usar la función anterior, luego verifique la lista de materiales (~ 1 KB), luego verifique la información de configuración regional en el sistema operativo particular y solo luego continúe 98% ¿precisión?
OTRA INFORMACIÓN QUE LA GENTE PUEDE ENCONTRAR INTERESANTE:
https://groups.google.com/forum/?lnk=st&q=delphi+WIN32+funciones+para+detectar+qué+codificación++está+en+uso&rnum=1&hl=pt-BR&pli=1#!topic/borland .public.delphi.internacionalización.win32/_LgLolX25OA
function FileMayBeUTF8(FileName: WideString): Boolean;
var
Stream: TMemoryStream;
BytesRead: integer;
ArrayBuff: array[0..127] of byte;
PreviousByte: byte;
i: integer;
YesSequences, NoSequences: integer;
begin
if not WideFileExists(FileName) then
Exit;
YesSequences := 0;
NoSequences := 0;
Stream := TMemoryStream.Create;
try
Stream.LoadFromFile(FileName);
repeat
read from the TMemoryStream
BytesRead := Stream.Read(ArrayBuff, High(ArrayBuff) + 1);
Do the work on the bytes in the buffer
if BytesRead > 1 then
begin
for i := 1 to BytesRead-1 do
begin
PreviousByte := ArrayBuff[i-1];
if ((ArrayBuff[i] and $c0) = $80) then
begin
if ((PreviousByte and $c0) = $c0) then
begin
inc(YesSequences)
end
else
begin
if ((PreviousByte and $80) = $0) then
inc(NoSequences);
end;
end;
end;
end;
until (BytesRead < (High(ArrayBuff) + 1));
//Below, >= makes ASCII files = UTF-8, which is no problem.
//Simple > would catch only UTF-8;
Result := (YesSequences >= NoSequences);
finally
Stream.Free;
end;
end;
Ahora probando esta función…
En mi humilde opinión, la única forma de COMENZAR a realizar esta verificación correctamente es verificar el conjunto de caracteres del sistema operativo en primer lugar porque, al final, casi en todos los casos se hacen algunas referencias al sistema operativo. No hay forma de escapar de todos modos…
Observaciones:
- La función WideFileExists() se toma de TntClasses.pas (fuente de Koders.net).
Reseñas y calificaciones de la guía
Recuerda que puedes optar por la opción de interpretar .