Recent

Author Topic: reset  (Read 2663 times)

oproescu

  • New Member
  • *
  • Posts: 48
reset
« on: September 21, 2023, 02:36:16 pm »
Hello,
I want to open for reading a series of text files named name with the sequence:
AssignFile (F,'name');
Reset (F)
     repeat
     readln(F, string variable);
     .........
     until eof(F)
things proceed normally if the text files named are in the folder with the application, if the text files named are in another folder subordinate to the folder with the application, the file is deleted by the reset function.
The names of the text files are created with the sequence:

var
name:array[1..100] of string;
i,nfile:integer;
F:textfile
FileAttrs: Integer;
sr: TSearchRec;

           findfirst('*.adi',FileAttrs,sr); {when the files are in the same folder as the application and they open correctly}
           findfirst('FOLDER\*.txt',FileAttrs,sr); {when the files are in a folder subordinate to the one with the application and the reset function deletes them}
           name[1]:=sr.name;
           for i:=2 to 200 do
              begin
              findnext(sr);
              if sr.name=name[i-1] then goto 10;
              name:=sr.name;
              end;
10: FindClose(sr);nfile:=i-1;if name[1]='' then nfile:=0;
-----
AssignFile (F,'name');
Reset (F)
     repeat
     readln(F, string variable);
     .........
     until eof(F)

Where am I wrong?
With thanks,
Oproescu

Bogen85

  • Hero Member
  • *****
  • Posts: 685
Re: reset
« Reply #1 on: September 21, 2023, 03:54:33 pm »
Please use the code blocks for this forum, it makes posting things like this more readable, rather than the bold/etc markers.
See the # button on the formatting toolbar.

Hello,
I want to open for reading a series of text files named name with the sequence:
Code: Pascal  [Select][+][-]
  1. AssignFile (F,'name[i]');
  2. Reset (F)
  3.      repeat
  4.      readln(F, string variable);
  5.      .........
  6.      until eof(F).
  7.  

things proceed normally if the text files named are in the folder with the application, if the text files named are in another folder subordinate to the folder with the application, the file is deleted by the reset function.
The names of the text files are created with the sequence:

Code: Pascal  [Select][+][-]
  1. var
  2. name: array[1..100] of string;
  3. i,nfile:integer;
  4. F:textfile
  5. FileAttrs: Integer;
  6. sr: TSearchRec;
  7.  
  8.            findfirst('*.adi',FileAttrs,sr); {when the files are in the same folder as the application and they open correctly}
  9.            findfirst('FOLDER\*.txt',FileAttrs,sr); {when the files are in a folder subordinate to the one with the application and the reset function deletes them}
  10.            name[1]:=sr.name;
  11.            for i:=2 to 200 do
  12.               begin
  13.               findnext(sr);
  14.               if sr.name=name[i-1] then goto 10;
  15.               name[i]:=sr.name;
  16.               end;
  17. 10: FindClose(sr);nfile:=i-1;if name[1]='' then nfile:=0;
  18. -----
  19. AssignFile (F,'name[i]');
  20. Reset (F)
  21.      repeat
  22.      readln(F, string variable);
  23.      .........
  24.      until eof(F);
  25.  

Where am I wrong?
With thanks,
Oproescu

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11938
  • FPC developer.
Re: reset
« Reply #2 on: September 21, 2023, 04:04:51 pm »
Do you try to open a file that you didn't close() or closefile() ?

Bart

  • Hero Member
  • *****
  • Posts: 5467
    • Bart en Mariska's Webstek
Re: reset
« Reply #3 on: September 21, 2023, 06:35:52 pm »
Code: Pascal  [Select][+][-]
  1. AssignFile (F,'name[i]');
  2. Reset (F)
  3.      repeat
  4.      readln(F, string variable);
  5.      .........
  6.      until eof(F)
  7.  
Not related to your question, but that's wrong.
If the file is empty, you still try to read a line from it.
You should use a while loop instead, so the condition Eof(F) is checked before each read.

Bart

