How to read file in c++ using environment variable - c++

I want to read a file contents in C++ program which I have written inside a dll file. Right now I have hardcoded the path, but I want the path to be either dynamic or I should be able to use thru environment variable so I can either specify the path or the folder directly. I am using if stream in C++.Is there any way to do it
What I tried
if(const char* env_p = std::getenv("userdata"))
std::cout << "Your PATH is: " << env_p <<'\n';
std::vector<std::string> v;
string line;
//ifstream Myfile("C:\\Program Files\\Folder1\\users.txt"); working as its has hardcoded path
ifstream Myfile("users.txt");--- not working
ifstream Myfile(%userdata%);--- not working
while(!Myfile.eof())
{
while(getline(Myfile,line))
v.push_back(line);
cout <<endl;
cout <<"User in the file"<<endl;
for(auto i:v)
cout << i<<endl<<endl;
Myfile.close();
}

Related

Finding a string inside all subdirectories

I try to code a program that behaves like grep -r function. So far I can list all the subdirectories and folders inside of them recursively but what i need to do is to find a string inside all of these files and record them in a .log file. I am building with CMake on Ubuntu. The program compiles fine but probably I have something wrong with this function.(it basically saves the values found in a log file)
It's supposed to put inside the log file the following->
Directory:(line number):(the full line)
After the changes, the function works fine, I can see the directories and the line number of the searched word. The problem now is that I cannot see the line in the .log file, it shows in binary and not as a string. Do anyone know the reason ?
void showing_all_files(std::string path, std::string search)
{
std::ofstream log_file;
log_file.open("grep_ex.log");
for (const auto & entry : fs::recursive_directory_iterator(path))
{
int line_no = 0;
string line;
ifstream infile(path);
while(getline(infile, line))
{
++line_no;
auto pos = line.find(search);
if(pos != string::npos)
{
log_file << entry << ":" << line_no << ":" << line << endl;
}
}
// log_file << entry.path() << std::endl;
}
log_file.close();
}
ifstream infile(path); Should be ifstream infile(entry.path());.

Can't able to find a keyword in a File

When I try to Find a Keyword from the GetLine() Function It only Returns a Empty String. But when I try to print the Line with std::cout, it prints everything, so i debugged the solution I found that the String is empty but std::cout somehow manages to print the lines in file.
std::ifstream file(fileToSearch);
std::string line;
cout << endl << keyWords[i];
while (std::getline(file, line)) {
cout << endl << keyWords[i]<<" ";
cout << line;
if (auto pos = line.find(keyWords[i]) != std::string::npos) {
// std::stringstream iss(line.substr(pos + keyWords[i].size()));
cout << endl << "found again in String Table" << endl;
//iss >> j;
break;
}
}
This is the data in the File
%Checking Windows(R) Installer VersionConfiguring Windows InstallerConfiguring %sĀ½Setup has completed configuring the Windows Installer on your system. The system needs to be restarted in order to continue with the installation. Please click Restart to reboot the system.%s
When I checked the Encoding of the file in Notepad++. I found that the file is not encoded at all , but when I changed the file to UTF-8 I can get the Value and Search It Successfully. Is there anyway to do this by code rather than changing it Manually??

Why i can't use Windows Environment path with ofstream to write a text file?

Why i can't use Windows Environment path shortcut with ofstream to write a sample text file ?
\\ C:\Users\Me\AppData\Local\Temp\Test.txt
std::string Path = "%Temp%\\Test.txt"
ofstream myfile;
myfile.open (Path);
if (!myfile.is_open())
{
cout << "Could not create temp file." << endl;
}
myfile << "Hello World";
myfile.close();
myfile.is_open() always return false, also "%%Temp%%" and "\%Temp\%" not working.
I can get Temp path by Windows API, but i don't want to use API in this application.
Thank you
The %Temp% substitution is something done by some Windows programs, not by the C++ runtime. If you want to do this, just retrieve the environment variable yourself and build up a path. Something like this'll do it, but you'll want to add some error checking:
ostringstream tempfilepath;
tempfilepath << getenv("Temp") << '/' << "Test.txt";
ostream myFile;
myFile.open(tempfilepath.str());
...etc...

ifstream not working with variable parameter using C++11 and c_str() appended

Note: I am using the C++11 standard, so I don't see why this isn't working with or without c_str() appended.
I have the following code:
// open streams
ifstream in(input);
ofstream out(output);
// get which file to open
in.ignore(INT_MAX, ':'); // we don't need the beginning part
in.ignore(); // remove trailing whitespace
string fileLocation;
getline(in, fileLocation);
out << "Loading: " << fileLocation << endl;
cout << "Loading: " << fileLocation << endl;
// now that we know where the file is, load it:
ifstream file(fileLocation);
which reads from a file that looks vaguely like this
File: file.txt
(Subcommands below)
I know that I am pulling the correct filename because of the terminal output.
Anyway, I noticed that the stream wasn't opening properly, so I added this conditional to check:
if ( !file )
{
cout << "File wasn't loaded properly." << endl;
}
And sure enough, I see that message when running the program.
My question is this: how come, when I hard-code the file location, e.g. ifstream file("file.txt") it opens up no problem? How do I get this working properly?

