ofsteam overwriting the selected part of a txt file - c++

I am new in C++98. I am getting some fields from a large text file. I want to update only 4 out of 50 lines in the text file. Here is my code. It is getting the text from a lineEdit of a Qt4 form.
strcpy(Name,ui->lineEdit_1->setText(QString::fromStdString(Name)) );
strcpy(Class,ui->lineEdit_1->setText(QString::fromStdString(Class)));
strcpy(Grade,ui->lineEdit_1->setText(QString::fromStdString(Grade)));
std::fstream myfile;
myfile.open(mypath,std::fstream::in | std::fstream::out );
myfile<<Name<<"\t"<<"Name"<<"\n";
myfile<<Class<<"\t"<<"Class"<<"\n";
myfile<<Grade<<"\t"<<"Grade"<<"\n";
Here is sample.conf.txt:
Hello. Name
One. Class
Two. Classsec
A+. Grade
B+. Gradesec
On updating it by adding random values:
Name AA
Class BB
Grade CC
After executing the above code, it shows this updated sample.conf.txt:
AA Name
BB Class
CC Grade
A+. Grade
B+. Gradesec
It should be like this Model instead:
AA Name
BB. Class
Two. Classsec
CC. Grade
B+. Gradesec
Means it (fstream) is just:
1- overwriting truncate the top 3 lines in the file, leaving the rest of the file intact.
2- it is not selecting the position field name to overwrite its value, according to input content?
How can I overwrite by selecting the specific position by name and write its corresponding value, or write column-wise? How can I accomplish this task? Please help.

You cannot do this. When you update a file, then any text you write will replace exactly the same number of bytes as the size of the text you are writing.
It's not that case that if you write three lines of text, then they will replace the first three lines of text currently in the file (unless those two pieces of text happen to be exactly the same length).
Unless you are doing binary IO with fixed length records then trying to update files is not the way to go. Instead your program should read in the whole file into some data structure, manipulate that data structure as required, and then write out the entire data structure to a file, replacing the whole contents of the file.

Related

How to read a specific line from a text file in c++?

C++ program that displays on the screen item codes with corresponding
item descriptions and prices. It asks the user to enter the code of the item
purchased by a customer. It looks for a match of the item code stored in items.txt.
How can I output only a specific line from a text file after the user inputs the item code?
You need to read the file line-by-line (std::getline), extract (depending on the exact format, e.g. by searching for a whitespace in the string) and compare the code and then return the corresponding line on a match.
It is not possible to access lines from a text file directly by index or content.
This is assuming that you mean the file contains lines in the form
code1 item1
code2 item2
//...
If the code is just the index of the line, then you only need to call std::getline in a loop with a loop counter for the current index of the line.
If you do this multiple times on the same file, you should probably parse the whole content first line-by-line into a std::vector<std::string> or a std::(unordered_)map<std::string, std::string> or something similar to avoid the costly repeated iteration.
Depending on the use case, maybe it would be even better to parse the data into a database first and then query the database, even if it is only e.g. sqlite or something like that.

Include massive text file in C++ program