oproescu

  • New Member
  • *
  • Posts: 48
Re: reset
« Reply #4 on: September 22, 2023, 08:08:05 am »
Thank you Bogen 85 and many apologies!

@marcov, the file is being opened for the first time, so it has not been opened before. The problem is that, if the file "name" is in the folder with the executable, it is opened and read. If the "name" file is in another folder subordinate to the one with the executable, the "name" file is "seen" and AssignFile is executed but disappears after (or during the execution) of the Reset function. I checked by writing the name of the file on the screen before and after Reset, before executing the Reset function the file exists, after executing the Reset function it no longer exists.

@Bart, the file is not empty. And its name disappears after the execution (or during the execution) of the Reset function and can no longer be read by the repeat---until sequence.

rvk

  • Hero Member
  • *****
  • Posts: 6582
Re: reset
« Reply #5 on: September 22, 2023, 08:20:37 am »
@marcov, the file is being opened for the first time, so it has not been opened before. The problem is that, if the file "name" is in the folder with the executable, it is opened and read. If the "name" file is in another folder subordinate to the one with the executable, the "name" file is "seen" and AssignFile is executed but disappears after (or during the execution) of the Reset function. I checked by writing the name of the file on the screen before and after Reset, before executing the Reset function the file exists, after executing the Reset function it no longer exists.
It could be seen that way but reset did not delete the file.
It could be that the filesystem had a delay in deleting the file and it just happens to be on the reset call. But it's definitely not the cause.

You show a small snippet of your code but there are definitely problems with your code.
You also don't have error handling (like {$I-} and reading of IOResult) which are needed in this code. Not handling that could case all sorts of problems.

Show the complete code relevant to this problem (use the # button to add the tags).

Also... Restructure that for loop of 2 to 200.
You have an array of 100 and try to do 2 to 200?
The for is not needed if you use a while loop with findnext and please, please remove the goto-structure.

For a correct example of findfirst/findnext see the documentation (at the bottom)
 https://www.freepascal.org/docs-html/rtl/sysutils/findfirst.html

You can use break to break out of a loop instead of goto.
« Last Edit: September 22, 2023, 08:29:07 am by rvk »

oproescu

  • New Member
  • *
  • Posts: 48
Re: reset
« Reply #6 on: September 22, 2023, 12:39:34 pm »
Thank you rvk! Let's say that the problem would come from what you say. But why, using the same instructions, does the file in the application folder remain after the Reset function and can be read, but disappears after the Reset function when the file is in another folder?

rvk

  • Hero Member
  • *****
  • Posts: 6582
Re: reset
« Reply #7 on: September 22, 2023, 12:55:45 pm »
Thank you rvk! Let's say that the problem would come from what you say. But why, using the same instructions, does the file in the application folder remain after the Reset function and can be read, but disappears after the Reset function when the file is in another folder?
It doesn't. It's just your conclusion ;)
But there is something else wrong and we can't see what without any code.
That might lead to your conclusion.

You could, for example, have file handles open and the filesystem could hold off deleting the file until it's closed or there is an error.

