How to create files corresponding to program location? - c++

Is there a way to create files on a computer using C++ and the location of the C++ program? I want to be able to use this program on multiple computers yet each computer has its own different directory. For example if I want to create test.txt file located on the user directory is there a way to put the path of the file corresponding to the program file's location because "user" differs on the name of the user.

as long as you are on windows you can use the API GetUserName then use SetCurrentDirectory API to change working directory then create your file there using CreateFile or fstream:
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ULONG len = 50;
LPSTR lpBuffer = (LPSTR)GlobalAlloc(GPTR, len);
GetUserName(lpBuffer, &len);
cout << lpBuffer << endl;
// don't forget to clean when you're done:
string str = "C:\\Users\\";
str += lpBuffer;
str += "\\test.txt";
cout << str << endl;
ofstream out(str.c_str());
if(out.fail())
perror("Opening failed");
out << "Hello " << lpBuffer;
out.close();
GlobalFree(lpBuffer);
GlobalFree(lpBuffer);
return 0;
}
this program gets the current username and creates file inside its folder and writes in it "Hello" 'yourusername'

Related

Passing a value while writing inside a file:C++

I need to pass the value of one of the variables(containing the value of a path) to the contents of the file I am writing. The file outfile is of type ".ctl"
Lets say the file "outfile.ctl" gets created at location /abc/xyz
so I will be having /abc/xyz/outfile.ctl at this location. Now inside outfile.ctl file I have written some context. If you see the contents carefully I have included the line: file <<"file='filepath/Trial.data'\n"; which creates another file with the name Trial.data in the location filepath.Lets says filepath = /pqr/stu. So Ideally after the outfile.ctl file compiles I should have trial.data created at /pqr/stu llocation. I want to achieve this by the system command. But not getting the desired result created.Elaborated code is below
Snippet of the code.
void somefunc()
{
fstream file_1;
char outfile1[120],
filename[50] = "/abc/xyz/outfile.ctl";
char filepath[50] = "/pqr/stu/;
strcpy(outfile1, filename);
cout << outfile1;
cout << "\n";
file_1.open(outfile1, ios::out);
if (file_1) {
file_1 << "export\n";
file_1 << "client=000\n";
file_1 << "file='" << filepath << "/Trial.data'\n";
file_1 << "delete from BDRGIN\n";
file_1 << "select * from BDRGIN\n";
file_1.close();
system("R3trans outfile1");
}
Ideally the last line should create the trial data file in /pqr/stu/ folder but it doesnt. In my case it doesnot happen so , and a file outfile_1(without file extension) gets created in the folder where I am running the .cpp script. Can someone help?
It's not hard
file << "file='" << filepath << "/Trial.data'\n";
In C++ variables don't get substituted inside strings (unlike some scripting languages).
EDIT
You have basically made the same mistake again with your system command, variables don't get substituted inside strings. If you need a string variable which is made from other string variables you have to build up the string using strcpy and strcat. Try it like this
char cmd[250];
strcpy(cmd, "R3trans ");
strcat(cmd, outfile1);
cout << cmd << "\n"; // for testing
system(cmd);
You are missing a couple of things which I added:
You didn't include the output filename and filepath variables into your code, you didn't post all of your code to make in compilable.
Below is the code with "current path" (which we obtain with cwd in Linux) and your filename, included into your file "Trial.data" and written to the "current path/Trial.data" in you compile directory.
#include <iostream>
#include <fstream>
#include <string.h> //for strcat to concatinate the two (filepath+filename)
#include <unistd.h> //for getcwd to obtain your 'current path'
using namespace std;
int main(){
fstream file;
char cwd[256];
char *filepath= {getcwd(cwd, sizeof(cwd))}; // or write your path here instead
char filename[15] = "/Trial.data";
strcat(filepath, filename);
file.open(filepath,ios::out);
if(!file){
cout<<"File creation failed";
} else {
cout<<"New file created";
file <<"export\n";
file <<"client=000\n";
file <<"file='" << filepath << "'\n";
file <<"select * from HTTPURLLOC\n";
file.close(); // Step 5: Closing file
}
return 0;
}

Why doesn't this open the file in the directory of the program?

I have this short program:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char * argv[]) {
std::string homedir = std::getenv("HOME");
std::string filename = argc > 1 ? argv[1] : (homedir + "/" + "file");
std::cout << homedir << std::endl;
std::cout << filename << std::endl;
std::fstream file;
file.open(filename, std::ios::out);
file << "Yo yo waddup" << std::endl;
file.close();
return 0;
}
When I supply no arguments, it opens a file in the users home directory. That of course makes sense. But when I run it from a different directory like this:
$ ./folder/hometest examplefile
The program creates "examplefile" in my current directory instead of the directory where the program is.
Why exactly is this happening?
Why exactly is this happening?
The program is behaving just as expected.
The file is opened relative to the current work directory, not where the executable is located.
If it didn't work that way,
All your programs will have to work with absolute paths, or
The location of the program will be flooded with files. First, that might not be possible because of permissions issue. Second, in a multi-user system, users will end up trying to create the same file names/directories.
Neither of the above is desirable.