I have a comma delimited text file that has a few million entries. After every 23 entries there is a newline. I will add each full line as an instance of a vector, with the 23 fields as instances of a sub-vector. So, the first instance will be vec[0][0-22], followed by vec[1][0-22], etc.
This file is a part of my program and needs to be compiled with it. Meaning, I don't want to have to provide the file additionally and use ifstream to read the data from the separate file.
I already can sort the data using ifstream, but now I need to integrate the raw data into the program so that I can compile it all together.
I am unable to make this large comma-delimited-field text file into one long string and then separate it into fields because some of the fields have quotes within them, with commas between the quotes too.
example:
`19891656,PLANTAE,TRACHEOPHYTA,MAGNOLIOPSIDA,FABALES,FABACEAE,Zygia,ampla,(Benth.) Pittier,,,,,Pithecellobium amplum |Pithecolobium brevispicatum ,Jarendeua de Sapo,,,LC,,3.1,2012,stable,N
19891919,PLANTAE,TRACHEOPHYTA,MAGNOLIOPSIDA,FABALES,FABACEAE,Zygia,biflora,L.Rico,,,,,,,,,VU,B2ab(iii),3.1,2012,stable,N
2060,ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,OTARIIDAE,Arctocephalus,pusillus,"(Schreber, 1775)",,,,,Phoca pusilla,"Afro-Australian Fur Seal, Australian Fur Seal, Brown Fur Seal, Cape Fur Seal, South African Fur Seal",Arctocphale d'Afrique du Sud,,LC,,3.1,2015,increasing,N`
When my program runs it will source data from this mass of text, and it will not need to use ifstream with a path to an external file. How can I include this text file in my program? Is there a way to "include" text files? If I need to make a massive array of strings, how do I do this with quoted fields with commas between the quotes? I would be happy to clarify any part of this question which seems vague as I am really curious as to how I can make this work.
Technically this text file is a csv, but I am hesitant to include csv as a tag because I think people will think I am looking for a csv parsing solution.
You may want to write a script to convert each line of your data file into an initializer of a record struct with a trailing comma after each lins [if you don't want to use a terminator entry (see below) than except the last line]. This script may be your data type specific. Say,
12,Joe,,,YES -> MyType(12,"Joe",0,0,true),
Then #include the entire converted file in place of your data array/vector element initializers, for ex
MyType myData [] =
{
#include "my_data_file_converted"
MyType() //an optional terminal entry
};
Of course MyType should have constructor(s) accepting your initialization sequences.

Appending the header of a txt document with ColdFusion

Using ColdFusion I would like to append the header of the file each time that I add a row into the txt file
The format for the header is as follows:
E.g.
1234567890123456789012345678901234567890
BEEP BANK 1000009099810
The header's content is broken down into:
Element Description Pad char Pad side Length
Bank name First 16 characters of the Bank name as per file [space] right 16
name, padded with spaces at the end if the name is
less than 16 characters long. Convert to Uppercase
Record count Number of data records in the file, depicted as a 0 left 3
3 character, zero-left-padded string
Total value Value (in cents) of all amounts in the file, 0 left 10
depicted as a 10 character, zero-left-padded
string
Total Header Record Length 29
At the moment I am running a loop and inside of the loop I would like to update the Record Count and the Total Value inside of the header while still keeping the same format
What I would like to know is how do I get the header of the txt file called test.txt and split the numeric value to get the individual values namely Record Count and Total Value to work with them and add my new dynamic values to them?
Thanks in advance
This will read the file and replace the first line, and write it back to the original file.
<cffile action="read" variable="textDoc" file="#getDirectoryFromPath(getTemplatePath())#/test.txt" />
<cfset textDoc = listSetAt(textDoc,1,"new header line","#chr(10)##chr(13)#")>
<cffile action="write" file="#getDirectoryFromPath(getTemplatePath())#/test.txt" output="#textDoc#">
In this instance we are using new-line and carriage-return as the list delimiters.
You will have to parse the file. If you want to keep it human readable (as opposed to making it XML or similar) then you have to tell coldfusion how to find the characters to update.
I assume the header is always static, only the numbers recording the records change.
The best way is to include those records in the header by escape characters, for example {{125}}.
Then grab the file, and do a regexp looking for {{.?}}, update the number and replace. Then write the file.
OR just delete the whole header and rewrite with the update data everytime the file is saved. Whichever is easier in your case.

c++ overwriting file data?

I am trying to run a program to replace certain data within a file. The relevant parts of the file attempting to be replaced look like the following:
1 Information 15e+10
2 Information 2e+16
3 Information 6e+2
And so on.
The files in question can be very large in the multiple gigabyte range and to my understanding because of this using a buffer of the whole file and rewriting the whole file is impossible/unreasonable. Well that is all fine I just want to replace the values (ex. the 15e+10).
This all works fine with simple ios::in|ios::out and tellp() if I am replacing the value with a similar sized value (15e+10->12e+12) or even if its a smaller size as I can simply add an extra space which can be ignored down the line (ex. 15e+10->4e+10 ). But I am running into the problem if I need to replace the value with a value whose length is longer than already in the file (ex. 6e+2->16e+10) it will write over the new line character or start writing over the information in the next line.
I have searched on the forums and everyone says you can either overwrite in the file, you can append to the end of the file, or you can buffer and recreate the whole file. Is there anyway I can achieve my goal of overwriting the value correctly without having to recreate the file?
If not then how can I have 2 files open (1 input 1 output) to do this if multiple files in question are too large for the memory?
Note: I would also like to avoid using boost:: as I need to be able to run this on a system without the boost library.
Open a stream to read from the input (IN) file and a second stream (OUT) to write to a new output (tmp) file.
Read from IN and write to OUT. When you get a value from IN that you want to replace write the replacement to OUT instead of the value you got from IN.
When parsing is complete replace the first file with the second (tmp) file.
Would this work for you?
Use lseek()/fseek() for "jump" to a given position in a file.
You can use seekp to go to the location and rewrite it with <<
Example:
example.txt ( |?| = 1 byte of data )
|A|B|C|\n|1|2|3|D|E|F|\n|4|5|6|
//Somewhere in the code
fstream file;
open("example.txt");
//Somehow find the character distance and store it into "distance"
seekp(distance);//If distance = 0, it will go to "A" like rewind() but easier for me
If the distance is 4, the next character will be overwritten is 1
file << "987";
And the file will be
|A|B|C|\n|9|8|7|D|E|F|\n|4|5|6|
BUT the only problem here is when you need to increase/decrease the size:
Increase:
You will overwrite the other character so you need to create a temp string to store it the rest of data or separate it into smaller chunk if the data is too large like
|A|B|C|\n|9|8|7|D|E|F|\n|4|5|6|
string tempstring;
seekp(distance);
file >> tempstring;
seekp(distance);
file << content << tempstring; //content is the data
Decrease:
The easiest solution is to write NULL character \0 to the excess space like
|A|B|C|\n|1|\0|\0|D|E|F|\n|4|5|6|
The only side-effect is the file size is the same as before

Taking substring from string between " sign // C++ Builder

I've got problem with following task. I need to load output txt data from other program to my one and search it for following string:
"zhi": 97.92716217041016,
and especially numerical value (97.92...). The "," sign is separator between other exported values.
I was trying to deal with that in c++ builder following way:
1. read file
2. load lines as strings
3. find position of zhi
4. add 6 to position - this will point on numbers
5. delete everything before new pointer
6. delete everything after 15 char
I know there have to be some easier way but I'm beginner with c++.
Can someone guide me what function I can use to find numbers between "zhi": and , ?
Use std::getline to read file as std::string types.
Use string::find to get the position of the text after "zhi":.
Use string::find to get the position of the ','.
Use string::substr to get a copy of the string between the two positions.
Remember, modifying files in the middle is difficult, especially if you have to delete or insert more characters.
The traditional method of modifying files is:
1. Copy all unchanged content from original file to new file.
2. Write changed text to new file.
3. Write remaining unchanged text to new file.
4. Close all files.