File being used by another process

jschuchert

Active Member
Licensed User
Longtime User
I have created several points that need to be stored in my file. However I am getting an error that states "File blah blah cannot be accessed because it is being used by another process". This said to me that the file was still open when I tried to open it again. However, I have made sure the file was closed as the following code will show. Here is the code leading up to the problem:

B4X:
Sub compassrule(dnorthstart,deaststart, totaldist, sfirst, spend)
erlat = main.closenorth - dblNorth        'total error in latitude
erdep = main.closeeast - dblEast          'total error in departure
FileClose(c)
FileOpen(c,main.strfilename,cRead)
lineoftext=FileRead(c)
Do Until lineoftext=EOF
coord()=StrSplit(lineoftext,",")
If coord(0)=main.strfirst Then
dblNorth1 = coord(1)
dblEast1 = coord(2)
Exit
End If
lineoftext=FileRead(c)
Loop
FileClose(c)

For i = main.strpointno-(main.intcounter) To main.strpointno-1
FileClose(c)
FileOpen(c,main.strfilename,cRead)
lineoftext=FileRead(c)
Do Until lineoftext=EOF
coord()=StrSplit(lineoftext,",")
If coord(0)=i Then
dblNorth2 = coord(1)
dblEast2 = coord(2)
dblNdiff = Abs(dblNorth1 - dblNorth2)
dblEdiff = Abs(dblEast1 - dblEast2)
dist = Sqrt(dblNdiff ^ 2 + dblEdiff ^ 2)
lat = lat + (dist * erlat / totaldist)
dep = dep + (dist * erdep / totaldist)
dblNorth2 = dblNorth2 + lat
dblEast2 = dblEast2 + dep
coord(1) = dblNorth2
coord(2) = dblEast2
coord(0) = i
dblnorth=dblnorth2
dbleast=dbleast2
main.strpointno=coord(0)
FileClose(c)
CallSub("storecoord")  'problem after this sub is called
dblNorth1 = dblNorth2
dblEast1 = dblEast2
Exit
End If
lineoftext=FileRead(c)
Loop
FileClose(c)
Next 
FileClose(c)
End Sub

Then here is the code for the storecoord sub:
B4X:
Sub storecoord()
coord(0) = main.strpointno
coord(1) = dblNorth
coord(2) = dblEast
FileClose(c)
FileOpen(c,main.strfilename,cWrite,cAppend) '[color=red] Where error is triggered [/color]
FileWrite(c, coord(0) & "," & coord(1) & "," & coord(2) & "," & coord(3))
FileClose(c)
End Sub

All of the numbers work leading up to the problem. I have successfully stored points using this sub with other routines. Could the error message be intimating something else? I suspect it might be bad logic within the For...Next with Do...until embedded but can't pinpoint it. I appreciate all the past support I have gotten here. Thanks.

Jim Schuchert
 

jschuchert

Active Member
Licensed User
Longtime User
Well guys, apparently you can't come up with a solution, either. Since my post, I have done everything I can think of, but without success. There is a work around I can use but it is really hokey and will require my explaining in the instruction manual how to do it, including exiting and returning to the program. Maybe b4ppc doesn't have the tools for this one. I have determined that a file opened for read, then closed then opened for write within the same routine can't be done without firing the error I keep getting. It doesn't make sense that it cannot be done because I have done it with other software but my skill level simply is not high enough yet with b4ppc. Hopefully one of you gurus will see the solution right away.

Jim
 

mjcoon

Well-Known Member
Licensed User
I must first say that I don't know what the problem is.

