PDA

Ver la Versión Completa : Lazarus: TStringList.LoadFromFile error cuando la ruta tiene eñes/acentos


euMesmo
25-02-2015, 18:52:54
Hola a todos/as.

He estado buscando por varios foros de delphi/lazarus pero no encuentro nada que funcione.

El problema es el siguiente, un programa simple en Windows:

Cargo un archivo de texto, que se encuentra en la misma ruta que el ejecutable, a un stringlist mediante loadfromfile, pues bien, si el ejecutable está en una carpeta (o ruta) cuyo nombre no tiene eñes ni acentos funciona sin más problema. En cuanto cambio el nombre de carpeta por otro que tenga acentos deja de funcionar (si cambio el nombre de carpeta por otro sin acentos funciona).

El código lo podemos resumir en algo como:

ruta:=AnsiToUtf8(ExtractFilePath(Application.ExeName));
fichero:=TStringList.Create;
fichero.LoadFromFile(ruta+'app.cfg');

Ya he probado, creo que todos, los utf8encode, decode utf8toansi.

¿ Alguna idea?.

Gracias por vuestro tiempo.

ecfisa
25-02-2015, 19:18:47
Hola euMesmo, bienvenido a Club Delphi :)

Cuando incluyas código en tus mensajes usa las etiquetas de este modo:
http://sia1.subirimagenes.net/img/2014/09/20/140920064308529777.jpg

Y como es costumbre con los iniciados te invitamos a leer nuestra guía de estilo (http://www.clubdelphi.com/foros/guiaestilo.php).

En cuanto a tu consulta, intenta de este modo:

var
fichero: TStringList;
begin
fichero:= TStringList.Create;
try
fichero.LoadFromFile(UTF8ToAnsi(ExtractFilePath(Application.ExeName)+'app.cfg'));
Memo1.Lines.Assign(fichero); // Acción de ejemplo
finally
fichero.Free;
end;
end;


Saludos :)

euMesmo
25-02-2015, 20:06:10
Gracias ecfisa.

Lo primero mis disculpas por lo del código y gracias por tu respuesta.

Ya había intentando esto sin conseguir el éxito. Intentaré explicar mejor el problema.

En una aplicación, en el evento "FormCreate" creo el stringlist y lo cargo mediante loadfromfile, si el ejecutable y el cfg (es un fichero de texto utf-8) están en la carpeta "Aplicacion" funciona (carga el archivo de configuración), si pongo cualquier nombre a esa carpeta que no tenga eñes o acentos sigue funcionando, pero si lo cambio por "Aplicación" aparece el error que de que no puede cargar el archivo (Unable to open file) aunque la ruta que aparece en el mensaje es la correcta, acento incluido.

De momento todo me hace pensar que es un bug de lazarus en windows ya que en linux el mismo código no genera el error.

¿ Alguna idea?. Muchas gracias.

ecfisa
25-02-2015, 20:23:49
Hola euMesmo.

Es verdaderamente extraño... En mi código original de prueba funciona correctamente:

procedure TForm1.FormCreate(Sender: TObject);
var
fichero: TStringList;
begin
fichero:= TStringList.Create;
try
fichero.LoadFromFile(UTF8ToAnsi('C:\tmp\ÁéíóúÑñ\ÁéíóúÑñ.txt'));
Memo1.Lines.Assign(fichero);
finally
fichero.Free;
end;
end;

Muestra:
http://s13.postimg.org/wl3auhr3r/eu_Mesmo.jpg

Prueba realizada en Windows 7 y Lazarus Ver: 1.2.6 - Revisión SVN: 46529

Saludos :)

euMesmo
25-02-2015, 20:43:56
Si efectivamente funciona, pero si ejecutable y archivo de texto lo mueves a una carpeta cuyo nombre no tenga acentos sigue funcionando, pero al cambiar el nombre de esa carpeta con un acento deja de funcionar, no por el nombre del archivo (eñé.cfg en mi prueba) si no por el de la carpeta que lo contiene.

Pongo el código con el que he probado (uso W7 y Lazarus 1.2.6):

