How do I find the current directory? - c++

I am trying to read a file which I read previously successfully.
I am reading it through a library, and I am sending it as-is to the library (i.e. "myfile.txt").
I know that the file is read from the working/current directory.
I suspect that the current/working directory has changed somehow.
How do i check what is the current/working directory?

Since you added the visual-c++ tag I'm going to suggest the standard windows function to do it. GetCurrentDirectory
Usage:
TCHAR pwd[MAX_PATH];
GetCurrentDirectory(MAX_PATH,pwd);
MessageBox(NULL,pwd,pwd,0);

Boost filesystem library provides a clean solution
current_path()

Use _getcwd to get the current working directory.

Here's the most platform-agnostic answer I got a while ago:
How return a std::string from C's "getcwd" function
It's pretty long-winded, but does exactly what it's supposed to do, with a nice C++ interface (ie it returns a string, not a how-long-are-you-exactly?-(const) char*).
To shut up MSVC warnings about deprecation of getcwd, you can do a
#if _WIN32
#define getcwd _getcwd
#endif // _WIN32

This code works for Linux and Windows:
#include <stdio.h> // defines FILENAME_MAX
#include <unistd.h> // for getcwd()
#include <iostream>
std::string GetCurrentWorkingDir();
int main()
{
std::string str = GetCurrentWorkingDir();
std::cout << str;
return 0;
}
std::string GetCurrentWorkingDir()
{
std::string cwd("\0",FILENAME_MAX+1);
return getcwd(&cwd[0],cwd.capacity());
}

Related

Unicode output not showing

I'm trying to learn Unicode programming in Windows.
I have this simple program:
#include <iostream>
#include <string>
int main()
{
std::wstring greekWord = L"Ελληνικά";
std::wcout << greekWord << std::endl;
return 0;
}
However, it outputs nothing. Any ideas how to make it output Greek?
I tried adding non-Greek letters, and that didn't work quite right either.
The first thing to try is to make the program not dependent on the encoding of the source file. So use Unicode escapes not literal Unicode letters
std::wstring greekWord = L"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC";
Having the incorrect encoding in the source file is only one thing of many things that could be preventing you from printing Greek. The other obvious issue is the ability of your terminal to print Greek letters. If it can't do that, or needs to be set up correctly so that it can then nothing you do in your program is going to work.
And probably you want to fix the source code encoding issue, so that you can use unescaped literals in your code. But that's dependent on the compiler/IDE you are using.
If you are outputting your cout to a normal console then the console doesn't usually support unicode text like greek, try setting it up for unicode text or find another way to output your data, like txt files or some gui,
There are two way to do this.
The old, non-standard Microsoft way is as follows:
#include <fcntl.h>
#include <io.h>
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stdin), _O_WTEXT);
// your code here
}
You will fild this everywhere, but this is not necessarily a good way to solve this problem.
The more standards-compliant way is as follows:
#include <locale>
int main()
{
std::locale l(""); // or std::locale l("en_US.utf-8");
std::locale::global(l); // or std::wcout.imbue(l); std::wcin.imbue(l);
// your code here
}
This should work with other modern compilers and operating systems too.
TRY this it works with me :
#include
#include <io.h>
#include <fcntl.h>
using namespace std;
int main() {
_setmode(_fileno(stdout),_O_U16TEXT);
wcout<<L"Ελληνικά";
setlocale(LC_ALL,"");
return 0;
}

file systems in C++

I'm working on a project in which I have to do some file handling.
If only someone could tell how to work with file system like
moving, copying, deleting, renaming and checking for the existence of files in Windows.
Check file management functions section on msdn.
For example, to copy a file with WinAPI you can use CopyFile:
#include <windows.h>
#include <iostream>
int main()
{
BOOL ret = CopyFile(TEXT("test.txt"), TEXT("test-copy.txt"), TRUE);
if (ret)
std::cout << "CopyFile failed. GetLastError:" << GetLastError() << std::endl;
}
If your compiler supports you may as well use std::filesystem which is portable (e.g. that code should work equally well on windows and linux):
#include <filesystem>
int main()
{
std::filesystem::copy("test.txt", "test-copy.txt");
}
There is also boost::filesystem that heavily influenced std::filesystem.

