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.
Related
I'm very confused with the new programming assignment we got in class a few days ago. It asks us to read info from a file which contains an unknown number of rows and columns and then sort the data. My question is how do I do that?
My reasoning was that if I knew the number of columns, I would just create an array of structures and then create a new structure for each row. But since the number of columns is also unknown, I don't know how to approach this.
Also, we only allowed to use <iostream> <fstream>, <cctype> and <vector> libraries.
You could use a
std::vector<std::vector<WhateverTypeYouWantToStore>>
Use std::vector. You can create a 2D vector like this:
vector<vector<string> > table;
And then read the lines from a file, and put the data into a one dimensional vector (vector<string> line). And then, You can push_back the line vector into the table, like this:
table.push_back(line);
You can see more information about vector on this page: cplusplus.com
I hope you must know what format of data that you are going to read from text file's row and column. First to understand, you will read first row, then second row and so on. If you do not know type of data, then believe all of it as string of characters. So, you can assume wherever you fine null char '\0' then you are finding data for first row, so go on read character by character look for next '\0'. Then wherever you find '\n' that will be last point of first row and you just discovered last column. After '\n' you will start reading 2nd row and so on. With this you can determine how many rows and columns are there. You keep on reading text file until you reach EOF.
See the attached image.
Text File Format
Also, define a pointer to character type and use realloc to assign memory to it. With realloc() you can grow it, as you find more data. Please go through realloc() manual for reference.
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'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.
Is there a way that I can seek to a certain line in a file to read or write data?
Let's say I want to write some data starting on the 10th line in a text file. There might be some data already in the first few lines, or the file could even be empty. Is there a way I can seek directly to the line I want without having to worry about what's already in the file?
Only if the lines are all the same length (seek to 9 * bytes_per_line). Otherwise, you'll just have to scan your way to the appropriate spot in the file.
Also be wary of writing into the middle of a file. It may not do what you expect (insert new lines). It will simply overwrite whatever content is already there, and won't respect existing line boundaries.
You can seek to a position in a file, but that position must be a character offset from the start, end or current position - see for example fseek(). There is no way of seeking to a particular line, unless all the lines are exactly the same length.
No, you have to process the data to find the line delimiters (unless you have fixed length lines). Have a look at getline(), ftell() and fseek(). http://www.pixelbeat.org/programming/readline/cpp.cpp
The easy best way is to read the file in memory inserting for instance each line in a vector of strings, then modifying/adding whatever you want, and re-write each line in a new file.
(supposing the file fits in memory)