8 de junio de 2017

Opciones alternativa a la función FILE()

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

1 comentario :

  1. Buenos días.

    Espartaco: 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

    **

    ResponderBorrar

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.