 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
Felip Master

Registrado: 09 Jun 2004Mensajes: 200
|
Publicado: Lun 29 Ago, 2022 8:55 pm Asunto: Abrir archivo dentro de UnicodeString |
|
|
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 |
|
 |
Felip Master

Registrado: 09 Jun 2004Mensajes: 200
|
Publicado: Lun 29 Ago, 2022 10:45 pm Asunto: |
|
|
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 |
|
 |
Felip Master

Registrado: 09 Jun 2004Mensajes: 200
|
Publicado: Mar 30 Ago, 2022 3:40 am Asunto: |
|
|
¡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 |
|
 |
Felip Master

Registrado: 09 Jun 2004Mensajes: 200
|
Publicado: Mar 30 Ago, 2022 12:40 pm Asunto: |
|
|
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 |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Mie 31 Ago, 2022 10:53 pm Asunto: |
|
|
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 |
|
 |
Felip Master

Registrado: 09 Jun 2004Mensajes: 200
|
Publicado: Jue 01 Sep, 2022 2:50 am Asunto: |
|
|
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 |
|
 |
|
|
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
|
© 2002–2026 Club Builder · Funciona con phpBB.
|