procedure TForm1.FormCreate(Sender: TObject);
var
fichero: TStringList;
begin
fichero:= TStringList.Create;
try
fichero.LoadFromFile(UTF8ToAnsi(ExtractFilePath(Application.ExeName)+'eñé.cfg'));
Memo1.Lines.Assign(fichero);
finally
fichero.Free;
end;
end;

Como dices es muy extraño. De momento estoy diciendo a los usuarios de windows que coloquen la carpeta con el programa en "c:" para evitar problemas pero, al ser una aplicación que no necesita ningún tipo de instalación, la verdad queda mal.

euMesmo
26-02-2015, 12:51:46
Bien, creo que encontré el problema.
El código funciona si quito "UTF8ToAnsi"

Gracias a todos.

ecfisa
27-02-2015, 04:31:20
Hola euMesmo.
Bien, creo que encontré el problema.
El código funciona si quito "UTF8ToAnsi"

Gracias a todos.
¿ Es decir que el código del mensaje #5 te funciona quitando la función UTF8ToAnsi ?, entonces quedo mas perplejo que antes...

De ese modo obtengo este mensaje de error:

http://s27.postimg.org/ccjbme3jn/eu_Mesmo.jpg

Sin embargo, de este modo sí funciona correctamente:

const
FNAME = 'Márgen ñato.txt';

procedure TForm1.Button1Click(Sender: TObject);
var
fichero: TStringList;
begin
fichero:= TStringList.Create;
try
fichero.LoadFromFile( ExtractFilePath(Application.ExeName) + UTF8ToAnsi(FNAME) );
Memo1.Lines.Assign( fichero ); // Acción de ejemplo
finally
fichero.Free;
end;
end;

Lo que me induce a pensar que la función ExtractFilePath realiza la conversión necesaria.

Nombres que usé para la prueba:

Ruta: c:\tmp\Cápita moño
Archivo: Márgen ñato.txt


Saludos :)

euMesmo
28-02-2015, 01:39:41
Veamos, el código #5 me funciona para el fichero "app.cfg" (sin acentos ni eñes en su nombre). Como apuntas, ExtractFilePath hace su trabajo, de hecho, en el mensaje que aparece, se ven claramente los acentos y no "?" o "Ã" como tu caso en el nombre del fichero, pero la cosa no acaba ahí y ya no sé que pensar.

Un programa exclusivamente con ese código no devuelve ningún error independientemente de si la ruta tiene o no acentos. Bien.

Ahora, en mi programa, el módulo principal, en el evento "formcreate" empieza exactamente lo mismo (incluido nombres y declaraciones de variables). Pues bien, en mi programa aparece el error de open file en "app.cfg" cuando cambio el nombre de la carpeta (Aplicacion) por el mismo con acento (Aplicación), evidentemente cierro el programa antes de cambiar el nombre y lo vuelvo a ejecutar. He comprobado que la aplicación no abriese "en otro lugar" este archivo y nada.

Como te imaginarás he dudado hasta de mi sombra, llevo casi 20 años programando en pascal (desde el Delphi 1) y creía haber visto "de todo".

En fin si a alguien se le ocurre algo que no dude en comentarlo.

Gracias por tu tiempo ecfisa

nlsgarcia
01-03-2015, 21:45:58
euMesmo,


...Cargo un archivo de texto, que se encuentra en la misma ruta que el ejecutable, a un stringlist mediante loadfromfile...si el ejecutable está en una carpeta (o ruta) cuyo nombre no tiene eñes ni acentos funciona sin más problema. En cuanto cambio el nombre de carpeta por otro que tenga acentos deja de funcionar...

:rolleyes:

Revisa este código:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

{ TForm1 }

