Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Abrir archivo dentro de UnicodeString

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Abrir archivo dentro de UnicodeString Responder citando

Para abrir algunos archivos directamente dentro de un UnicodeString, probé el siguiente código:

Código:

   if(OpenDialog1->Execute()) {
      std::wifstream is (OpenDialog1->FileName.c_str(), std::ifstream::binary);
      //is.imbue(std::locale(is.getloc(), new std::codecvt_utf16<wchar_t>));
      if (is) {
         is.seekg (0, is.end);
         int length = is.tellg();
         is.seekg (0, is.beg);
         String buffer;
         buffer.SetLength(length);
         is.read (buffer.c_str(),length);
         is.close();
         RichEdit1->Text = buffer;
      }
   }


Noté que si el archivo contiene caracteres Unicode, el resultado no es el que esperaba. En este caso, descomento la línea:

Código:

         is.imbue(std::locale(is.getloc(), new std::codecvt_utf16<wchar_t>));


y se abre el archivo. Pero si intenta abrir un archivo que no sea Unicode con esta instrucción anterior, la lectura no será correcta.

Otra forma de abrir el archivo es usando TFileStream:

Código:

   if(OpenDialog1->Execute()) {
      std::auto_ptr<TFileStream> fs(new TFileStream(OpenDialog1->FileName, fmOpenRead));
      String S;
      S.SetLength(fs->Size + 1);
      fs->Read(S.c_str(), fs->Size);
      S[fs->Size] = '\0';
      RichEdit1->Text = S;
   }


En este caso no importó, en mis pruebas, si el archivo tenía o no caracteres Unicode. La lectura fue perfecta.

¿Sabes por que pasa esto? ¿Por qué en una situación a la lectura no le importa el tipo de caracteres y en la otra da error?

Gracias.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Revisándolo mejor, creo que la información de arriba no es correcta.

Di un ShowMessage antes de que la String fuera a Text de RichEdit y noté que todos los caracteres eran ilegibles en ShowMessage. Es decir, aparentemente es RichEdit quien está arreglando las cadenas para mostrar, que están ilegibles en UnicodeString.

Es decir, en el caso de TFileStream, las cadenas no se pueden leer, pero RichEdit las hace legibles.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

¡He logrado! El siguiente código abre un archivo directamente dentro de un AnsiString o de un UnicodeString con la ventaja de que podemos definir la Codificación (Encode) de una manera más fácil:
Código:

#include <System.IOUtils.hpp>

void __fastcall TForm1::Button31Click(TObject *Sender)
{
   if(OpenDialog1->Execute()) {
     String LoadString;
     LoadString = TFile::ReadAllText(OpenDialog1->FileName, TEncoding::ANSI);
     //LoadString = TFile::ReadAllText(OpenDialog1->FileName, TEncoding::Unicode);
     ShowMessage(LoadString);
   }
}
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Cosas que no puedo entender:

Cita:

Modo de apertura Unicode:

Si un archivo tiene uno o más caracteres Unicode y es un archivo de texto, TRichEdit mostrará el contenido del archivo normalmente;
Si un archivo no contiene caracteres Unicode y es un archivo de texto, TRichEdit mostrará todo el contenido del archivo como si estuviera en otro idioma, similar al chino;
Si el archivo tiene la extensión RTF, TRichEdit mostrará el archivo normalmente como si lo cargara directamente con LoadFromFile


Cita:

Modo de apertura Ansi:

Si un archivo, en formato de texto, tiene uno o más caracteres Unicode, en TRichEdit solo se mostrará una pequeña parte del comienzo del archivo.
Si el archivo no tiene caracteres Unicode y está en formato de texto, el archivo se mostrará normalmente en TRichEdit
Si es un archivo RTF, el archivo se mostrará como si TRichEdit fuera un TMemo


No puedo entender estos diversos comportamientos de TRichEdit. Principalmente porque abre normalmente un archivo RTF en modo Unicode como si usara el método RichEdit1->Lines->LoadFromFile(...):

Código:

String str = TFile::ReadAllText(fileName, TEncoding::Unicode);
RichEdit ->Text = str;

// es igual a

RichEdit1->Lines->LoadFromFile(fileName);

Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Lo que ocurre se debe al diferente tamaño de cada carácter y su interpretación cuando se trata de una cadena de caracteres.
Unicode utiliza WCHAR que son 2 BYTES o dos CHAR. La mayoría de los caracteres de este tipo vienen representados como un CHAR seguido de 0x00. esto en modo cadenas AnsiChar representa un carácter seguido de fin de cadena (carácter nulo).

Cita:
Modo de apertura Unicode:
Si un archivo tiene uno o más caracteres Unicode y es un archivo de texto, TRichEdit mostrará el contenido del archivo normalmente;

En este caso y si estás en versiones de Builder que usan String en modo Unicode, El Componente se comporta como esperas.

Cita:
Modo de apertura Unicode:
Si un archivo no contiene caracteres Unicode y es un archivo de texto, TRichEdit mostrará todo el contenido del archivo como si estuviera en otro idioma, similar al chino;

En este caso el texo es ansi (tamaño CHAR) y lo trata como unicode malinterpretando todos los caracteres.


Cita:

Modo de apertura Ansi:

Si un archivo, en formato de texto, tiene uno o más caracteres Unicode, en TRichEdit solo se mostrará una pequeña parte del comienzo del archivo.
Si el archivo no tiene caracteres Unicode y está en formato de texto, el archivo se mostrará normalmente en TRichEdit
Si es un archivo RTF, el archivo se mostrará como si TRichEdit fuera un TMemo


Cuando abres como Ansi, el tamaño es CHAR (1 Byte). Si esto está en una cadena String de tipo Unicode (WideString), se interpretará el fin de la misma en el primer Byte nulo que aparezca. Además, el archivo estará truncado a la mitad de su tamaño según como se halla realizado su lectura y el cálculo del tamaño. sizeof(CHAR) = 1/2 sizeof( WCHAR)

Así, todo depende de cómo se haga la lectura, en que tipo de bufer se almacene (CHAR o WCHAR) y a que tipo de String se le asigne (AnsiString o WideString) Además, el tipo String será por defecto Ansi o Wide dependiendo de la versión de Builder que uses


Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Gracias por la explicación, escafandra. Estaba estancado en el tiempo con C++Builder 6 y, a pesar de haber instalado BCB CE hace unos años, prefería no salir de mi zona de confort. Hace poco me armé de coraje para soltar BCB6. Estoy encontrando algunas dificultades con estas diferencias entre AnsiString y String/UnicodeString, pero sigo adelante.

Muchas gracias por su ayuda. ¡Ha sido fundamental para mí!
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.