Hi,

I have a file output.txt as follows :

c FILE
c
c
c
p val 25 36
8 1 0
-1 -8 0
-9 -7 0
-9 -2 0
7 2 9 0
-10 6 0
-10 8 0
-6 -8 10 0
-11 -9 0
-11 -3 0
9 3 11 0
12 -10 0
12 -9 0
10 9 -12 0
13 -10 0

I wish to change the line "p val 25 36" to "p val 26 37". Is there a way to do so besides copying the file to a new file and changing the line when writing to the new file.

Is it possible to do using seekp and tellg.

Thanks

Dani AI

Generated

Yes — an in-place edit is possible with seekp/tellg, but only when the replacement occupies the same number of bytes as the original line (or when the program moves the rest of the file bytes after the change). 's fstream idea is exactly the right direction for same-length edits, and 's getline+rewrite approach is the safest general solution for length-changing edits.

A compact, safe-in-the-common-case pattern (find line, record start, overwrite when sizes match):

#include <fstream>
#include <string>

int main() {
    std::fstream f("output.txt", std::ios::in | std::ios::out);
    if (!f) return 1;
    std::string line, target = "p val 25 36", repl = "p val 26 37";
    while (true) {
        std::streampos start = f.tellg();                 // start of this line
        if (!std::getline(f, line)) break;
        if (!line.empty() && line.back() == '\r') line.pop_back(); // handle CRLF
        if (line == target) {
            if (repl.size() == line.size()) {
                f.seekp(start);
                f.write(repl.c_str(), repl.size());     // overwrite in-place
            } else {
                // fallback: stream to a temp file and replace safely (see below)
            }
            break;
        }
    }
    return 0;
}

Notes and cautions:

  • The OP's replacement ("p val 26 37") is the same length as the original ("p val 25 36"), so an in-place overwrite is safe here.
  • Newline handling (CRLF on Windows) can introduce an extra '\r' in binary reads; the code above strips it for comparison. Test on a copy first.
  • If the replacement is longer, either (a) stream the whole file to a temporary file and write the modified line then rename the temp file over the original (robust for any size), or (b) read the remainder of the file into a buffer and rewrite it after inserting the longer line (memory- and complexity-tradeoff). 's point about big files favors the streaming-to-temp-file method for safety and low memory use.

Recommended Answers

All 8 Replies

Yes you can. You could use an fstream for example, that would be the easiest way to do it. Or you can use an ifstream reading the file, then an ofstream to modify it.

Move the pointer (seekp) to the desired location and start writing out your data. You can put out your characters one by one, using "put". This is one way to do it. Or you can use "write". The tricky part is to determinate, where the pointer should be, and of course not to overwrite your "valid" data.

#include <fstream>
using namespace std;

int main () {

  char * buffer;
  long size;

  ifstream infile ("output.txt",ifstream::binary);
  ofstream outfile ("new.txt",ofstream::binary);

  // get size of file
  infile.seekg(0,ifstream::end);
  size=infile.tellg();
  infile.seekg(0);

  // allocate memory for file content
  buffer = new char [size];

  // read content of infile
  infile.read (buffer,size);

  // write to outfile
  outfile.write (buffer,size);
  
  // release dynamically-allocated memory
  delete[] buffer;

  outfile.close();
  infile.close();
  return 0;
}

How do i change the line ? Here is the code which copy the file but how do i change the line in the code?

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
	fstream myfile; // fstream for reading, and writing the file
	char your_thingy[] = "p val 26 37", tmp; // i used char array to store your data
	unsigned int pos = 0; // position of "seekp" - where you want start writing

	myfile.open( "yourfile.txt", ios::binary | ios::in | ios::out  ); // using binary mode
	
	if( !myfile ) // exit if unable to open
	{
		cout << "File does not exist!" << endl;
		cin.get(); // works as "pause"
		exit(1);
	}
	
	do // finding 'p' since you want to find this line "p val 25 36"
	{
		tmp = myfile.get(); // reading by char
		pos++; // incrementing pos
	}
	while( !myfile.eof() && tmp != 'p' ); // stop when 'p' found, or end of file

	myfile.seekp( pos-1, ios::beg ); //set pointer to 'p'
	myfile.write( your_thingy, strlen( your_thingy ) ); //write out your sentence
	// strlen gives back the size of the string

	myfile.close(); // closing file

	cout << "I am a leaf on the wind. Watch me soar. ;)" << endl; // Quote from Firefly :)
	cin.get();	// NO system( "PAUSE" ); use cin.get(); instead :)
	return 0;
}

It is not perfect, but works. You have to modify the code, to make it safe. ( Like what if 'p'is not in the text, but this was a specific task so I am not worried. ) You can also use different type of containers, not char *, like I did. Good luck with it.

I would just getline() each line into a vector of strings, find() the cullprit, then change it via the iterator find() returns. then output the new vector to the file. i estimate a 10 line solution or less.

Hmm, tempting maybe I write it again, based on your idea. I wonder how much resource that would use. :-/

Hi,

Could you give an example of how to find and change the line?

*Points To BevoX's Code*

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.