Create a directory if it doesn't exist

In my app I want to copy a file to the other hard disk so this is my code:
#include <windows.h>
using namespace std;
int main(int argc, char* argv[] )
{
string Input = "C:\\Emploi NAm.docx";
string CopiedFile = "Emploi NAm.docx";
string OutputFolder = "D:\\test";
CopyFile(Input.c_str(), string(OutputFolder+CopiedFile).c_str(), TRUE);
return 0;
}
so after executing this, it shows me in the D:HDD a file testEmploi NAm.docx
but I want him to create the test folder if it doesn't exist.
I want to do that without using the Boost library.
Use the WINAPI CreateDirectory() function to create a folder.
You can use this function without checking if the directory already exists as it will fail but GetLastError() will return ERROR_ALREADY_EXISTS:
if (CreateDirectory(OutputFolder.c_str(), NULL) ||
ERROR_ALREADY_EXISTS == GetLastError())
{
// CopyFile(...)
}
else
{
// Failed to create directory.
}
The code for constructing the target file is incorrect:
string(OutputFolder+CopiedFile).c_str()
this would produce "D:\testEmploi Nam.docx": there is a missing path separator between the directory and the filename. Example fix:
string(OutputFolder+"\\"+CopiedFile).c_str()
#include <experimental/filesystem> // or #include <filesystem> for C++17 and up
namespace fs = std::experimental::filesystem;
if (!fs::is_directory("src") || !fs::exists("src")) { // Check if src folder exists
fs::create_directory("src"); // create src folder
}
Probably the easiest and most efficient way is to use boost and the boost::filesystem functions. This way you can build a directory simply and ensure that it is platform independent.
const char* path = _filePath.c_str();
boost::filesystem::path dir(path);
if(boost::filesystem::create_directory(dir))
{
std::cerr<< "Directory Created: "<<_filePath<<std::endl;
}
boost::filesystem::create_directory - documentation
Here is the simple way to create a folder.......
#include <windows.h>
#include <stdio.h>
void CreateFolder(const char * path)
{
if(!CreateDirectory(path ,NULL))
{
return;
}
}
CreateFolder("C:\\folder_name\\")
This above code works well for me.
_mkdir will also do the job.
_mkdir("D:\\test");
https://msdn.microsoft.com/en-us/library/2fkk4dzw.aspx
OpenCV Specific
Opencv supports filesystem, probably through its dependency Boost.
#include <opencv2/core/utils/filesystem.hpp>
cv::utils::fs::createDirectory(outputDir);
Since c++17, you can easily do this cross-platform with:
#include <filesystem>
int main() {
auto created_new_directory
= std::filesystem::create_directory("directory_name");
if (not created_new_directory) {
// Either creation failed or the directory was already present.
}
}
Note, that this version is very useful, if you need to know, whether the directory is actually newly created.
And I find the documentation on cppreference slightly difficult to understand on this point: If the directory is already present, this function returns false.
This means, you can more or less atomically create a new directory with this method.
Use CreateDirectory (char *DirName, SECURITY_ATTRIBUTES Attribs);
If the function succeeds it returns non-zero otherwise NULL.
You can use cstdlib
Although- http://www.cplusplus.com/articles/j3wTURfi/
#include <cstdlib>
const int dir= system("mkdir -p foo");
if (dir< 0)
{
return;
}
you can also check if the directory exists already by using
#include <dirent.h>
This works in GCC:
Taken from:
Creating a new directory in C
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat st = {0};
if (stat("/some/directory", &st) == -1) {
mkdir("/some/directory", 0700);
}

How do i open a file when you know only part of the file name? C++

