• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 8632
  • Last Modified:

Create a text file using Visual Foxpro

I'm trying to use the code below to check for the existence of a .ini file, if it does not exist, create it. If it exists but is empty prompt the user for a path, then write the path to the file. If it does exist and contains a path, is the path valid, if not prompt the user for the path, then write it to the file.

The code appears to execute without error in the Debugger, but it doesn't create a file. If I compile the application and run it, the code doesn't even execute, even though the triggering conditions exist..Am I missing something about the Low Level functions?
IF FILE('autodocspath.ini')  && Does the ini file exist in the current directory? 
	Local gnFileHandle,nSize,cString
	gnFileHandle = FOPEN('autodocspath.ini')
	* Seek to end of file to determine number of bytes in the file.
	nSize =  FSEEK(gnFileHandle, 0, 2)     && Count the bytes
	IF nSize <= 0		&&Is the ini file empty?
		=FCLOSE(gnFileHandle)
		DO FORM locatedata
	ELSE			&&It's not empty, so read the contents
		 = FSEEK(gnFileHandle, 0, 0)      && Move pointer to BOF
		 m.pathname = FREAD(gnFileHandle, nSize)
		 m.pathname=ALLTRIM(m.pathname)
		=FCLOSE(gnFileHandle)
	ENDIF
	IF FILE((m.pathname)+"defaults.dbf") && DOes the path contained in the ini point to the data?
	ELSE
		=FCLOSE(gnFileHandle)
		DO FORM locatedata
	ENDIF
ELSE					&&ini doesn't exist in the current directory
	DO FORM locatedata
ENDIF

&& this is the code that executes when LocateData is run:
LOCAL gnFileHandle
m.length=LENC(ALLTRIM(m.pathname))
IF (RIGHT(ALLTRIM(m.pathname),1)="\")
ELSE
	m.pathname=ALLTRIM(m.pathname)+"\"
ENDIF	
IF FIle(ALLTRIM(m.pathname)+'defaults.dbf')
	gnFileHandle = FOPEN('autodocspath.ini',12)
    =FWRITE(gnFileHandle , (m.pathname))
	=FCLOSE(gnFileHandle)
	USE ALLTRIM(m.pathname)+"defaults.dbf" ALIAS defaults
	REPLACE defaults.path WITH ALLTRIM(m.pathname)
	HIDE WINDOW locatedata
	RELEASE WINDOWS
ELSE
	WAIT WINDOW "Defaults.dbf was not found in the specified location."
	m.pathname=""
	thisform.refresh
ENDIF

Open in new window

0
mikejcurtis
Asked:
mikejcurtis
  • 4
  • 4
  • 2
  • +2
2 Solutions
 
wcsoctuCommented:
You could make it simpler using STRTOFILE and FILETOSTR.
But it looks like gnFileHandle is not being passed to the form and is local to each section, thus you don't have a valid file handle when you write the file.
0
 
pcelbaCommented:
gnFileHandle is not the problematic part.

The most dangerous part is the FWRITE() function which does not reduce the file size, so your code would probably cause unexpected behavior sooner or later... So, I agree you should use STRTOFILE() and FILETOSTR() as the first improvement but it does not help to solve all problems.

To check if your code executes you may place WAIT WINDOW "I am executed..." commands onto several places as the easiest trap. The form locatedata does not appear because you don't have READ EVENTS command in your main program most probably. (You should not forget to CLEAR EVENTS when the form is released.)

BUT do you need this form? You can use GETFILE() or LOCATEFILE() function which does the work for you.

If you need to ask just for folder name then you may use GETDIR().

Also to add missing backslash to path you may call ADDBS() function.

The "file is not created" problem is possible because FCREATE() is not used in your code but the code is most probably posted as incomplete.

BTW, how is the m.pathname variable declared?
0
 
mikejcurtisAuthor Commented:
I gotta tell you straight up, I''ve had no formal training in Foxpro. Everything I know how to do I've figured out pretty much on my own, therefore I'm sure I am unconventional if not downright lethal.

The code I included is a sub routine, the main calling program does include the READ EVENTS and CLEAR EVENTS.

I did notice after I hit Submit, that I didn't have the FCREATE() in there.

For the FWRITE() my intent was that the file not be written to unless it contains an invalid path, but I see what you're saying because if I need to write to the file, I need to make it empty first, or the file may grow.

As for the form, I'll look at the GETFILE() LOCATEFILE() options. My main calling program checks for the existence of a table in the current directory when the application runs. If it's not found, the first bit of code runs, and if needed the Locatedata form for the user to type in the path.  

m.pathname is a Public Character variable.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
mikegagnonCommented:
pcelba

>>>BUT do you need this form? You can use GETFILE() or LOCATEFILE() function which does the work for you.

Most likely you meant LOCFILE()
0
 
pcelbaCommented:
Of course, LOCFILE() ... It seems I am not able to copy/paste the code from Command window. :-)