ifstream opens files named by cin but not when pulled from an array. Any difference between cin and a regular string definition?

TL;DR File names stored as strings in array (using new) - ifstream won't open them (perror returns "No such file or directory"). Swap out array variable with a call to the user to name the file (using cin) - ifstream opens the file. Why? How do I get the array to work?
Things to Know
All files exist in folders with naming scheme run20### where
All files are named S20###.ABC where ### is the same from the parent directory and ABC can go from 001-999. These are all text files (there are no .txt extensions though) that CAN be opened by ifstream and getline.
I'm writing a program that's going to pull information from up to 150 files. An early version I wrote had the user input the file name (using cin). ifstream took the stored name and opened the file successfully every time. Obviously, I don't want to type 150 file names in so the program stores all of the file names as strings in an array for the program to pull from. However, when it goes to open the file (in the correct path and with the correct file name and extension), the error I get from perror returns "No such file or directory." If I just do a quick swap of the variables though so that the file name comes from cin, the file opens. Why would cin work and the array version not? Is there any way to get the array to work?
I've also tried something similar where there is no array. Instead, in the for loop that would pull the files from the array, the file gets named each time.
Here's the code (sorry about the headers, couldn't get it to format right):
#include <iostream>
#include <array>
#include <string>
#include <ctime>
#include <cstring>
#include <fstream>
#include <sstream>
using namespace std;
int main() {
//--------------------------Initial setup----------------------------------
cout << "Please give the full name of the folder you would like to open in the /Users/lucas/HPS/TDCData directory" << endl << endl;
string sFolderName;
cin >> sFolderName;
// Create path. I have mine here but you'll have to change it to something you'll
// use if you want to run the code
string sPathName = "/Users/lucas/HPS/TDCData/" + sFolderName;
//----------------Create file name array------------------------------------
// Get naming base from the folder name given
string sFileBase = "S20";
for (int i = 5; i <= sFolderName.length(); i++){
sFileBase = sFileBase + sFolderName[i];
}
//Specify range since different directories have different numbers of files
cout << "Files must be named S20###.ABC" << endl;
cout << "Specify a range for ABC" << endl;
int iFloor;
int iCeiling;
cout << "Floor: " << endl;
cin >> iFloor;
cout << "Ceiling: " << endl;
cin >> iCeiling;
// Define an array to store names and then store them
string *aFiles;
int iFilesSize = iCeiling - iFloor + 1;
aFiles = new string [iFilesSize];
cout << "Array created" << endl;
for (int i = iFloor; i <= iCeiling; i++){
string name = sFileBase;
if (i < 10){
name = name + ".00" + to_string(i);
}
else if (i < 100) {
name = name + ".0" + to_string(i);
}
else {
name = name + '.' + to_string(i);
}
aFiles[i-1] = name;
}
//----------------Open each file in aFiles----------------------
for (int i = 0; i < iFilesSize; i++){
// There are two important lines of code here. The first gets sFileName from
// aFiles. The second gets sFileName from user input using cin (this is commented out).
// Obviously, none of the last section of code is needed for the second line to work.
// The first line does not work for me. The second does.
string sFileName;
//First
sFileName = aFiles[i];
//Second
//cin >> sFileName
string sFullPath = sPathName + "/" + sFileName;
cout << "Searching ... " << sFullPath << endl << endl;
//Open file
ifstream inputFile(sFullPath);
//Check that the file opened
if (! inputFile.is_open()) {
cout << "Error reading" << sFullPath << endl;
perror("Error is: ");
return 0;
}
else {
cout << "File opened successfully..." << aFiles[i] << endl << endl;
}
}
cout << "All files opened..." << endl << endl;
return 0;
}
Also here's a link to a zip of one of the directories for any tests someone might want to run. Thanks for any and all help!
It looks like you start filling aFiles from index iFloor, while you start reading aFiles from index 0.
How about changing aFiles[i-1] = name; to aFiles[i-iFloor] = name;
"TL;DR File names stored as strings in array (using new)"
Don't do this. Use a dynamic container like std::vector<std::string> instead.
"- ifstream won't open them (perror returns "No such file or directory")."
Use the debugger to check what's actually passed to the
ifstream inputFile(sFullPath);
with sFullPath.
"Swap out array variable with a call to the user to name the file (using cin) - ifstream opens the file. Why? How do I get the array to work?"
You cannot replace the behaviors of a stream getting values as you're trying with the array.
The best way to make the input stream source transparent, is to simply use a std::istream reference, and don't care if it's std::cin or e.g. a std::istringstream reference.
The std::string instance needed to initialize the mentioned std::istringstream can be build e.g. using a std::ostringstream and pass the str() property to the std::istringstream constructor.