You also have two findfirst commands after each other but you must always close a successful findfirst (which you don't).

You also do
Code: [Select]
AssignFile (F,'name[i]');That will open a file with the name [ i ]. Not a file with the name in that array element.
So you are not opening different files but just that one file with the name 'name [ i ]'.

(I added the spaces around [ ] because otherwise it would be hidden in the post here. That's why code tags are important.)


« Last Edit: September 22, 2023, 02:36:58 pm by rvk »

Zvoni

  • Hero Member
  • *****
  • Posts: 2741
Re: reset
« Reply #8 on: September 22, 2023, 01:57:02 pm »
Code: Pascal  [Select][+][-]
  1. var
  2. name: array[1..100] of string;
  3. i,nfile:integer;
  4. F:textfile
  5. FileAttrs: Integer;
  6. sr: TSearchRec;
  7.  
  8.            findfirst('*.adi',FileAttrs,sr); {when the files are in the same folder as the application and they open correctly}
  9.            findfirst('FOLDER\*.txt',FileAttrs,sr); {when the files are in a folder subordinate to the one with the application and the reset function deletes them}
  10.            name[1]:=sr.name;
  11.            for i:=2 to 200 do
  12.               begin
  13.               findnext(sr);
  14.               if sr.name=name[i-1] then goto 10;
  15.               name[i]:=sr.name;
  16.               end;
  17. 10: FindClose(sr);nfile:=i-1;if name[1]='' then nfile:=0;
  18. -----
  19. AssignFile (F,'name[i]');
  20. Reset (F)
  21.      repeat
  22.      readln(F, string variable);
  23.      .........
  24.      until eof(F);
  25.  

I'd be more surprised this compiles at all.
He has a "name"-Variable which is an Array with 100 Elements

...and then he loops "2 to 200"....

What i don't understand: Just use FindAllFiles and be done with it....
https://lazarus-ccr.sourceforge.io/docs/lazutils/fileutil/findallfiles.html

EDIT: Your Goto 10 to exit the loop prematurely can be replaced with "Break;"
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Bart

  • Hero Member
  • *****
  • Posts: 5467
    • Bart en Mariska's Webstek
Re: reset
« Reply #9 on: September 22, 2023, 11:14:57 pm »
@Bart, the file is not empty.

You're missing the point here.
It's generally an unsafe method you are using.
Also (and this has been noted before), there is no error checking at all.
(May not be needed if this is just a simple tool for your own private purpose, otherwise you should.)

And its name disappears after the execution (or during the execution) of the Reset function and can no longer be read by the repeat---until sequence.
That makes absolutely no sense to me whatsoever...

As others have said: show us the complete code, otherwise we can't help you with your problem.

Bart

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: reset
« Reply #10 on: September 22, 2023, 11:36:33 pm »
As others have said: show us the complete code, otherwise we can't help you with your problem.
+1

If you managed to forget to close the file properly for example then that can lead to all sorts of strange behaviour because you are basically messing up your filesystem and as a result will confuse the OS (API) in the process. Not using any error checking will for sure lead to unexpected behaviour.

Right now, as it stands, there is so much wrong with the presented code that I don't even know where to begin. What is it that you are trying to accomplish in the first place ?

« Last Edit: September 22, 2023, 11:40:28 pm by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: reset
« Reply #11 on: September 23, 2023, 01:03:17 am »
I suggest to complete remove all of your old low level code and replace with 2 simple methods
from SysUtils: FileExists()
from Classes: TStringList.LoadFromFile()
combine both and you should have what you wanted.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Bart

  • Hero Member
  • *****
  • Posts: 5467
    • Bart en Mariska's Webstek
Re: reset
« Reply #12 on: September 23, 2023, 11:15:17 am »
Some flaws in your original code snippet:
  • nested findfirst without findclose
  • assigning to 'name[ i ]': a literal string
  • accessing the loop variable after the for loop
  • the 2..200 loop

The example below finds all text files in the subfolder "FOLDER" and displays their contents.
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. uses
  4.   sysutils;
  5.  
  6. var
  7.   FNames: array[1..100] of string;
  8.   i, NrOfFiles:integer;
  9.   F: TextFile;
  10.   FileAttrs: Integer;
  11.   SR: TSearchRec;
  12.   S: String;
  13.  
  14. begin
  15.   FileAttrs := faAnyfile;
  16.   NrOfFiles := 0;
  17.   writeln('Collecting text files in "FOLDER" and filling the FNames array:');
  18.   if FindFirst('FOLDER\*.txt',FileAttrs,SR) = 0 then
  19.   begin
  20.     repeat
  21.       Inc(NrOfFiles);
  22.       FNames[NrOfFiles] := 'FOLDER\' + SR.name;
  23.       writeln('FNames[',NrOfFiles,']=',FNames[NrOfFiles]);
  24.     until FindNext(SR) <> 0;
  25.     FindClose(SR);
  26.   end;
  27.   writeln('Nr of files found: ',NrOfFiles);
  28.   writeln;
  29.   if (NrOfFiles > 0) then
  30.   begin
  31.     writeln('Now processing found files:');
  32.     for i := 1 to NrOfFiles do
  33.     begin
  34.       AssignFile(F,FNames[i]);
  35.       writeln('Contents of ',FNames[i],':');
  36.       Reset(F);
  37.       while not Eof(F) do
  38.       begin
  39.         readln(F,S);
  40.         writeln(S);
  41.       end;
  42.       CloseFile(F);
  43.       writeln('<EOF>');
  44.       writeln;
  45.     end;
  46.   end
  47.   else
  48.     writeln('No files found: nothing to process ;-)');
  49. end.

This is a sample output:
Code: [Select]
C:\Users\Bart\LazarusProjecten\bugs\forum\reset>test
Collecting text files in "FOLDER" and filling the FNames array:
FNames[1]=FOLDER\a.txt
FNames[2]=FOLDER\b.txt
FNames[3]=FOLDER\c.txt
FNames[4]=FOLDER\d.txt
FNames[5]=FOLDER\e.txt
Nr of files found: 5

Now processing found files:
Contents of FOLDER\a.txt:
aa
<EOF>

Contents of FOLDER\b.txt:
bb
<EOF>

Contents of FOLDER\c.txt:
cc
<EOF>

Contents of FOLDER\d.txt:
dd
<EOF>

Contents of FOLDER\e.txt:
<EOF>


Notice that the file e.txt is empty and since the code uses the "while not Eof(F)" loop, it perfectly displays the empty contents, whereas the original code would fail with a runtime error.

I did not include any error checking.
If you don't use exceptions, and you want to handle errors, you must turn IOError checking off, and handle all errors yourself (with IOError checking on (it's on by default IIRC), an IOError will terminate your program.)