And one more hint for mikejcurtis:

        USE ALLTRIM(m.pathname)+"defaults.dbf" ALIAS defaults
        REPLACE defaults.path WITH ALLTRIM(m.pathname)

should be followed by table closing:
        USE
0
 
jrbbldrCommented:
mikejcurtis - "I gotta tell you straight up, I''ve had no formal training in Foxpro"

First, welcome to the community of developers.

If you have already become familiar with the use of the VFP TRACE Window, then I apologize for what follows.  Just ignore it.

But if you are not familiar with it, you should get familiar to checking out your code with the use of the VFP TRACE Window.    It will allow you to 'walk through' your code line by line, if you want to, and check things out as you go.

That way you can 'see' what is happening and what the results are of various operations.

And I'll modify pcelba's advice immediately above slightly
      USE ALLTRIM(m.pathname)+"defaults.dbf" ALIAS defaults
              should probably by something like:
     USE ADDBS(ALLTRIM(m.pathname)) + "defaults.dbf" ALIAS defaults

Good Luck
0
 
mikejcurtisAuthor Commented:
Well, I'd like to pull my hair out, but despite my avatar, that's been pretty much gone for quite a wile!

Thanks jrbbldr, I've been using the Trace window, but that isn't helping with my current problem. I guess I'm just approaching this completely wrong or something.

Let me state my dilemma succinctly and see if anyone knows a way to deal with it.