How to get the absolute path of the desktop for the calling user on Windows

How can I get the absolute path to the desktop for the user that is starting my program?
int main () {
ofstream myfile;
myfile.open ("C:\\Users\\username\\Desktop\\example.txt");
myfile << "Writing this to a file" << endl;
myfile.close();
}
Edited : as Remy Lebeau suggested
I want to get absolute path to desktop for every computer starting program?
If you are in windows you need to use the API SHGetFolderPath function, click here for more informations.
When you get the path of the desktop you will need to combine (append) it with your file name, the generated path will represents the full path of the file wich is situated in the desktop, there is the full code:
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <shlobj.h> // Needed to use the SHGetFolderPath function.
using namespace std;
bool GetDesktopfilePath(PTCHAR filePath, PTCHAR fileName)
{
// Get the full path of the desktop :
if (FAILED(SHGetFolderPath(NULL,
CSIDL_DESKTOPDIRECTORY | CSIDL_FLAG_CREATE,
NULL,
SHGFP_TYPE_CURRENT,
filePath))) // Store the path of the desktop in filePath.
return false;
SIZE_T dsktPathSize = lstrlen(filePath); // Get the size of the desktope path.
SIZE_T fileNameSize = lstrlen(fileName); // Get the size of the file name.
// Appending the fileName to the filePath :
memcpy((filePath + dsktPathSize), fileName, (++fileNameSize * sizeof(WCHAR)));
return true;
}
int main()
{
ofstream myFile;
TCHAR filePath[MAX_PATH]; // To store the path of the file.
TCHAR fileName[] = L"\\Textfile.txt"; // The file name must begin with "\\".
GetDesktopfilePath(filePath, fileName); // Get the full path of the file situated in the desktop.
myFile.open(filePath); // Opening the file from the generated path.
myFile << "Writing this to a file" << endl;
myFile.close();
return 0;
}

Saving a file in a different place for linux

I am trying to save a file somewhere else than the folder of the exe. I have pieced together this unelegant way:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
using namespace std;
int main() {
//getting current path of the executable
char executable_path[256];
getcwd(executable_path, 255);
//unelegant back and forth conversion to add a different location
string file_loction_as_string;
file_loction_as_string = executable_path;
file_loction_as_string += "/output_files/hello_world.txt"; //folder has to exist
char *file_loction_as_char = const_cast<char*>(file_loction_as_string.c_str());
// creating, writing, closing file
ofstream output_file(file_loction_as_char);
output_file << "hello world!";
output_file.close();
}
Is there a more elegant way to do this? So that the char-string-char* is not necessary.
Also is it possible to create the output folder in the process apart from mkdir?
Thank you
You can get rid of 3 lines of code if you use the following.
int main()
{
//getting current path of the executable
char executable_path[256];
getcwd(executable_path, 255);
//unelegant back and forth conversion to add a different location
string file_loction_as_string = string(executable_path) + "/output_files/hello_world.txt";
// creating, writing, closing file
ofstream output_file(file_loction_as_string.c_str());
output_file << "hello world!";
output_file.close();
}

Problems formatting arrays and strings in C++