But it seems strange to start a code sequence with closing the file before opening it. That hints that you think that other regions of code are/may be not clsong the file when "finished with". (I don't know if the FileClose() fails if the file is not open; if so that means you are indeed leaving the file open.) Why not keep the opening and closing in the same Sub?

The Help about files mentions the "connection name" but does not say what sort of variable this is. It does not seem to need to be declared or "Dim"ed, so there is no opportunity to specify whether it is local to a module (I deduce you are using modules since you use "Main.") or public. Are you using the same connection name in other modules?

Another approach might be to use ErrorLabel(), but I'm not sure what you would do in the error handling routine!

HTH, Mike.
 

klaus

Expert
Licensed User
Longtime User
I had also a look at your code and don't see why you get the error.
As already suggested by mjcoon, I would also remove all unnecessary FileClose(c) lines.
Another suggestion is to change the 2nd routine that way:
B4X:
Sub storecoord()
  coord(0) = main.strpointno
  coord(1) = dblNorth
  coord(2) = dblEast
  FileOpen([COLOR=red]c1[/COLOR],main.strfilename,cWrite,cAppend)
  FileWrite([COLOR=red]c1[/COLOR], coord(0) & "," & coord(1) & "," & coord(2) & "," & coord(3))
  FileClose([COLOR=red]c1[/COLOR])
End Sub

Or could you post a sbp file so we could also test it and try to find out what's going wrong.

Best regards.
 

jschuchert

Active Member
Licensed User
Longtime User
Mike and Klaus,

Thank you for your responses. I suppose it is a VB habit of mine to always close a file prior to opening just in case I did not close it from a prior routine. Mike's suggestion that maybe B4PPC doesn't handle that well is a good one and I will check that out. Klaus, your suggestion to change the connection name in the 'Storecoord' sub doesn't work because the file name (strfilename)is still the same. If I change the file name, all is OK.

Here is what I am trying to do:

I have a text file of values, separated with commas (strfilename) that I open at the beginning of the application. Then other routines make calculations, the results of which are added to that file via the 'storecoord' sub. No problems so far. Now I have a routine (a traverse) that creates new points w/coordinates intended to close upon itself or an existing point. These new points are also stored in the file. Still no problems to here. Since the traverse does not exactly close upon the 'closing point', I need to adjust the distances/coordinates to make it precise. This is where the 'compassrule' sub comes to play. The code in this sub is supposed to adjust the coordinates and put them back into the file. The math works fine but putting the points back into the file is where the error occurs. Looking at my code, you will see where I have tried to do this by closing the file, then opening it for writing (storecoord). I realize I will have 2 sets of the same points in the file (unadjusted and adjusted) but I will address that later. My work-around is to create a second file to contain the adjusted points, have the user exit the program and copy and paste from the second file to overwrite the points in the main file (strfilename). I could probably do it with code without leaving the program but that is a lot of additional code if not necessary. Hopefully this explanation will help your understanding of the issue.

I guess what I am really asking is whether or not my logic should work and if it is feasible to do it with the method I am using. Thanks Mike and Klaus for your help.

JIm
 

klaus

Expert
Licensed User
Longtime User
Hi Jim,
Couldn't you store the content of your file in a matrix variable, make all your changes and addings in that matrix and when leaving the program store the matrix back to the file. I find that this would be more efficient than working in the file or even with two files.

Best regards.
 

jschuchert

Active Member
Licensed User
Longtime User
Hi Klaus,

Thanks again for your taking the time to help me. I am not clear on what you mean by storing in a matrix. Would you please give me a brief example?

Jim
 

klaus

Expert
Licensed User
Longtime User
You have several possibilities:

1) With a matrix variable:
Dim Pnt(1000,4)
where
Pnt(i,0)=coord(0)
Pnt(i,1)=coord(1)
Pnt(i,2)=coord(2)
Pnt(i,3)=coord(3)
i is the index of the point you are looking at

2) or with a structure variable

Dim Type (X, North, East, K) Pnt(1000)
where
Pnt(i).X=coord(0)
Pnt(i).North=coord(1)
Pnt(i).East=coord(2)
Pnt(i).K=coord(3)
You should adapt X and K to the meaning of your variables, as I don't know what coord(0) and coord(3) do mean.

3) or with single array variables:
Dim PntX(1000)
Dim PntNorth(1000)
Dim PntEast(1000)
Dim PntK(1000)
where
PntX(i)=coord(0)
PntNorth(i)=coord(1)
PntEast(i)=coord(2)
PntK(i)=coord(3)

I hope this is more understandable.

Best regards.
 

mjcoon

Well-Known Member
Licensed User
You have several possibilities:

1) ...

Or perhaps even more radically