I am distributing an application to several manufacturing plants. What I can't know is where they are going to install the application, and worse, where they are going to put the application's data. Some of the IT managers want to keep the data with the executable, some want to store applications (things that don't change) one place, and the data another. My application has to be able to deal with both possibilities with minimal input from the local IT staff.

I thought a way to deal with this is to have a routine use Low-Level File Functions check for the data in the default path, if it's not found, then prompt for the path and store that path in a 'defaults' table, and from then on refer to that defaults table. Well I couldn't get that to work because I kept getting errors about the defaults table not being found.

So I thought I could use a text file like an ini file, first check for the data, if it's not found, check for the ini file, if it's found see if the path it contains is correct, if not, empty it and display a form for the path, then write that path to both the ini and the default table. From then on, unless the data is moved again, the program would be able to locate the data.

Well using the attached code in the development environment works just right. But if I compile the application and run it as an executable, it works except when the data is not in the same folder as the application. What doesn't happen is the last DO FORM LOCATEDATA. Instead of popping up the LOCATEDATA window, I get an error saying defaults not found.

I inserted WAIT's through out to try to see where it's having the problem, but as soon as all the elements for the LOCATEDATA form are loaded and inititated and just before the form should be displayed, 'Defaults.dbf is not found' appears. I have searched throughout the application for any USE commands or other references to the defaults table, but I can find none.

How would an expert handle this ambiguity in where the data is stored versus where  the executable it stored?
IF FILE('autodocspath.ini')  && Does the ini file exist in the current directory? 
	PUBLIC gnFileHandle,nSize,cString
	gnFileHandle = FOPEN('autodocspath.ini')
	* Seek to end of file to determine number of bytes in the file.
	nSize =  FSEEK(gnFileHandle, 0, 2)     && Count the bits
	IF nSize <= 0		&&Is the ini file empty?
		=FCLOSE(gnFileHandle)
		DO FORM locatedata
	ELSE			&&It's not empty, so read the contents
		 = FSEEK(gnFileHandle, 0, 0)      && Move pointer to BOF
		 m.pathname = FREAD(gnFileHandle, nSize)
		 m.pathname=ALLTRIM(m.pathname)
		=FCLOSE(gnFileHandle)
	ENDIF
	IF FILE((m.pathname)+"defaults.dbf") && DOes the path contained in the ini point to the data?
	ELSE
		=FCLOSE(gnFileHandle)
		DO FORM locatedata
	ENDIF
ELSE					&&ini doesn't exist in the current directory
	DO FORM locatedata
ENDIF

Open in new window

0
 
mikejcurtisAuthor Commented:
Oh also, I have a READ EVENTS and CLEAR EVENTS in the program that calls the code shown above.
0
 
jrbbldrCommented:
"What I can't know is where they are going to install the application,  and worse, where they are going to put the application's data. Some of  the IT managers want to keep the data with the executable, some want to  store applications (things that don't change) one place, and the data  another"

This is not too unusual.

Often the application utilizes a configuration file (pretty much like you are suggesting), Windows registry entries or a configuration table to store these parameters and then utilize them when needing to acquire data.

Which approach you take is up to you.

One method would be to have a Configuration utility run to capture the user's choices and then store them as:
  *  Windows registry entries
  *  VFP Data table field values (a separate configuration data table)
  *  Some Text file (such as an INI file)
  * or some other means

The main body of the application can not run until these parameters have been defined, but once done, it would retrieve the path info and utilize it as needed.

One of the easiest approaches (from the VFP perspective) might be to use a VFP data table for this info.

But if you wanted to use the INI Text file approach (would not be my 1st choice) - I would approach it something like what follows:

DO FORM locatedata  && Return from here with Intended Path Info

SET SAFETY OFF  && Ensure possible over-write will go through

cConfigFileDir = <somewhere>
cConfigFile = ADDBS(cConfigFileDir) + "autodocspath.ini"
IF FILE(cConfigFile)
   * --- File Exists, Get contents into a string ---
   cConfigString = FILETOSTR(cConfigFile)
   
   * --- Now parse string to find individual values ---
   * --- And change the individual values within the string if needed ---
       <do Whatever needed >

   * --- Write the INI file ---
   =STRTOFILE(cConfigString,cConfigFile)
ELSE  && IF FILE(cConfigFile)
   * --- No Config File Exists, Create One ---
   * --- Build string in some manner depending on your needs ---
   cConfigString = 'Data: ' + cDataPath + CHR(10)+CHR(13)
   cConfigString = cConfigString + 'Reports: ' + cReportsPath + CHR(10)+CHR(13)
      * --- And so on ---

   * --- Write the INI file ---
   =STRTOFILE(cConfigString,cConfigFile)
ENDIF  ** IF FILE(cConfigFile)

Good Luck

0
 
wcsoctuCommented:
" Instead of popping up the LOCATEDATA window, I get an error saying defaults not found. "
Is it possible that you have the defaults table in the forms data environment?
Right-click the form and click Data Environment.  Remove it if it is there.
0
 
mikejcurtisAuthor Commented:
No, I did check that. The Data environment is empty.
0
 
pcelbaCommented:
This not problem of Data environment most probably but it seems the form uses Private data session.

So, what is form's DataSession propery value?

Another (easier) solution would be to post the form (bith .SCX and .SCT file) here for review. It does not seem to contain some secrets. You just have to add .TXT extension to the form file names.
0
 
pcelbaCommented:
And maybe I am also wrong. The current directory can be different for compiled EXE and your form simply does not find the defaults.dbf file then the message "Defaults.dbf was not found in the specified location.". It is not error message but application message or WAIT WINDOW message.

And let me say one sentence about different locations of EXE and data:  You should take into account the situation where the EXE is installed in a folder with read/only access rights for users, so to store some INI file is possible during the installation or you have to store it somewhere else.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 4
  • 4
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now