Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 11-09-2006
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
ANSI, UNICODE, Big Endian y UTF-8

Hola, amigos,

El otro día estaba intentando hacer un código para extraer el texto de un archivo UNICODE y ponerlo en un TMemo (por ejemplo). Usé los archivos de C:\WINDOWS\inf para probar. El resultado fue exitoso, pero surgieron nuevas dudas:

Diferencia entre UNICODE, UNICODE Big Endian y UTF-8

Además, intenté hacer una función inverse (guardar el texto de un TMemo en un archivo UNICODE). La función está casi hecha, pero tiene un fallo. Aquí estan las dos:

DE ARCHIVO UNICODE A TEXTO ANSI:

Código Delphi [-]
Function UnicodeToAnsi(FileName: String): String;
 
type //Bloque de lectura de 256 KB
  TBloque = array [0..131071] of WideChar;
 
var
  F : File of TBloque;
  F2: File of WideChar;
  C : TBloque;
  C2: WideChar;
  P : PWideChar;
  Max, Posi, N: Integer;
  Fin, S: String;
 
begin
//Inicializar
Result:='';
S:='';
Fin:='';
Max:=0;
Pos:=0;
 
//Comprobaciones
If not FileExists(FileName) then
  begin
  raise Exception.Create('El archivo indicado no existe');
  exit;
  end;
 
//Calcular tamaño máximo
AssignFile(F2, FileName);
Reset(F2);
Max:=FileSize(F2);
CloseFile(F2);
 
//Si el archivo está vacío, salimos
If Max=0 then exit;
 
//Leer grandes bloques
AssignFile(F, FileName);
Reset(F);
If FileSize(F)>0 then
 for n:=1 to FileSize(F) do
   begin
   Seek(F, n-1);
   Read(F, C);
   P:=C;
   WideCharToStrVar(P, S);
   Fin:=Fin+S;
   Fin:=Copy(Fin, 1, Length(Fin)-1);
   end;
Posi:=FileSize(F)*131072;
CloseFile(F);
 
//Si con los bloques lo hemos leído todo
if Posi=Max then
  begin
  Result:=Copy(Fin, 2, Length(Fin)-1);
  Exit;
  end;
 
//Si quedan datos por leer
AssignFile(F2, FileName);
Reset(F2);
for n:=Posi to Max-1 do
  begin
  Seek(F2, n);
  Read(F2, C2);
  S:=C2;
  Fin:=Fin+S;
  end;

CloseFile(F2);
 
//Damos el resultado final
Result:=Copy(Fin, 2, Length(Fin)-1);
end;


GUARDAR TEXTO ANSI EN ARCHIVO UNICODE

Código Delphi [-]
 
Procedure AnsiToUnicode(Text, FileName: String);
 
type
  TBloq = array[0..8191]of WideChar;
 
var
  F : File of TBloq;
  F2: File of WideChar;
  B : TBloq;
  W : WideChar;
  S : String;
  Max, Posi, N: Integer;
 
begin
//Inicializar
Posi:=0;
Max:=Length(Text);
If Max=0 then Exit; //Salimos si no hay texto
 
//Empezamos a escribir el archivo
AssignFile(F,FileName);
ReWrite(F);

//Si podemos usar los bloques
If Max>8191 then for N:=1 to Max div 8192 do
  begin
  If N=0 then
    begin
    S:='_'+Copy(Text,1,8191);
    StringToWideChar(S,@B,8192);
    B[0]:=WideChar($FEFF);
    Write(F,B);
    Inc(Posi,8192);
    end
   else
    begin
    S:=Copy(Text,(N-1)*8191+1,8192);
    StringToWideChar(S,@B,8192);
    Write(F,B);
    Inc(Posi,8192);
    end;
  end;
 
//Si ya hemos acabado cerramos el archivo
if Posi=Max then
  begin
  CloseFile(F);
  Exit;
  end;
 
//Si no hemos acabo, seguimos
CloseFile(F);
AssignFile(F2,FileName);
Reset(F2);
Seek(F2,FileSize(F2));
If Posi=0 then
  begin
  W:=WideChar($FEFF);
  Write(F2,W);
  end;
For N:=Posi to Max do
  begin
  W:=WideChar(Text[n]);
  Write(F2,W);
  end;
 
//Finalizamos
CloseFile(F2);
end;


¿Alguien podría ayudarme a acabar la segunda función?
¿Alguien podría explicarme la diferencia entre UNICODE, Big Endian y UTF-8, y cómo cargar estos archivos en un TMemo?

Muchísimas gracias.
Responder Con Cita
  #2  
Antiguo 11-09-2006
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Personalmente la segunda función la haría de la siguiente manera:

Código Delphi [-]
procedure AnsiToUnicode(Text, Filename: string);
var
  WStr: WideString;
  F: File;
  Escritos: Integer;
