Ojective: To open config file, look for a particular line which has tag and change its value
Example:
config .txt
bla bla
bla bla
SYSTEM_A_EXTERNAL_IP=192.168.0.57 // need to change ip address
bla bla
bla bla
What I have done so far: My code open the file and look for the particular line which has tag and change its value .
Problem: I failed to see those changes in the actual file. I am aware that ofstream will write into line but if I do ofstream instead of ifstream getline function gets an error.
Code1:
bool SetIpAddr(string & iAddr)
{
bool check= false;
// Open file
ifstream iFile(IpConfigFile.c_str(), ios_base::out|ios::app | ios::binary);
if(iFile.is_open())
{
check= true;
}
// Read content of ipconf file searching for the value of Head Id Name
if(true == check)
{
string TargetName = SystemAIdValue + ExternalIpNamePostfix+ ValueAssignmentCharacter;
string outbuf;
while( !iFile.eof() )
{
getline(iFile, outbuf);
// find the matching string
if( 0 == outbuf.compare(0,TargetName.size(),TargetName) )
{
outbuf.erase(outbuf.begin()+TargetName.size(), outbuf.end());
outbuf.insert(0+TargetName.size(), iAddr);
std::cout<< " after insertion " << outbuf << std::endl;
break;
}
}
}
// Close (input) file
if( iFile.is_open() )
{
iFile.close();
}
return check;
}
Code2: Also doesnt work.
bool SetIpAddr(string & aIpAddr)
{
bool lResult = false;
std::fstream ifile("platform_ip_config");
string lTargetIp = HeadAIdValue + ExternalIpNamePostfix+ ValueAssignmentCharacter;
std::deque<std::string>lines;
std::string inbuf;
while( std::getline(ifile, inbuf));
{
std::cout<<" we are in while"<<std::endl;
std::cout<<" getline =="<< inbuf<< std::endl;
std::cout<<" ip =="<<lTargetIp<< std::endl;
if( 0 == inbuf.compare(0,lTargetIp.size(),lTargetIp) )
{
std::cout<<" we are in matching"<<std::endl;
std::cout<< inbuf << std::endl;
inbuf.erase(inbuf.begin()+lTargetIp.size(), inbuf.end());
std::cout<<" after erase " << inbuf << std::endl;
inbuf.insert(0+lTargetIp.size(), aIpAddr);
std::cout<< " after insertinon " << inbuf << std::endl;
}
lines.push_back(inbuf);
}
ifile.seekg (0, ios::beg );
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(ifile, "\n"));
}
lines.push_back(inbuf);
}
ifile.seekg (0, ios::beg );
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(ifile, "\n"));
}
What you are doing is inherently tricky, writing to the middle of a file hoping the result will remain in place.
for example
192.168.120.111
uses up a lot more characters than
10.10.10.10
the way i would do this is read the whole files into lines.
std::fstream file(file_name);
std::deque<std::string> lines;
std::string temp;
while(std::getline(file, temp))
{
//detect that this the line you want
if(this_is_my_line(temp))
{
//do what you need to do to the string
modify(temp);
}
lines.push_back(temp);
}
file.seekg (0, ios::beg
//write back to file
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(file, "\n"));
Please note you do not need to explicitly close a file in C++, the RAII semantics will close it for you, by doing it your self your increasing the opportunity for bugs to creep into your code.
THIS WORKS ON MY SYSTEM
#include <iostream>
#include <fstream>
#include <string>
#include <deque>
#include <iterator>
int main()
{
std::string line;
const std::string token("SYSTEM_A_EXTERNAL_IP=");
std::deque<std::string> lines;
{
std::ifstream file("config.txt");
while(std::getline(file, line))
{
if(std::equal(token.begin(), token.end(), line.begin()))
{
line=token+"10.10.10.5"; //or whatever
}
lines.push_back(line);
}
}
{
std::ofstream file("config.txt");
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(file,"\n"));
}
return 0;
}
By using an ifstream you are opening the file for reading, if you use the fstream base class instead you should be able modify the file
Another approach is to read the entire file into a buffer, make changes to the buffer and overwrite the original file using the ofstream class
Related
I'm writing a program, which takes the lines of text to work with from the file, the name of which the user passes as an argument, e.g. program <name of the file>. But if the name is not provided, the input is taken dynamically from std::cin. What I've tried:
Redirecting the buffer (somewhy causes segfault)
if (argc == 2) {
std::ifstream ifs(argv[1]);
if (!ifs)
std::cerr << "couldn't open " << argv[1] << " for reading" << '\n';
std::cin.rdbuf(ifs.rdbuf());
}
for (;;) {
std::string line;
if (!std::getline(std::cin, line)) // Here the segfault happens
break;
Creating a variable, in which the input source is stored
std::ifstream ifs;
if (argc == 2) {
ifs.open(argv[1]);
if (!ifs)
std::cerr << "couldn't open " << argv[1] << " for reading" << '\n';
} else
ifs = std::cin; // Doesn't work because of the different types
for (;;) {
std::string line;
if (!std::getline(ifs, line))
break;
Now I'm thinking of doing something with file structures/descriptors. What to do?
UPD: I would like to have the possibility to update the input source in the main loop of the program (see below).
The seg fault in your first example is due to a dangling pointer; right after you call std::cin.rdbuf(ifs.rdbuf()), ifs is destroyed.
You should do what #NathanOliver suggests and write a function which takes an istream&:
#include <iostream>
#include <fstream>
#include <string>
void foo(std::istream& stream) {
std::string line;
while (std::getline(stream, line)) {
// do work
}
}
int main(int argc, char* argv[]) {
if (argc == 2) {
std::ifstream file(argv[1]);
foo(file);
} else {
foo(std::cin);
}
}
Hello stack overflow community. I came here as a last resort because i probably made a stupid mistake i cannot see myself.
The question im asking is for some reason when i try to read a file with an absolute path(or relative, you can see i tried that in my code) it cannot read the file for some unknown reason(atleast to me). This is a small thing for a big project im working on. Thank you guys!
main.cpp
#include <iostream>
#include <fstream>
#include <filesystem>
#include <unistd.h>
#include <string>
std::string openf() {
FILE* pipe = popen("zenity --file-selection", "r"); // open a pipe with zenity
if (!pipe) return "ERROR"; // if failed then return "ERROR"
char buffer[912]; // buffer to hold data
std::string result = ""; // result that you add too
while(!feof(pipe)) { // while not EOF read
if(fgets(buffer, 912, pipe) != NULL) // get path and store it into buffer
result += buffer; // add buffer to result
}
//I thought i needed to convert the absolute path to relative but i did not after all
// char cwd[10000];
// getcwd(cwd, 10000); // get cwd(current working directory)
// result = std::filesystem::relative(result, cwd); // convert the absolute path to relative with cwd
pclose(pipe); // cleanup
return result;
}
std::string readf(std::string filename){
std::string res;
std::ifstream file;
file.open(filename.c_str());
if(file.is_open()) {
while(file){
res += file.get();
}
}else {
std::cout << "failed to open file " + filename;
}
return res;
}
int main( void ){
std::string file = openf();
std::cout << file << std::endl;
std::string str = readf(file);
std::cout << str << std::endl;
return 0;
}
output
/home/meepmorp/Code/Odin/test/test.odin
failed to open file /home/meepmorp/Code/Odin/test/test.odin
It seems zenity, which you use as file chooser, outputs an extra newline after the file name, which you include in the name. In Linux, files can actually contain embedded newline characters in their name, and you actually try to open "test.odin\n" instead of "test.odin".
And thisI am trying to get the things written in a .txt file called CodeHere.txt and here is my main.cpp:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, const char * argv[]) {
string line;
string lines[100];
ifstream myfile ("CodeHere.txt");
int i = 0;
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
lines[0] = line;
i++;
}
myfile.close();
}
else cout << "Unable to open file";
cout << lines[0];
myfile.close();
return 0;
}
And the output is: Writing this to a file.Program ended with exit code: 0
But in my CodeHere.txt it has: hello
I tried saving it, but the result didn't change. I'm not sure whats going on. Can anyone help?
Are you sure that your .txt file is in the same repertory? To me, it just looks like you entered the path wrong. Try with the absolute path (full one). Another option is that you haven't saved the text file yet, you're just editing it, and so it is in fact empty, that would be why your cout doesn't print anything.
This should work, using a vector<string> to store the lines read from file
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
string line;
vector<string> lines;
ifstream myfile ("CodeHere.txt");
int i = 0;
if (myfile.is_open())
{
while ( getline(myfile, line) )
{
lines.push_back(line);
i++;
}
myfile.close();
}
else {
cout << "Unable to open file";
return -1;
}
cout << lines[0] << '\n';
return 0;
}
Try this:
vector<string> lines;
if (file.is_open()) {
// read all lines from the file
std::string line;
while (getline(file, line)) {
lines.emplace_back(line);
}
file.close();
}
else {
cout << "Unable to open file";
return -1;
}
cout << "file has " << lines.size() << " lines." << endl;
for (auto l : lines) {
cout << l << endl;
}
I feel like I've tried everything, I can get the first file to append to the second but cannot get the second file into a third. What am I doing wrong?
To be clear I need to take one file, append it to a second file, then put the contents of that second file into a third. I was able to simulate this outcome by putting both files into strings and then putting those strings into a third file, but that's not 'correct' in this problem.
I'm not particular to any way or any technique, I've tried a few and nothing works. This is the latest attempt, still doesn't work for the last step.
Here's my code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string a,b,c;
cout << "Enter 3 file names: ";
cin >> a >> b >> c;
fstream inf;
ifstream two;
fstream outf;
string content = "";
string line = "";
int i;
string ch;
inf.open(a, ios::in | ios:: out | ios::app);
two.open(b);
outf.open(c, ios::in);
//check for errors
if (!inf)
{
cerr << "Error opening file" << endl;
exit(1);
}
if (!two)
{
cerr << "Error opening file" << endl;
exit(1);
}
if (!outf)
{
cerr << "Error opening file" << endl;
exit(1);
}
for(i=0; two.eof() != true; i++)
content += two.get();
i--;
content.erase(content.end()-1);
two.close();
inf << content;
inf.clear();
inf.swap(outf);
outf.close();
inf.close();
return 0;
Here's an idea:
#include <fstream>
using namespace std;
void appendf( const char* d, const char* s )
{
ofstream os( d, ios::app );
if ( ! os )
throw "could not open destination";
ifstream is( s );
if ( ! is )
throw "could not open source";
os << is.rdbuf();
}
int main()
{
try
{
appendf( "out.txt", "1.txt" );
return 0;
}
catch ( const char* x )
{
cout << x;
return -1;
}
}
I want to read data from a txt file, but i am not able to get it. I am new to c++.
Here is my code, but it does not work. I used getline(),
ifstream inFile;
string sPassWord;
inFile.open("QdatPassWordconfig.config");
inFile.seekg(0,ios::end);
int length=inFile.tellg();
if (inFile.is_open())
{
while (!inFile.eof())
{
getline(inFile,sPassWord);
cout<<sPassWord<<endl;
}
cout<<"get data from txt file"<<endl;
// here ,I cannot read data from file
cout<<sPassWord<<endl;
}
if(!inFile.is_open() || length==0)
{
cout<<"file is create or write"<<endl;
sPassWord="BdsWUjT26";
ofstream outFile;
outFile.open("QdatPassWordconfig.config");
outFile<<sPassWord<<endl;
outFile.close();
}
inFile.close();
cout<<sPassWord<<endl;
It isn't clear if you are trying to read the first line of the file, the last line of the file, or all the lines of the file. Here program snippets for each possibility:
To read the first line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
if(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n"
}
}
To read all of the lines of the file:
// TESTED
#include <iostream>
#include <fstream>
#include <string>
int main ()
{
std::ifstream inFile("QdatPassWordconfig.config");
std::string sPassWord;
while(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
}
}
To read the last line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
int lineCount = 0;
while(std::getline(inFile, sPassWord)) {
lineCount++;
}
if(lineCount) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n";
}
}
inFile.seekg(0,ios::end);
int length=inFile.tellg();
1.You forgot seek back to the beginning. Like this:
inFile.seekg(0,ios::end);
int length=inFile.tellg();
inFile.seekg(0,ios::beg);
2.You need to practice on your if and else statement.
3.Don't use std::ifstream::eof. Use std::getline.
Do something like this:
// Declare local variables
std::ifstream inFile;
std::string sPassword = "";
::UINT length = 0;
// Attempt to open file
inFile.open( "QdatPassWordconfig.config" );
// Use your if and else statement like this:
// Is inFile open?
if( inFile.is_open( ) )
{
// Read file line by line using std::getline
while( std::getline( inFile, sPassword ) ) {
// Print sPassword
std::cout << sPassword << std::endl;
}
// Done with inFile, close it
inFile.close( );
}
else
{
// Do whatever if inFile can't be open
}
There are so many errors with your code, so I decided to show you how I would have done it (please do read the comments):
void Example( void )
{
// DECLARATION
bool bInputMode = true;
std::fstream ioFile;
::UINT nFileSize = 0;
std::string strPassword = "";
// INITIALIZATION
// *Open or create ioFile
// ioFile can now do both input and output operations
ioFile.open( "Passwords.pw",
std::fstream::in |std::fstream::out | std::fstream::app );
// *Calculate/set the value of bInputMode
// first, calculate the size of the file
// if the size of the file is = 0,
// bInputMode = false - which means to be in output mode
ioFile.seekg( 0, std::ios::end );
if( ( nFileSize = ioFile.tellg( ) ) = 0 )
bInputMode = false;
ioFile.seekg( 0, std::ios::beg );
// DO WHATEVER
// *Since bInputMode == true,
// we shall read each line from ioFile by using std::getline
if( bInputMode )
{
// *Get each line within ioFile and "copy" it to strPassword
// and then print strPassword
// *With std::getline, we could get the spaces
while( std::getline( ioFile, strPassword ) )
std::cout << strPassword << std::endl;
}
// *Since bInputMode == false,
// we shall create a new from ioFile and then write to it
else
{
std::cout << "Creating/writing a new file..." << std::endl;
strPassword = "Password123";
ioFile << strPassword << std::endl;
}
// CLEAN-UP
// We are done with ioFile, close it.
ioFile.close( );
};
Please point out any errors! Some feedback and suggestions would be great as well.