Saltar al contenido

Detección del tipo de archivo ‘texto’ (ANSI vs UTF-8)

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

  1. Si el archivo contiene una secuencia que no puede ser un UTF-8 válido, asuma que es ANSI.
  2. 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).
  3. 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 .

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *