Can insert in an fstream, but not in an iostream - c++

Trying to insert a string in the middle of a file, starting from its end.
The following code works with an fstream, but not with an iostream (in this case the output string is equal to the input one):
// File contents: "abcdefghijklmnopqrstxyz"; "uvw" missing
// 1 - OK
//fstream iofs(fPath, ios_base::in | ios_base::out);
// 2 - Same output
filebuf fileBuffer;
iostream iofs(&fileBuffer); // generic output stream
fileBuffer.open(fPath.c_str(), ios_base::in | ios_base::out | ofstream::app);
iofs.rdbuf(&fileBuffer);
iofs.seekg(0, ios_base::end);
iofs.seekp(0, ios_base::end);
for(int i = 1; i < 20; ++i)
{
iofs.seekg(-i, std::ios_base::end);
char c = char(iofs.peek());
if(c == 't') {
iofs.seekp(-i + 1, std::ios_base::end);
iofs << "uvw"; // add missing token
iofs << "xyz"; // append pre-existing token
break;
}
}
Output:
Case 1: Begin = abcdefghijklmnopqrstxyz; Result = abcdefghijklmnopqrstuvwxyz
Case 2: Begin = abcdefghijklmnopqrstxyz; Result = abcdefghijklmnopqrstxyz
Am I doing something wrong, or I simply cannot do an insert in a iostream?

A generic iostream is not seekable - think keyboard or printer.
You don't check the result of the seekp operation. It probably fails and sets the stream into an error state. Any further output attempts will then do nothing.

Related

c++ how modify file using fstream

I want to edit the first 100 characters of a file,
I do this, but the new characters override the previous ones (like the photo)
my code :
fstream fileStreamIn("text.txt", ios::in | ios::out | ios::binary);
int theSize = 100;
string theMainBuffer(theSize, '\0');
fileStreamIn.read(&theMainBuffer.front(), theSize);
theMainBuffer.resize(fileStreamIn.gcount());
//cout << theMainBuffer << endl;
fileStreamIn.close();
fileStreamIn.open("text.txt", ios::in | ios::out | ios::binary);
fileStreamIn << "blahblah ";
fileStreamIn.close();
I want "blahblah" to be added to the contents of the file and the previous contents of "helloworld" not to be deleted
output :
blahblahrld !
è !©ª}2•¼Ü²ù­XkLÉ·ð„!ð–ç„ñWïðʃ¡ åñ·§Dß}ˆ¹mÐÕŠw:—*ËtMÒJf-Öù“hñ<³:rÛä‡ ”‘Ôyv-4mXþeߧzè’¬ŒŽ<¤‘“‰l'g‚Šâ¡;¬Èa|ÔÁ3îú€;‰±Ï.ÖLáÑȽ[ïÿÿúU%ã2§Ls§n~çˆÏÔäÔ™ 4øÒ‘Ö°,y•»Ô'`` ¬ÜgÜò`÷Tº^E1ØàùÛ÷i§d¨Ù`I5»7á8Zéz0¥Ž’3Y7Êœ¦}eíÝΦIm?óbÙOâ-ŸäëŠgýhýR
Â3‘†y±è±/VŠ¤?Ïù4?’ÑûIÆLQ~DãŠ?Ôêð#N ]³böPK ZQamë š PK 5 -
I want this output :
blahblah hello world !
è !©ª}2•¼Ü²ù­XkLÉ·ð„!ð–ç„ñWïðʃ¡ åñ·§Dß}ˆ¹mÐÕŠw:—*ËtMÒJf-Öù“hñ<³:rÛä‡ ”‘Ôyv-4mXþeߧzè’¬ŒŽ<¤‘“‰l'g‚Šâ¡;¬Èa|ÔÁ3îú€;‰±Ï.ÖLáÑȽ[ïÿÿúU%ã2§Ls§n~çˆÏÔäÔ™ 4øÒ‘Ö°,y•»Ô'`` ¬ÜgÜò`÷Tº^E1ØàùÛ÷i§d¨Ù`I5»7á8Zéz0¥Ž’3Y7Êœ¦}eíÝΦIm?óbÙOâ-ŸäëŠgýhýR
Â3‘†y±è±/VŠ¤?Ïù4?’ÑûIÆLQ~DãŠ?Ôêð#N ]³böPK ZQamë š PK 5 -
What is the problem, how can I solve the problem?
thanks
If you don't care to keep the first 100 bytes, simply create 100 lengths of string, change some values and write it to the stream would be enough. Reading a file is not needed.
std::fstream fs("text.txt", ios_base::out | ios_base::binary);
string buffer(100, ' ');
string update="Hello";
buffer.replace(0, update.size(), update);
fs.seekp(20); // move to write position
fs.write(buffer.data(), buffer.size());
fs.close();
Use ios::trunc as the file open mode.
For more info check out this.

Converting C function to C++ language

Since this is my first encounter with the C programming language, it's not clear to me how I'm going to convert a piece of code to C++. I know that this code can be used in C ++ but I want to work exclusively on the syntax of the C++ language.
Here is my code:
FILE *f;
char name[10],surname[10],j[10];
f=fopen("Marks.txt","r");
fscanf(f,"%d",&n);
I want to open the file using:
ifstream input;
input.open("Marks.txt");
But then I don't know what to use instead of the fscanf function because I can no longer use FILE *f;
Like this:
int main()
{
// Let the constructor handle opening the file.
std::ifstream input("Marks.txt");
int n = 0;
std::string s;
double d = 0;
// Read an int, followed by a string, followed by a double.
if (input >> n >> s >> d)
{
std::cout << "Success!\n";
}
else
{
std::cout << "Failure!\n";
}
// The destruction of 'input' will close the file.
}
Here's the C++ way to do it, though you technically can still use that C code.
#include <ifstream>
int main() {
std::string str;
int i;
double d;
char c_str[10];
std::ifstream input;
input.open("Marks.txt");
input >> str; // reads a word of text into str
input >> i; // assuming there is a valid integer after the first line, reads it into i
input >> d; // assuming there is a valid double after that, reads it into d
// reads up to 9 characters + a '\0', stopping if it reaches a period
input.get(c_str, 10-1, '.');
// etc.
}
First to do is make a std::fstream object then open the file of your choice, you can do any lines (in sequence) of the following:
// Option 1
std::fstream input; // create the object
input.open("Marks.txt", ios::in); // since this is a `std::fstream` object, you'll need to specify `ios::in` for input operations
// Option 2
std::ifstream input; // create the object, this time dedicated to input
input.open("Marks.txt"); // no need to specify `ios::in`
// Option 3
std::fstream input("Marks.txt", ios::in); // you can directly open the file using the constructor, but specify `ios::in`
// Option 4
std::ifstream input("Marks.txt"); // directly opening the file using the constructor with the object dedicated to input
Next, you'll use operator>> or std::getline() to get input from the stream
// first declare the variables
std::string str1 = ""; // use std::string in C++ instead C-style strings (char[])
int ing1 = 0;
// Option 1
input >> str1; // this parses the contents of the file into str1, until the space
/*
Suppose "Marks.txt" has this inside it:
Hello World
The first content of the file until a space is "Hello", this string parsed into str1
*/
// Option 2
ing1 = input.get() // this parses only one character then turns it into an integer (destination type) into ing1
/*
Suppose "Marks.txt" has this inside it:
1234567890
ing1 will bear the value 1.
however, like std::iostream, this does not convert the character to it's integral value (ASCII, automatically) thus when:
abcdefghij
ing1 will have the value 0, since 'a' is not an integer
*/
// Option 3
input.getline(str1, 6); // this will parse into str1 six (6) characters, including spaces (not sure with control characters)
/*
Suppose "Marks.txt" has this inside it:
StackOverflow
"StackO" will be parsed into str1
*/
Note: this operations differ when stream is opened in binary mode (ios::binary) and be careful with std::getline() this may overload the buffer (especially when specified with std::numeric_limits<std::streamsize>::max())
EDIT: IMPORTANT close the stream after using.
// some operations here
// file is no longer needed -> close it
input.close();

C++ Can't write file with peek ; using fstream

I create in C++ a function that write in file, by using stream. I want that file was overwrite when i call this code. When i add a fstream.peak, to know the next char, nothing was written in my text file. If they return -1, I want they write at X position in my text file. Here's my code (note that I begin in C++..) Thanks for the future help! :)
fstream myFStream = myFStream.open("./myFile.txt, ios::in |ios::out | ios::trunc | ios::binary);
int positionFile = 2;
myFStream.seekp(positionFile, ios::beg);
char textToWrite[10] = "";
textToWrite = "mytext";
**// [don't write when I add this IF]
if (myFStream.peek() > 0)
{ positionFile += 15; }**
myFStream.write(textToWrite, 6);
myFStream.close();

Can't append text to specific position in C++

I'm trying to add text to a specific position in C++ with ofstream and seekp. However, it always append to the end of the file.
I've alredy tried to write with file.write(string, len), but the result is so the same.
My code:
void printHistory(int media, time_t timestamp){
ofstream file("history.json", ios::app);
long initial_pos = file.tellp();
file.seekp(initial_pos-3);
file << ", [" << timestamp << "," << media << "]]\n}";
file.close();
}
How about something like:
fstream fs ("fred.txt", ios::in | ios::out);
fs.seekg (0, ios::end);
streamoff filesize = fs.tellg();
fs.seekp (filesize - 3); // locate yourself 3rd char from end.
fs.write( "X", 1 );
fs.close();
Generally, to "insert" you have to write to a temporary stream or file. You cannot actively update in the middle.
Lots of STL types support insertion, but it is simulated via behind the scenes processes.
pseudo code:
pos = some_int_point_in_file
open(file) as f and open(tmp) as t:
read f into t until pos then
insert whatever
finishing reading the rest of f into t
swap file and tmp

Need some help understanding why wifstream buffer not being saved back to file

The following code does exactly what it's supposed to with one exception. The modified buffer content is not being save to the file. I have stepped through the code and I can see the buffer being changed so I'm not sure what's happening. Any comments would be appreciated.
bool replacestring(char *ifile, wstring& searchString, wstring& replacementString)
{
wstring buffer;
wifstream finout(ifile, ios_base::in | ios_base::out | ios_base::binary);
if(!finout.is_open())
{
cout << "Can not open file " << endl;
return(1);
}
while(getline(finout,buffer))
{
auto pos = buffer.find( searchString ) ;
while( pos != std::string::npos )
{
buffer.replace( pos, searchString.size(), replacementString ) ;
pos = buffer.find( searchString, pos + replacementString.size() ) ;
}
if(finout.bad())
perror("BAD READ");
}
finout.close();
return 0;
}
After you've copied some data from a stream into a buffer, that buffer is separate from the stream, and changes made to the buffer will not be reflected in the stream.
ifstream and wifstream are input streams, not output streams.
filebuf or wfilebuf might be what you want instead.
http://en.cppreference.com/w/cpp/io/basic_filebuf
Or Boost.Iostreams.
It might be easier to just write to a second file using an ofstream or wofstream. This would also avoid the risk of clobbering the existing file.
Similar question:
C++ - Find and replace in text file (standard system libraries)