4) Use a Table. This has the advantages (should you need them) that you can extend it dynamically merely by adding new rows (just like a file) and also filter to discover rows with given content without doing a search.

A table is just like a matrix but is declared like a Control, not a variable. This is because it can be visible to the user but does not have to be. The columns in the table are equivalent to the named elements in Klaus's "2) or with a structure variable".

HTH, Mike.
 

jschuchert

Active Member
Licensed User
Longtime User
Thank both of you very much for the alternatives. I will explore and try to implement something like that in my code. It may prove to be a valuable tool.
Klaus, coord(0) is the point number and coord(3) is the descriptor of the point.

Jim
 

mjcoon

Well-Known Member
Licensed User

In http://www.b4x.com/forum/questions-help-needed/5166-scope-multiple-module-code.html#post30220, Erel explains that to use a file across module boundaries the connection name can be declared as "Public".

Mike.
 

jschuchert

Active Member
Licensed User
Longtime User
Mike,

Thank you for your follow-up and I was really anxious to try it. However, no matter what I do so far as the 'connection' to the main file 'strfilename', it cannot be opened for 'write' after having been opened for 'read' within the code I posted. Further experimention revealed that as soon as I leave the main module, the error occurs...but only if the read/write happen in the non-main module. If opened for "read" in the main module then I can open for "write" in the other module but not both as previously mentioned. It doesn't make sense but that is what is happening. I have googled the problem and the answer is to restart the application which is a poor alternative but is how I may have to handle it. I am also playing with the 'type structure' suggested by Klaus and table by you but it would mean a major reconstruction of my app. I am familiar enough with the 'file' system now that I can move around it pretty well and would prefer staying there. I will do further experimenting on a dummy file to verify my findings. Thanks for your help.

Jim
 

jschuchert

Active Member
Licensed User
Longtime User
Mike and others,

I created a test application and did successfully what I couldn't do with the other app on which I have been posting. I didn't use any forms, only code and it worked perfectly. Here is the code for the test app.

B4X:
Sub Globals
   'Declare the global variables here.
Public strfilename,testfile
End Sub

Sub App_Start
   strfilename="c:\cogo\basic4ppc\test.txt"
   testfile="c:\cogo\basic4ppc\testwrite.txt"
   FileOpen(c,strfilename,cWrite,cAppend)
   FileWrite(c,"come" & "  " & "go" & " " & "stay")
   FileWrite(c,"1" & "," & "2" & "," & "3")
   FileWrite(c,"How are you, anyway")
   FileClose(c)
   
   FileOpen(c,strfilename,cRead)
   lineoftext=FileRead(c)
   FileOpen(c1,testfile,cWrite,cAppend)
   Do Until lineoftext=EOF
   FileWrite(c1,lineoftext)
   lineoftext=FileRead(c)
   Loop
   FileClose(c)
   FileClose(c1)
   FileOpen(c1,testfile,cRead)
   lineoftext=FileRead(c1)
   FileOpen(c,strfilename,cWrite,cAppend)
   FileWrite(c,lineoftext)
   FileClose(c)
             FileClose(c1)
   CallSub("testmod.somesub")  [color=red] In another module[/color]
             End Sub

B4X:
Sub Globals
   'Declare the global variables here.
End Sub

Sub somesub   '[color=red]new module[/color]
For i=1 To 4
FileOpen(c,main.strfilename,cRead)
lineoftext=FileRead(c)
Do Until lineoftext=EOF
lineoftext=FileRead(c)
Loop
FileClose(c)
FileOpen(c,main.strfilename,cWrite,cAppend)
FileWrite(c,"hello" & "  " & "goodbye")
FileClose(c)
Next
End Sub

I have now proved to myself that the read/write works across modules with essentially the same code as my real application. It wouldn't do it in my real app so back to the drawing board to see if I can come up with the elusive answer. :sign0148:

Jim
 

mjcoon

Well-Known Member
Licensed User
Hi Jim, I'm not certain what the distinction with your other app is. But I would not expect that making the file name string variables Public would make any difference. As far as execution is concerned they could just be string constants in each FileOpen() call.