TForm1 = class(TForm)
Memo1: TMemo;
ToggleBox1: TToggleBox;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure ToggleBox1Change(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;

var
Form1: TForm1;
FileStrList : TStringList;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.ToggleBox1Change(Sender: TObject);
var
openDialog : TOpenDialog;
AuxStr : String;
MsgUser : String;

begin

openDialog := TOpenDialog.Create(self);
openDialog.InitialDir := GetCurrentDir;
openDialog.Options := [ofFileMustExist];
openDialog.Filter := 'Text Files|*.txt';

if openDialog.Execute then
begin
FileStrList := TStringList.Create;
AuxStr := openDialog.FileName;
FileStrList.LoadFromFile(UTF8ToAnsi(AuxStr));
Memo1.Lines.Text := AnsiToUtf8(FileStrList.Text);
end
else
begin
MsgUser := 'No se Selecciono Ningún Archivo de Texto para Visualizar';
MessageDlg(MsgUser,mtinformation,[mbok],0);
end;

openDialog.Free;

end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
FileStrList.Free;
CloseAction := cafree;
end;

end.

El código anterior en Lazarus Versión #:1.2.6 FPC Version 2.6.4 bajo Windows 7 Professional x32, permite visualizar archivos de texto que contengan caracteres acentuados o con ñ tanto en su contenido como en el nombre del directorio en donde residen, como se muestra en las siguientes imágenes:

http://i42.photobucket.com/albums/e305/nlsgarcia/FileTestLazarus-1_zpsehtdd7lt.jpg

http://i42.photobucket.com/albums/e305/nlsgarcia/FileTestLazarus-2_zpsobmuzfpm.jpg

Espero sea útil :)

Nelson.

euMesmo
04-03-2015, 00:02:57
Hola nlsgarcia, disculpa por no contestar antes.

Veamos, el problema no es el contenido del archivo a abrir si tiene o no palabras con acentos. El problema está en la ruta en la que se ejecuta el programa, si en esa ruta ninguna de las carpetas tiene acentos, eñes, espacios en blanco, funciona, abre el archivo y lee correctamente el archivo, si cambio el nombre de cualquiera de las carpetas de la ruta y no pongo acentos, sigue funcionando, en cuanto cambio el nombre de una carpeta por uno con acento aparece el error de "open file".

Dicho de otra forma, si se copia la carpeta que contiene el programa y todos los archivos necesarios en el escritorio de un usuario que se llame "José" ya aparece el error dado que "José" está en la ruta de acceso al archivo.

Gracias por tu atención.

nlsgarcia
04-03-2015, 00:15:19
euMesmo,


...el problema no es el contenido del archivo a abrir si tiene o no palabras con acentos...El problema está en la ruta en la que se ejecuta el programa...en cuanto cambio el nombre de una carpeta por uno con acento aparece el error de "open file"...

:rolleyes:

Revisa el código y las imágenes del Msg #9, este permite visualizar archivos de texto que contengan caracteres acentuados o con ñ tanto en su contenido como en el nombre del archivo y directorio/ruta en donde residen en cualquier combinación.

Espero sea útil :)

Nelson.

euMesmo
06-03-2015, 14:18:30
Gracias Nelson.

Pero el código que se plantea carga el archivo mediante un "OpenDialog", yo lo hago directamente llamando al archivo ya que sé su ubicación mediante un "loadfromfile(ruta)".

nlsgarcia
07-03-2015, 00:19:38
euMesmo,


...el código que se plantea carga el archivo mediante un "OpenDialog", yo lo hago directamente llamando al archivo ya que sé su ubicación mediante un "loadfromfile(ruta)"...

:rolleyes:

Revisa este código:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

{ TForm1 }

TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;

var
Form1: TForm1;
FileStrList : TStringList;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Caption := EmptyStr;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
S : String;
FileName : String;

begin

FileName := 'FileTest-áéíóúäëïöüñ ÁÉÍÓÚÄËÏÖÜÑ.txt';

FileStrList := TStringList.Create;

S := ExtractFilePath(AnsiToUtf8(Application.Exename)) + FileName;

Label1.Caption := S;

FileStrList.LoadFromFile(Utf8ToAnsi(S));

Memo1.Lines.Text := AnsiToUtf8(FileStrList.Text);

end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
FileStrList.Free;
CloseAction := cafree;
end;

end.

El código anterior en Lazarus Versión #:1.2.6 FPC Version 2.6.4 bajo Windows 7 Professional x32 es una variación del código del Msg #9, el cual permite visualizar archivos de texto que contengan caracteres acentuados o con ñ tanto en su ruta, nombre o contenido en cualquier combinación, como se muestra en la siguiente imagen:

http://i42.photobucket.com/albums/e305/nlsgarcia/FileTestLazarus-3_zpsjnnfiurs.jpg

Espero sea útil :)

Nelson.