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.
Related
I have the following contents in a text file.
Waterpark Avenue 3000
Coit 1010
Synergy Park 9119
Joaquin 1980
Richardson 2413
I want to read the file in such a way that I can output the details in different columns using setw() operator.
The issue I'm facing here is that some lines have 2 names and the others have just 1 and, I can't figure out a way to get around it.
I'd probably start by reading an entire line into a string. Then I'd search for the first non-digit, starting from the right end of the string. Or, depending, I might search for the first white-space character starting from the right end of the string (the two seem equivalent in your examples).
Either way, once you've found that point, you can create one string from the beginning to there, and another from there to the end.
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
I'm writing a payroll program in c++ and need to be able to read lines in a file, do calculations, and then overwrite the read lines in the file. IS there a function/way i can simply overwrite specific lines, insert new lines, add onto the end of an existing file?
There are no C++ functionality to "insert" or "remove" text in a text-file. The only way to do that is to read the existing text in, and write out the modified text.
If the new text fits in the same space as the old one, all you need to do is to overwrite the existing text - and of course, you can always add extra spaces before/after a comma in a .CSV file, without it becoming part of the "field". But if the new data is longer, it definitely won't work to "overwrite in place".
Adding to the end is relatively easy by using the ios_base::ate modifier. But inserting in middle still involves basically reading until you find the relevant place, and then, if the new text is longer, you have to read all the following lines before you can write the new one(s) out.
I am trying to parse a table in the form of a text file using ifstream, and evaluating/manipulating each entry. However, I'm having trouble figuring out how to approach this because of omissions of particular items. Consider the following table:
NEW VER ID NAME
1 2a 4 "ITEM ONE" (2001)
1 7 "2 ITEM" (2002) {OCT}
1.1 10 "SOME ITEM 3" (2003)
1 12 "DIFFERENT ITEM 4" (2004)
1 a4 16 "ITEM5" (2005) {DEC}
As you can see, sometimes the "NEW" column has nothing in it. What I want to do is take note of the ID, the name, the year (in brackets), and note whether there are braces or not afterwards.
When I started doing this, I looked for a "split" function, but I realized that it would be a bit more complicated because of the aforementioned missing items and the titles becoming separated.
The one thing I can think of is reading each line word by word, keeping track of the latest number I saw. Once I hit a quotation mark, make note that the latest number I saw was an ID (if I used something like a split, the array position right before the quotation mark), then keep record of everything until the next quote (the title), then finally, start looking for brackets and braces for the other information. However, this seems really primitive and I'm looking for a better way to do this.
I'm doing this to sharpen my C++ skills and work with larger, existing datasets, so I'd like to use C++ if possible, but if another language (I'm looking at Perl or Python) makes this trivially easy, I could just learn how to interface a different language with C++. What I'm trying to do now is just sifting data anyways which will eventually become objects in C++, so I still have chances to improve my C++ skills.
EDIT: I also realize that this is possible to complete using only regex, but I'd like to try using different methods of file/string manipulation if possible.
If the column offsets are truly fixed (no tabs, just true space chars a la 0x20) I would read it a line at a time (string::getline) and break it down using the fixed offsets into a set of four strings (string::substr).
Then postprocess each 4-tuple of strings as required.
I would not hard-code the offsets, store them in a separate input file that describes the format of the input - like a table description in SQL Server or other DB.
Something like this:
Read the first line, find "ID", and store the index.
Read each data line using std::getline().
Create a substring from a data line, starting at the index you found "ID" in the header line. Use this to initialize a std::istringstream with.
Read the ID using iss >> an_int.
Search the first ". Search the second ". Search the ( and remember its index. Search the ) and remember that index, too. Create a substring from the characters in between those indexes and use it to initialize another std::istringstream with. Read the number from this stream.
Search for the braces.
Text file (or CSV) is:
Data:,,,,,\n
(but with 100 ","s)
In C or C++ I would like to open the file and then fill in values between the ",".
i.e.- Data:,1,2,3,4,\n
I'm guessing that I need some sort of search to find the next comma, insert data, find the next comma insert, etc.
I was looking at memchr() for a buffer and was wondering if there is something similar for a text file?
If you could point me in the right direction, I would appreciate it.
(I don't mind reading a book to find something out like this either, I just don't know what book would have this information?)
Thank You.
You can't actually do that in C... if you open in read/write mode you'll overwrite characters, not insert them.
http://c-faq.com/stdio/fupdate.html
You need to open the file, read the line into memory, write the new line to a temp file.
After you're done inserting all the lines, copy the temp file over the original file. I don't think there's any other way to do it.
(This is for the C++ case)
Just parse the data into an Linked list with the Objects that hold the data, modify the data and overwrite the file.
You first need to split your data into lines(\n creates a new linked-list Element):
Data:,,,,,\n
Data2:,,,,,\n
will get the strings (pseudolist):
["Data:,,,,,", "Data2:,,,,,"]
So now you need to define your Object for each Line like:
class LineStruct {
public:
string head;
LinkedList<string> data;
};
and fill it.
Then you edit the data-structure and after that you write it back to disk.
If you have
Data:,,,,,\n
then there is no space between the , to fill, you have to write out brand new lines.
However if you had
Data: , , , , , \n
then you could overwrite just those parts represented by ' '
in C you would seek to the part of the file and write and then seek to the next pos, sorry no code off the top of my head.
This is where I would look:
std::getline for reading lines into std::strings
std::string::find_first_of for finding the comas
std::stringstream for building the new output-line
As suggested by wmils answer, you will have to either use a temporary file, or hold all the new lines in memory until all lines are processed, and then overwrite the original file.