Como se ha visto últimamente en los foros de noticias de microsoft, la función FILE() tiene algunos "errores" que pueden afectar el comportamiento de nuestros programas, aquí encontrarás algunos métodos adicionales.
Normalmente, la función File() la utilizamos para revisar si existe un archivo en cierta ruta, pero el comportamiento de la misma función tiene sus detalles que están documentados en la ayuda:
"Si el archivo no puede encontrarse en el directorio predeterminado, se buscará en la ruta de acceso de Visual FoxPro establecida con SET PATH. "
Que significa esto? Que aunque se le indique la ruta completa de un archivo a buscar, la función File() buscará también ese mismo archivo dentro de la ruta establecida por PATH, dándole un tiempo adicional en hacer su labor. Por ejemplo:
Caso 1.
Intentamos buscar el archivo "HolaMundo.txt" en una ruta especifica:
? FILE("c:\miApp\miDirectorio\HolaMundo.txt")
Si el archivo no existe en ese directorio devolverá .F., pero..., si algún archivo llamado "HolaMundo.txt" se encuentra en algunas de las rutas establecidas por el comando SET PATH, o en el directorio de trabajo de la aplicación, entonces devolverá .T., cuestión que puede afectar en gran medida el comportamiento de nuestro sistema.
Caso 2
Buscamos el archivo "HolaMundo.txt" sin poner ruta completa para hacer validaciones de X tipo:
IF File("HolaMundo.txt") Messagebox("... blah blah blah....") ENDIF
Si por alguna razón, nuestro archivo se encuentra en cualquier otra localidad establecida por SET PATH, la función también devolverá .T., una vez más, caso dificil de controlar, si suponemos que podemos tener cientos de rutas establecidas.
Como es de imaginarse, los inconvenientes que puede ocasionar este comportamient normal de la función FILE() puede ser algo engorroso.
Muy bien, que hay por hacer? Hasta el momento, gracias a la colaboración que ha surgido en los mensajes de los newsgroup de microsoft, tenemos lo siguiente:
Opción 1
Quitar las rutas establecidas por SetPath antes de utilizar la función File():
Function SureFile LParameters tcFileName Local lcOldPath Local llRetValue lcOldPath = SET("PATH") SET PATH TO llRetValue = File(m.tcFileName) SET PATH TO &lcOldPath Return llRetValue EndFunction
Opcion 2
Utilizar la función ADIR(), la cual, no presenta el inconveniente de la tan mencionada función FILE().
Function SureFile LParameters tcFileName RETURN (ADIR(laDummy, m.tcFileName) > 0) EndFunction
Opcion 3
Utilizando la función SYS(2000):
Function SureFile LParameters tcFileName RETURN NOT EMPTY(SYS(2000,m.tcFileName)) ENdFunction
Opcion 4
Utilizar una API para llevar a cabo la labor:
*** En tu programa de inicio, solo una vez ***** declare Integer GetFileAttributes in win32api string @ **************************************** Function SureFile LParameters tcFileName return (GetFileAttributes(@m.tcFileName) <> -1) EndFunction
Esta última opción es la que he visto funciona un poco más rapido que las anteriores, ya que no hay que re-establecer ningún setting, ni crear ningún arreglo, ni buscar nada que no sea exactamente lo que deseamos.
Así pues, pongo a consideración las opciones disponibles, hagamos nuestras y pruebas y si tienen algún comentario al respecto, comentemoslo ya sea aquí, o en los newsgroups de microsoft (son públicos y gratuitos).
Espero que la información les sea de utilidad.
Espartaco Palma Martínez
Buenos días.
ResponderBorrarEspartaco: He hecho varias pruebas y he encontrado que el impasse que mencionas en tu artículo se produce sólo si no se da la ruta de ubicación del archivo en el parámetro de la función FILE() --pero...--.
Hace aprox un año luego de leer el artículo, decidí replantear la función FILE() en mis aplicaciones, decidiéndome por GetFileAttributes de la API.
Por estos días decidí afrontar este impasse de VFP. Pero no encontré el problema.
Entonces decidí escribir un test y aportarlo, para que alguien haga más pruebas.
Como en este artículo se menciona que la misma ayuda "documenta este comportamiento", la revisé y encontré que se aclara que "se hace la búsqueda en el SET PATH" sólo si no se incluye la ruta en el parámetro de FILE(), que fue lo que yo había descubierto.
Se me hace que te estás basando en la ayuda de VFP8 traducida al español (lo mencionado en el artículo es textual), en la que no se encuentra la aclaración que estoy exponiendo.
La ayuda que uso es dv_foxhelp_vfp9sp2_v1.08, liberada recientemente (aunque he usado la dv_foxhelp_vfp9sp2_v1.07 desde que recuerdo).
De hecho, en lo personal no considero que sea una inconsistencia que la función FILE() de VFP devuelva .t. cuando no se dé la ruta de ubicación de un archivo y el archivo no esté en el dir predeterminado, sino en algún otro dentro del SET PATH de VFP, pues precisamente ese es el objetivo del comando SET PATH.
Como menciono, las pruebas las hago con un .PRG. Sería bueno que alguien expusiera algo con respecto a un .APP o un .EXE.
Seguimos en contacto.
HERNAN CANO M
Analista de Sistemas
** ProbandoFILE.prg
clear
close databases all
clear all
close all
local M.lDepurar
M.lDepurar = .f.
if !directory('\ProbandoFILE',1)
M.lDepurar = .t.
md \ProbandoFILE
endif
if !directory('\ProbandoFILE\DIR1',1)
md \ProbandoFILE\DIR1
endif
if !directory('\ProbandoFILE\DIR2',1)
md \ProbandoFILE\DIR2
endif
if !directory('\ProbandoFILE\DIR3',1)
md \ProbandoFILE\DIR3
endif
local OldDir
OldDir = curdir()
cd \ProbandoFILE
StrToFile('dir1\file1.txt','dir1\file1.txt',1)
StrToFile('dir2\file2.txt','dir2\file2.txt',1)
StrToFile('dir3\file3.txt','dir3\file3.txt',1)
set path to
?'---'
?curdir()
?'---'
?'set path to',set('path')
?'---'
? file('dir2\file2.txt') && --> .t.
? file('file1.txt') && --> .f.
? file('file2.txt') && --> .f.
? file('file3.txt') && --> .f.
?'---'
set path to \ProbandoFILE,\ProbandoFILE\dir1,\ProbandoFILE\dir2,\ProbandoFILE\dir3
**?'---'
?'set path to',set('path')
?'---'
? file('dir2\file2.txt') && --> .t.
? file('file1.txt') && --> .t.
? file('file2.txt') && --> .t.
? file('file3.txt') && --> .t.
?'---'
? file('dir1\file1.txt') && --> .t.
? file('dir1\file2.txt') && --> .f.
? file('dir1\file3.txt') && --> .f.
? file('dir1\file4.txt') && --> .f.
?'---'
? file('\ProbandoFILE\file1.txt') && --> .f.
? file('\ProbandoFILE\file2.txt') && --> .f.
? file('\ProbandoFILE\file3.txt') && --> .f.
? file('\ProbandoFILE\file4.txt') && --> .f.
? file('file4.txt') && --> .f.
?'---'
set path to
cd &OldDir
if M.lDepurar
erase \ProbandoFILE\DIR1\file1.txt
erase \ProbandoFILE\DIR2\file2.txt
erase \ProbandoFILE\DIR3\file3.txt
rd \ProbandoFILE\DIR1
rd \ProbandoFILE\DIR2
rd \ProbandoFILE\DIR3
rd \ProbandoFILE
endif
**