What I was referring to, and what Erel's earlier post was about, was the connection names, which are "c" and "c1" in your code. These are variables that are being given some magic value by the FileOpen() to distinguish each open file.

Since you have not declared c or c1 to be Public I imagine that it would make no difference if you used different connection names in the different modules.

Whereas if you had made c and c1 Public you could open a file in the main module and use it (without close and re-open) in the secondary module by using main.c and main.c1.

I would expect that it would not be permissible to open the same file twice simultaneously for writing, even in the same program. But richer coding environments have additional options to set whether a file open is to be exclusive or mutual.

A FileOpen() is usually fairly resource-hungry because of the Operating System's requirement for checking access permissions and so forth. I would expect (but have not tried) that a file opened for writing can also be read from. If so this may make it possible to reduce the number of FileOpen() you have to do.

HTH, Mike.
 

jschuchert

Active Member
Licensed User
Longtime User
Hello Mike,

Well, by putting the problem sub (compassrule) into the main module so that I did not have to cross module boundaries, the issue I was having went away. I tried the 'public' declaration of the connection name but that did not work...for me at least. I think I will now transfer everything to the main module to make life easier. Nevertheless, I appreciate your time to help me solve the problem. I also thank Klaus for his input. You guys and others I have dealt with are really great. I'm sure you will see me again but if not before Christmas, I wish you all a wonderful holiday season.

Jim
 

jschuchert

Active Member
Licensed User
Longtime User
Klaus,

Thank you for taking the time to do this. I have fooled around a lot with the 'compassrule' sub so you will see many lines commented out. There will have to be some instruction from me so you can follow what to do to see the problem. I have attached the zip file of the code and the module plus a text file I used to do the routine. After starting the program, select 'travtest' from the listbox. Then choose 'Ang-Dist' from the menu and put the following in the boxes:
Occ 7
Sight 1
Cls Pt 8
Angle 275
Dist 200
Next 10
OK
Display box should show results
Repeat the above process for Angle, Dist and Next as follows:
225
400
11 it should appear automatically
Ok

92
400
12
OK

254
180
13
OK

In the angle box enter the word 'close'

You will see the error about 'file being used by another process'. It occurs on line 1348 in the 'compassrule' sub. The other code used for this routine is run from 'btnangdistOK'.

Please don't spend much time with this because I think I have resolved the issue by placing all code in the main module. It will be interesting, though, if you see something that I failed to catch. Good luck.

Jim
 

klaus

Expert
Licensed User
Longtime User
Hi Jim,
I had a look at your program and get also always the same error.
I tried different things but witout any success.

From a simple programming logic it should work.
So to me it seems beeing a B4PPC bug ?

I would suggest that Erel had a look at it.

Best regards.
 

agraham

Expert
Licensed User
Longtime User
It's not a bug, it's a programming error

In Main you open the file at line 1033 then later call the Sub where the error occurs with the file still open at line 1097. As the file is open for reading you can reopen it again for reading in the Sub (actually another Sub that it calls) but cannot reopen it for writing which is why you get the error. If you put a FileClose before the Sub call at line 1097 it doesn't error.
B4X:
1033 FileOpen(c, strfilename,cRead)
 ....
1097 CallSub("modppc1.closeparcel", spend) ' Problem!, file is still open here
Some comments.

You don't need all those CallSub statements. They cost performance and are unnecessary unless you need to choose the target Sub at runtime.

Your file handling needs rethinking. With all that opening and closing going on you are almost bound to miss something and so run into errors like this.
 

jschuchert

Active Member
Licensed User
Longtime User
Klaus, thank you so much for testing the program and finding what I was finding. But agraham nailed it with a great "eagle eye". I would never have suspected that was where the culprit was. In my first post I mentioned that it must be that the file was still open but couldn't imagine where it was since I "thought" I had made sure it was closed. Even after it was pointed out, I thought the 'fileclose' in a subsequent sub took care of it.

Apparently if everything is in the same module, this doesn't apply. I have put everything in my main module now and that particular error doesn't happen although 'fileclose' is not at that location. Incidentally, what is the correct syntax for calling a sub in another module if you don't use 'callsub'? I have tried various alternatives without success. Thanks again.

Jim
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…