begin
  WStr:= #$FEFF + Text;
  AssignFile(F, Filename);
  {$I-}
    Rewrite(F,Sizeof(WideChar));
  {$I+}
  if IOResult = 0 then
  begin
    BlockWrite(F,PWChar(WStr)^,Length(WStr),Escritos);
    CloseFile(F);
  end;
end;

En cuanto a tu función, ¿cual es exactamente el fallo que te da?
Responder Con Cita
  #3  
Antiguo 13-09-2006
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
Cita:
Empezado por seoane
En cuanto a tu función, ¿cual es exactamente el fallo que te da?
Pues sencillamente aparece un byte (que no debería estar) en la tercera posición. Creo que es debido a eso que dices del ReadUTF del móvil.

Muchas gracias por la función (qué cortita, en comparación con la mía)

Y gracias mamcx por el artículo
Responder Con Cita
  #4  
Antiguo 14-09-2006
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
Gracias otra vez por el artículo, he aprendido mucho.

seoane, la función que hiciste tiene un pequeño fallo: aquí va la corrección:

Código Delphi [-]
procedure AnsiToUnicode(Text, Filename: string);
var
  WStr: WideString;
  F: File;
  Escritos: Integer;
begin
  WStr:=' '+Text;
  WStr[1]:=WideChar($FEFF);
  AssignFile(F, Filename);
  {$I-}
   Rewrite(F,Sizeof(WideChar));
  {$I+}
  if IOResult = 0 then
    begin
    BlockWrite(F,PWChar(WStr)^,Length(WStr),Escritos);
    CloseFile(F);
    end;
end;

También he mejorado la mía (la que extrae el texto del archivo UNICODE). Aquí va:

Código Delphi [-]
Function UnicodeToAnsi(FileName: String): string;
type
  TAr = Array[0..0] of WideChar;
var
  F: File;
  WStr: WideString;
  AStr: String;
  Ar: ^Tar;
begin
Result:='';
If not FileExists(FileName) then exit;
AssignFile(F,FileName);
FileMode:=0;
Reset(F,1);
GetMem(Ar,FileSize(F));
BlockRead(F,Ar^,FileSize(F));
CloseFile(F);
WideCharToStrVar(PWideChar(Ar),AStr);
FreeMem(Ar);
Result:=Copy(AStr,2,Length(AStr)-1);
end;

Bueno, seguro que aún se puede mejorar.

Hasta otra
Responder Con Cita
  #5  
Antiguo 14-09-2006
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Cita:
Empezado por ixMike
seoane, la función que hiciste tiene un pequeño fallo
¿que fallo?

Esto:
Código Delphi [-]
  WStr:=' '+Text;
  WStr[1]:=WideChar($FEFF);

Es lo mismo que esto:
Código Delphi [-]
  WStr:= #$FEFF + Text;

No entiendo porque lo haces de la otra manera. Pero de ahí a decir que lo otro es un fallo

EDITO: Parece que en versiones anteriores de delphi (yo usaba el TurboDelphi), la instrucción que pongo yo se le atraganta. Pero todo tiene solución:
Código Delphi [-]
  WStr:= #$FEFF + WideString(Text);

Última edición por seoane fecha: 14-09-2006 a las 14:31:47.
Responder Con Cita
  #6  
Antiguo 15-08-2007
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 23
ContraVeneno Va por buen camino
Gracias ixMike
este hilo me ha servido de maravillas

Muchas gracias
__________________

Responder Con Cita
  #7  
Antiguo 11-09-2006
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Un buen articulo:

http://www.joelonsoftware.com/articles/Unicode.html
__________________
El malabarista.
Responder Con Cita
  #8  
Antiguo 11-09-2006
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Voy a contar una anécdota por si a alguien le puede ser de utilidad. Hace unos días un amigo intentaba enviar una cadena de texto a un teléfono móvil a través del bluetooth, este texto lo leía después en el móvil con un applet hecho en java. Para ello, inocentemente, usaba la instrucción ReadUTF de java. Pero algo fallaba, resulta que java tiene su propio formato para las cadenas UTF, hay que añadir al principio de cada cadena 2 bytes (el byte alto primero) que representan el tamaño en bytes de la cadena.

Última edición por seoane fecha: 11-09-2006 a las 21:52:24.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Unicode PTW Varios 0 22-01-2006 13:30:31
Unicode arantzal Varios 2 19-09-2005 18:44:07
ANSI-ASCII y caracteres Ñ, ¿, etc. nax C++ Builder 0 27-08-2005 02:44:23
Unicode Sworied MySQL 1 12-08-2004 08:27:38
Unicode pacogp Varios 2 17-02-2004 15:02:35


La franja horaria es GMT +2. Ahora son las 17:20:53.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi