my program reads a line from a text file using :
std::ifstream myReadFile("route.txt");
getline(myReadFile, line)
And if it finds something that i'm looking for (tag) it stores that line in a temp String. I wan't to continue this until i find some other tag, if i find an other tag i want to be able to return to the previous line in order for the program to read if again as some that other tag and do something else.
I have been looking at putback() and unget() i'm confuse on how to use them and if they might be the correct answer.
Best would be to consider a one pass algorithm, that stores in memory what it could need at the first tag without going back.
If this is not possible, you can "bookmark" the stream position and retreive it later with tellg() and seekg():
streampos oldpos = myReadFile.tellg(); // stores the position
....
myReadFile.seekg (oldpos); // get back to the position
If you read recursively embedded tags (html for example), you could even use a stack<streampos> to push and pop the positions while reading. However, be aware that performance is slowed down by such forward/backward accesses.
You mention putback() and unget(), but these are limited to one char, and seem not suited to your getline() approach.
The easiest thing by far, if you only ever want to roll back by one line, is always to keep track of the line you're on and the line before.
Maintain a cur variable that stores the current line, and prev that stores the previous one. When you move to the next line, you copy cur into prev, and read the new line into cur.
That way, you always have the previous line available.
Related
I want to add columns of data to a text file, one column in each iteration (one space between each column). If I open file for appending, it adds next column at the bottom of first column. Is it possible to append sideways?
All data isn't available at the start. Only one column of data becomes available in each iteration, and it gets lost in the next iteration.
Consider the file to be one long stream of characters, some of them just happen to be line breaks. Append always starts at the end of the file. If I'm reading you right you need to use seekp(seek new position to put new characters at) on your fstream to get to the right position before writing.
You know the format of your file, therefore you can calculate how much to skip in each line.
Something like this might work:
read line
while line != "":
skip forward the right number of " "
write new column
read new line
I'm a bit of a noob to c++. I understand that when one reads from a stream, you read from the left. e.g If you had a file with the line:
I'm playing around with streams
When you read the file, the first string you'll retrieve from the file is I'm
Is it possible to make the first string you retrieve to be streams
Reading a stream from the right, basically.
Note: This is assuming that you don't read entire lines per time
Streams are not read from left to right, they're read from first to last. They are supposed to model things where this is the logical way to read them and in some cases (e.g. keyboard input) the only sensible way to read them. For a stream that is entirely known at the start (e.g. a file) you could, if you really really wanted, painstakingly seek to the last element and then read them in one-by-one seeking as you go. This would be slow and ugly.
Instead, I recommend you read from first to last in the usual fashion and then manipulate the data once you've got it.
What you want to do is to read the words from right to left, not the whole stream. Reading the stream from right to left would result in smaerts not in streams and I am sure you can not do that out of the box. What I suggest is that you read the words in a vector and then reverse it. Alternatively, reverse the whole string before reading from it and then reverse each word after reading it.
No, there's no support for this in the streams library. A file is generally arranged with the document data going from left to right, top to bottom. Given variable length lines, you can't generally know where the line terminates unless you scan over all the data in the line.
For this requirement, you're best off reading an entire line into a string with getline, then you have many options such as:
writing your own string scanner to find each word in turn (simple enough, fast)
creating a istringstream from the reversed line text, then looping to stream each word in turn - reversing it back before processing (convenient for stream features - whitespace skipping, conversions, status etc.)
tokenising the line into an array or similar, and iterating that in reverse order (simple conceptually, but memory hungry)
I'm opening a file and getting a QTextStream of it. I am then reading the stream line by line using readLine(). When the line matches a certain string, I need to replace it with another string. I need the behaviour to be that the line is completely replaced (ie, if the line was "longword" and I replace it with "word", the line should contain "word" and "word" only).
At the moment I am using seek() and then the << operator to put my string in at the given location, but the remnants of the last string remain, so I am left with something like "wordword". How can I prevent this from happening and ensure the entire previous line is fully replaced with my new one?
To my knowledge, you cannot simply remove a chunk of a text file in-place. If the replacement string was identical in size, you might be able to replace those exact bytes, and if it were shorter you might be able to hack around the problem by filling the empty space with nulls.
If you didn't want to do that, you would have to create a new file, read each line from the old file, make any required changes to that line in memory, then write that line out to the new file. Once this is complete, you could then replace the original file with the new file.
If it were possible to add/remove chunks to/from the file, you would most likely be left with a considerably fragmented file on the HDD. If you needed to insert more characters, extra fragments would have to be created as the new data simply couldn't fit in the amount of space occupied by the old data, and removing data would leave holes in the file.
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.
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)