How to read from a specific line from a text file in VHDL - file

I am doing a program in VHDL to read and write data. My program has to read data from a line, process it, and then save the new value in the old position. My code is somewhat like:
WRITE_FILE: process (CLK)
variable VEC_LINE : line;
file VEC_FILE : text is out "results";
begin
if CLK='0' then
write (VEC_LINE, OUT_DATA);
writeline (VEC_FILE, VEC_LINE);
end if;
end process WRITE_FILE;
If I want to read line 15, how can I specify that? Then I want to clear line 15 and have to write a new data there. The LINE is of access type, will it accept integer values?

Russell's answer - using two files - is the answer.
There isn't a good way to find the 15th line (seek) but for VHDL's purpose, reading and discarding the first 14 lines is perfectly adequate. Just wrap it in a procedure named "seek" and carry on!
If you're on the 17th line already, you can't seek backwards, or rewind to the beginning. What you can do is flush the output file (save the open line, copy the rest of the input file to it, close both files and reopen them. Naturally, this requires VHDL-93 not VHDL-87 syntax for file operations). Just wrap that in a procedure called "rewind", and carry on!
Keep track of the current line number, and now you can seek to line 15, wherever you are.
It's not pretty and it's not fast, but it'll work just fine. And that's good enough for VHDL's purposes.
In other words you can write a text editor in VHDL if you must, (ignoring the problem of interactive input, though reading stdin should work) but there are much better languages for the job. One of them even looks a lot like an object-oriented VHDL...