Basically you then should after each and every reset, rewrite, closefile, read or write check the IOResult variable. If it's not zero, then an error has occurred and you should handle that.
It's a bit of a PITA doing it this way though.

Bart

oproescu

  • New Member
  • *
  • Posts: 48
Re: reset
« Reply #13 on: September 23, 2023, 04:18:22 pm »
Thanks, but I don't think it's worth continuing. I'm a beginner, but I don't do the stupid thing of writing two "finfirst" instructions one after the other without closing them first, as someone noted above. In my example, there are two "finfirsts" but there is a comment after them
findfirst('*.adi',FileAttrs,sr); {when the files are in the same folder as the application and they open correctly}
findfirst('FOLDER\*.txt',FileAttrs,sr); {when the files are in a folder subordinate to the one with the application and the reset function deletes them}
which should show that I use only one of them, I block the other one with //. When reading from the folder with the application it works fine, when reading from another folder, after the "Reset" function, the files disappear.
I will not provide the source of the application. But, in the meantime, I solved the problem by doing other maneuvers, at my level of skill. But it is clear to me that the "Reset" function deletes files when they are taken from another folder, it is the only difference between the two execution modes and that is the problem. If this is difficult to understand, I cannot show more.
Closed topic.
Oproescu

jamie

  • Hero Member
  • *****
  • Posts: 6735
Re: reset
« Reply #14 on: September 23, 2023, 04:47:05 pm »
Well, some lessons to learned here.

AS a recap, incase others didn't press on it.

 First of all, using the FindFirst and the search record, the Search record only holds the file name, not the file path, so you need to include the path along with the file name in other file functions to make sure it is seeing the file that was found by FindFirsrt, etc. You could also use "ChDIR" prior to that.

 Also, the for loop counter index variable is not to be used outside of the loop, it is not guaranteed to be defined or accurate, although in many cases in FreePascal I have seen it to be correct in most cases, whereas in Delphi it could count backwards for efficiency, which it does often.

 if you want to use a loop counter elsewhere outside of the loop, you can use a different loop control like a WHILE loop, or REPEAT...UNTIL loop via a variable, which does guarantee to maintain its correct value outside of the loop.

Thank and have a good day.





The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018