I need to be able to open a file when i only know part of the file name. i know the extension but the filename is different every time it is created, but the first part is the same every time.
You'll (probably) need to write some code to search for files that fit the known pattern. If you want to do that on Windows, you'd use FindFirstFile, FindNextFile, and FindClose. On a Unix-like system, opendir, readdir, and closedir.
Alternatively, you might want to consider using Boost FileSystem to do the job a bit more portably.
On a Unix-like system you could use glob().
#include <glob.h>
#include <iostream>
#define PREFIX "foo"
#define EXTENSION "txt"
int main() {
glob_t globbuf;
glob(PREFIX "*." EXTENSION, 0, NULL, &globbuf);
for (std::size_t i = 0; i < globbuf.gl_pathc; ++i) {
std::cout << "found: " << globbuf.gl_pathv[i] << '\n';
// ...
}
return 0;
}
Use Boost.Filesystem to get all files in the directory and then apply a regex (tr1 or Boost.Regex) to match your file name.
Some code for Windows using Boost.Filesystem V2 with a recursive iterator :
#include <string>
#include <regex>
#include <boost/filesystem.hpp>
...
...
std::wstring parent_directory(L"C:\\test");
std::tr1::wregex rx(L".*");
boost::filesystem::wpath parent_path(parent_directory);
if (!boost::filesystem::exists(parent_path))
return false;
boost::filesystem::wrecursive_directory_iterator end_itr;
for (boost::filesystem::wrecursive_directory_iterator itr(parent_path);
itr != end_itr;
++itr)
{
if(is_regular_file(itr->status()))
{
if(std::tr1::regex_match(itr->path().file_string(),rx))
// Bingo, regex matched. Do something...
}
}
Directory iteration with Boost.Filesystem. // Getting started with regular expressions using C++ TR1 extensions // Boost.Regex
I think you must get list of files in a directory - this [link] will help you with it.
After that, I think will be quite easy to get a specific file name.

What is a cross-platform way to get the current directory?

I need a cross-platform way to get the current working directory (yes, getcwd does what I want). I thought this might do the trick:
#ifdef _WIN32
#include <direct.h>
#define getcwd _getcwd // stupid MSFT "deprecation" warning
#elif
#include <unistd.h>
#endif
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s_cwd(getcwd(NULL,0));
cout << "CWD is: " << s_cwd << endl;
}
I got this reading:
_getcwd at MSDN
getcwd at Kernel.org
getcwd at Apple.com
There should be no memory leaks, and it should work on a Mac as well, correct?
UPDATE: I fear something is still wrong here (I'm trying to avoid creating a char array with a determined length, as there's no proper way to get a decent length for getcwd):
char* a_cwd = getcwd(NULL,0);
string s_cwd(a_cwd);
free(a_cwd); // or delete a_cwd?
If it is no problem for you to include, use boost filesystem for convenient cross-platform filesystem operations.
boost::filesystem::path full_path( boost::filesystem::current_path() );
Here is an example.
EDIT: as pointed out by Roi Danton in the comments, filesystem became part of the ISO C++ in C++17, so boost is not needed anymore:
std::filesystem::current_path();
You cannot call getcwd with a NULL buffer. As per the Opengroup:
If buf is a null pointer, the behavior of getcwd() is unspecified.
Also, getcwd can return NULL which can break a string constructor.
You'll need to change that to something like:
char buffer[SIZE];
char *answer = getcwd(buffer, sizeof(buffer));
string s_cwd;
if (answer)
{
s_cwd = answer;
}
Calling getcwd with a NULL pointer is implementation defined. It often does the allocation for you with malloc (in which case your code does have a memory leak). However, it isn't guaranteed to work at all. So you should allocate your own buffer.
char *cwd_buffer = malloc(sizeof(char) * max_path_len);
char *cwd_result = getcwd(cwd_buffer, max_path_len);
The Open Group has an example showing how to get the max path length from _PC_PATH_MAX. You could consider using MAX_PATH on Windows. See this question for caveats to this number on both platforms.