Use 2 files, an input file and an output file.
file_open(vectors, "stimulus/input_vectors.txt", read_mode);
file_open(results, "stimulus/output_results.txt", write_mode);
while not endfile(vectors) loop
readline(vectors, iline);
read(iline, a_in);
etc for all your input data...
write(oline, <output data>
end loop;
file_close(vectors);
file_close(results);

Related

How to write at the middle of a file in c

Is it possible to write at the middle of a file for example I want to insert some string at the 5th position in the 2nd line of a file in c ?
I'm not very familiar with some of C functions that are related to handling files , if someone could help me I would appreciate it
I tried using fputs but I couldn't insert characters at the desired location
open a new output file
read the input file line by line (fgets) writing each line out to a new file as you read.
When you hit the place you want to insert write the new line(s)
The carry on copy the old lines to the new file
close input and output
rename output file to input
Continuing from my comments above. Here's what I'd do:
Create two large, static char[] buffers of the same size--each large enough to store the largest file you could possibly ever need to read in (ex: 10 MiB). Ex:
#define MAX_FILE_SIZE_10_MIB (10*1024*1024)
static char buffer_file_in[MAX_FILE_SIZE_10_MIB];
static char buffer_file_out[MAX_FILE_SIZE_10_MIB];
Use fopen(filename, "r+") to open the file as read/update. See: https://cplusplus.com/reference/cstdio/fopen/. Read the chars one-by-one using fgetc() (see my file_load() function for how to use fgetc()) into the first large char buffer you created, buffer_file_in. Continue until you've read the whole file into that buffer.
Find the location of the place you'd like to do the insertion. Note: you could do this live as you read the file into buffer_file_in the first time by counting newline chars ('\n') to see what line you are on. Copy chars from buffer_file_in to buffer_file_out up to that point. Now, write your new contents into buffer_file_out at that point. Then, finish copying the rest of buffer_file_in into buffer_file_out after your inserted chars.
Seek to the beginning of the file with fseek(file_pointer, 0, SEEK_SET);
Write the buffer_file_out buffer contents into the file with fwrite().
Close the file with fclose().
There are some optimizations you could do here, such as storing the index where you want to begin your insertion, and not copying the chars up to that point into buffer_file_in, but rather, simply copying the remaining of the file after that into buffer_file_in, and then seeking to that point later and writing only your new contents plus the rest of the file. This avoids unnecessarily rewriting the very beginning of the fie prior to the insertion point is all.
(Probably preferred) you could also just copy the file and the changes you insert straight into buffer_file_out in one shot, then write that back to the file starting at the beginning of the file. This would be very similar to #pm100's approach, except using 1 file + 1 buffer rather than 2 files.
Look for other optimizations and reductions of redundancy as applicable.
My approach above uses 1 file and 1 or 2 buffers in RAM, depending on implementation. #pm100's approach uses 2 files and 0 buffers in RAM (very similar to what my 1 file and 1 buffer approach would look like), depending on implementation. Both approaches are valid.

Is it possible to scan a file in reverse from the last line in C?

I am running a simulation and want to add an option to continue evolving from the last iteration of a previous run. In order to do so, I need to read the last 2 lines of data from a file. Is there any way to do this without using fscanf to scan from the beginning of the file?
Have the previous run record in another file the ftell() values of the last few lines and other info to note the meta data of the file (e.g. date-time-modified).
A subsequent run can use this info to begin where the prior run left off.
If this side file is missing or does not agree with the current state of things, walk the files with fgetc(), fgets(), etc. to find where to begin again.

COBOL Replace the first line in a file without using OPEN I-O and REWRITE

Say that I have a file with the below format
<records count="n">
record line 1
record line 2
.
.
.
record line n
</records>
I'll have to open this file and change the value of n to another value based on some logic. After change my file should look like.
<records count="m">
record line 1
record line 2
.
.
.
record line n
</records>
I can open the file in OPEN I-O mode and change the first line using the REWRITE option to replace the first line. But I don't want to use these methods. Is there a way to achieve the same logic using OPEN INPUT and OPEN OUTPUT mode and replace the line with WRITE method.
Is there a way to achieve the same logic using OPEN INPUT and OPEN
OUTPUT mode and replace the line with WRITE method[?]
No, that would leave you with only the <records count="m"> in the file. All other records would be lost!
As long as the length of the first record is the same, after changing n to m, REWRITE is the most straight forward way to update that record.
Perhaps, if you explain why you want to use WRITE, there may be something else that could be done.
If the file is not 'too' large, read all the records into memory, change the first record, then write all the records to the file.
If the file is 'too' large, copy the file changing the first record, delete the first file, then rename the copy.
Perhaps less efficient for 'too' large, sort the file by adding a sequence number and changing the first record. This simply uses the sort file to hold the data, temporarily. Possibly a poor choice for a program to be converted.
You need to define what the limit for 'too' is.
There are non-standard routines for file access in Micro Focus, but those might be more difficult to convert.

replace a substring in a string in C, windows

I want to do the following:
open and read and ASCII file
locate a substring (geographical coordinates)
create its replacement (apply corrections to the original coordinates)
overwrite the original substring (write in the original file the corrected coordinates).
The format of the ASCII file is:
$GPGGA,091306.00,4548.17420,N,00905.47990,E,1,09,0.87,233.5,M,47.2,M,,*53
I will paste here only the part of the code that is responsible for this operation:
opnmea = fopen (argv[1], "r+");
if (fgets(row_nmea, ROW, opnmea)==NULL){
if (strstr(row_nmea,"$GPGGA")!=NULL) {
sscanf(row_nmea+17, "%10c", old_phi);
sscanf(row_nmea+30, "%11c", old_lam);
sscanf(row_nmea+54, "%5c", old_h);
fputs();
}
}
What I do till now is to extract in a variable the old coordinates and I was thinking to use fputs() for overwriting the old with new values. But I could not do it. The other part of the code that is not here is computing the correct coordinates. My idea is to correct the rows one by one, as the fgets() function reads each line.
I would appreciate very much any suggestion that can show me how to use fputs() or another function to complete my work. I am looking for something simple as I am beginner with C.
Thank you in advance.
Patching a text file in place is not a good solution for this problem, for multiple reasons:
the modified version might have a different length, hence patching cannot be done in place.
the read-write operation of standard streams is not so easy to handle correctly and defeats the buffering mechanism.
if you encounter an error during the patching phase, a partially modified file can be considered corrupted as one cannot tell which coordinates have been modified and which have not.
other programs might be reading from the same file as you are writing it. They will read invalid or inconsistent data.
I strongly recommend to write a program that reads the original file and writes a modified version to a different output file.
For this you need to:
open the original file for reading opnmea = fopen(argv[1], "r");
open the output file for writing: outfile = fopen(temporary_file_name, "w");
copy the lines that do not require modification: just call fputs(row_nmea, outfile).
parse relevant data in lines that require modification with whatever method you are comfortable with: sscanf, strtok, ...
compute the modified fields and write the modified line to outfile with fprintf.
Once the file has been completely and correctly handled, you can replace the original file with rename. The rename operation is usually atomic at the file-system level, so other programs will either finish reading from the previous version or open the new version.
Of course, if the file has only one line, you could simply rewind the stream and write back the line with fprintf, but this is a special case and it will fail if the new version is shorter than the original. Truncating the extra data is not easy. An alternative is to reopen the file in write mode ("w") before writing the modified line.
I would recommend strtok(), followed by your revision, followed by strcat().
strtok() will let you separate the line using the comma as a delimiter, so you will get the field you want reliably. You can break up the line into separate strings, revise the coordinates you wish, and reassemble the line, including the commas, with strcat().
These pages include nice usage examples, too:
http://www.cplusplus.com/reference/cstring/strtok/
http://www.cplusplus.com/reference/cstring/strcat/?kw=strcat

Deleting x amount of lines from the top of a text file

I'm writing an application which will use a log file. What I want to do is when the application starts it will check to see if the log file is above a certain size and if it is it will delete 'x' amounts of lines from the top of the log file to shorten it up. What would be a good way of going about doing this? Would it be easier to write the most recent entries to the top of the file and then delete from the bottom when I do delete?
So you have a log file, let's call it "log.log"
First, move log.log to log.log.bak. Open it for reading. Read line by line until you have read x number of lines. Open a new file, log.log, for writing. Continue reading lines from log.log.bak and for each line write it to log.log. When there are no more lines, close log.log and log.log.bak and then delete log.log.bak.
Some pseudo code:
x = number of lines to delete
move log.log to log.log.bak
open log.log.bak for reading
while i have read < x lines
read a line and throw it away
open log.log for writing
while there are more lines in log.log.bak
read a line from log.log.bak
write the line to log.log
close log.log
close log.log.bak
delete log.log.bak
There are plenty of questions left open-
What environment are you in? In a Un*x you could simply 'tail -100 input.txt >trimmed.txt'
Can you load the file into memory, or will it be too large?
Can you use an intermediate file?
What languages do you have available/are you familiar with?
How often will you perform the trimming? If you're writing more often than trimming, write to the bottom (which is fast) and perform the expensive trimming operation rarely.
If you have C available, you can find the filesize with fseek(f,0,SEEK_END);long size=ftell(f); (immediately after opening f).
If you need to trim, you can fseek(f,size-desired_size,SEEK_SET); and then while (fgetc(f)!='\n') {}, which will take you to the end of the line you intersect.
Then copy what remains to a new file.
I wouldn't remove a certain number of lines. Basically you have to process the whole file if you do that and that could be a lot of processing. The normal practice is just to roll the log file (rename it something else, often just appending the date) and start again.
Also bear in mind that the file being a certain size is no guarantee that there are the requisite lines there in which case you're just renaming the file the expensive way.
I often find it useful when an app startup begins at the top of a file too.
Keep several log files File1 - FileN for each kind of log.
Fill file File1 then File2 and so on when each file passes some fixed size.
When you fill FileN delete File1 and start over (deleting) and rewriting File1, File2 ...
This gives you a cyclical fixed size log.
Note: this requires you to keep track of which is the current log file to write to. This can be stored in a separate log file.

Resources