I'm having a simple problem that's been driving me nuts all day. I am trying to open a file on the current user's Desktop without knowing the current user's name.
The idea is that I would use the GetCurrentUser call to the API to get the user name. Then format a string to give the full path directory, and pass that variable into fopen to open the file. Here is the code I'm working on, I get no compiler errors and it compiles fine but nothing writes to the file.
int main() {
char pathName[200]; // declaring arrays
char userName[100];
DWORD userNameSize = sizeof(userName); // storage for user name
if (!GetUserName(userName, &userNameSize)) { cout << "user not found"; }
else { cout "hello" << userName;} // error checking
// format for Windows 7 desktop
sprintf(pathName, "\"C:\\Users\\%s\\Desktop\\text.txt\"", userName);
cout << pathName << "\n"; // confirms correct location
const char* fileLocation = pathName; // pointer to full path to pass into fputs
const char* test = "test"; // test information to write to file to confirm
FILE *f = fopen(fileLocation,"a+"); // open file in append mode
fputs(test, f); // write to file
fclose(f); // flush and exit
return 0;
}
Maybe I need to use a different call to format the string? Or declare fileLocation as a different variable type?
I'm fairly new to C++ and would appreciate any tips that would help me to be able to open a file on the current user's Desktop. Thanks.
EDIT IN RESPONSE TO JERRY'S ADVICE:
This is what my latest comment was referring to:
#include <iostream>
#include <cstring>
#include <string>
#include <conio.h>
using namespace std;
string location ("C:\\Users\\testuser\\Desktop\\log.dat");
char cstr = char* [location.size()]; //This is a problematic line
strcpy (cstr, location.c_str());
void write(const char* c)
{
const char* fileLocation = cstr;
//const char* fileLocation = g_pathName;
FILE *f = fopen(fileLocation,"a+"); // This is the problematic line right here.
if(f!=NULL)
{
fputs(c,f); // append to end of file
fclose(f); // save so no entries are lost without being flushed
}
}
int main ()
{
write("test");
cout << "done";
_getch();
return 0;
}
You have a missing semicolon at line 9 where it says:
...{ cout << "user not found" }...
Semicolons are not optional in C++, you need them for a working program. Also, as stated in the comments, you do not need quotes around the name of the file.
I'd use SHGetSpecialFolderPath from shlobj.h:
const char *szFileName = "text.txt";
const char *szContent = "test string";
char szPath[_MAX_PATH];
SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE);
strcat(szPath, "\\");
strcat(szPath, szFileName);
FILE *pFile = fopen(szPath, "a+");
if(pFile != NULL)
{
fputs(szContent, pFile);
fclose(pFile);
}
I would use SHGetKnownFolderPath with FOLDERID_Desktop to get the path to the desktop, then add a file name to the end. You also almost certainly want to do the manipulation on std::strings, then when you've created the full name, use the .c_str member function to retrieve the name as a C-style string. Unless you have a really specific reason to do otherwise, you're probably better off using a std::ofstream instead of a C-style FILE * as well (and in that case if your compiler is current, you can probably pass the std::string object directly as the name).
Edit: some quick demo code creating and writing to a file on the user's desktop:
#include <windows.h>
#include <Shlobj.h>
#include <objbase.h>
#include <string>
#include <fstream>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "shell32.lib")
std::string GetKnownFolderPath(REFKNOWNFOLDERID f) {
PWSTR sys_path;
SHGetKnownFolderPath(f, 0, NULL, &sys_path);
DWORD size = WideCharToMultiByte(CP_ACP, 0, sys_path, -1, 0, 0, NULL, NULL);
std::string path(size, ' ');
WideCharToMultiByte(CP_ACP, 0, sys_path, -1, &path[0], size, NULL, NULL);
// We're finished with the string the system allocated:
CoTaskMemFree(sys_path);
// WideCharToMultiByte leaves space for a NUL terminator we don't need
path.resize(path.size()-1);
return path;
}
int main() {
std::string path(GetKnownFolderPath(FOLDERID_Desktop));
path += "\\test.txt";
std::ofstream test(path.c_str());
test << "This is a test";
return 0;
}