I'm very very new to C++.
In my current project I already included
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
and I just need to do a quick check in the very beginning of my main() to see if a required dll exists in the directory of my program.
So what would be the best way for me to do that?
So, assuming it's OK to simply check that the file with the right name EXISTS in the same directory:
#include <fstream>
...
void check_if_dll_exists()
{
std::ifstream dllfile(".\\myname.dll", std::ios::binary);
if (!dllfile)
{
... DLL doesn't exist...
}
}
If you want to know that it's ACTUALLY a real DLL (rather than someone opening a command prompt and doing type NUL: > myname.dll to create an empty file), you can use:
HMODULE dll = LoadLibrary(".\\myname.dll");
if (!dll)
{
... dll doesn't exist or isn't a real dll....
}
else
{
FreeLibrary(dll);
}
There are plenty ways you can achieve that, but using boost library is always a good way.
#include <boost/filesystem.hpp>
using boost::filesystem;
if (!exists("lib.dll")) {
std::cout << "dll does not exists." << std::endl;
}
Related
Visual Studio is not recognising my #include 'Header.h' file. I have created the file in the Header Files in solution explorer and also tried manually pointing to the file. What I don't understand is, until yesterday there was absolutely no problem. Therefore, a simple cout doesn't work.
#include 'Header.h';
int main()
{
cout << "hi";
return 0;
}
#include "Header.h"
#include <iostream>
using namespace std;
int main()
{
cout << "hi";
return 0;
}
Not that Header.h is used in anyway, this is still the correct syntax.
You need #include <iostream> to be able to use cout.
You've got syntax errors in your #include preprocessor directive. Replace single with double quotes and drop the semicolon:
#include "Header.h"
Found the problem : I had to go to properties bar and change "Included In Folder" value to true from false.
I'm new to C++ and I've just read <C++ Primer> 4ed. Now I want to implement a little program to help me manage some mp3 files in my computer.
I have a .txt file which includes all the names(part of the names actually) of the files which I want to move(not copy) to a new folder(in the same column). For example, "word" and "file" in the .txt and I want to move all the .mp3 files whose filename contain "word" or "file" to a new folder. Hope my discription is clear, Opps..
I know how to read the strings in .txt into a set<string> and traverse it, but I have no idea how to search and move a file in a folder. I just want to know what else should I learn so that I can implement this function. I read C++ Primer and still I can't do much thing, that's really sad...
To move a file in C++, you do not have to use external libraries like Boost.Filesystem, but you can use standard functionality.
There is the new filesystem API, which has a rename function:
#include <iostream>
#include <filesystem>
int main() {
try {
std::filesystem::rename("from.txt", "to.txt");
} catch (std::filesystem::filesystem_error& e) {
std::cout << e.what() << '\n';
}
return 0;
}
The drawback is to compile it, you need a recent C++17 compiler. (I tested it on gcc 8.0.1, and I also needed to link against -lstdc++fs).
But what should work on any C++ compiler today, is the old C API, which also provides rename (cstdio):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
int main() {
if(std::rename("from.txt", "to.txt") < 0) {
std::cout << strerror(errno) << '\n';
}
return 0;
}
But note that in both cases, the rename will fail if the source and destination files are not on the same filesystem. Then you will see an error like this:
filesystem error: cannot rename: Invalid cross-device link [from.txt] [/tmp/to.txt]
In that case, you can only make a copy and then remove the original file:
#include <fstream>
#include <iostream>
#include <ios>
#include <cstdio>
int main() {
std::ifstream in("from.txt", std::ios::in | std::ios::binary);
std::ofstream out("to.txt", std::ios::out | std::ios::binary);
out << in.rdbuf();
std::remove("from.txt");
}
Or with the new API:
#include <iostream>
#include <filesystem>
int main()
{
try {
std::filesystem::copy("from.txt", "to.txt");
std::filesystem::remove("from.txt");
} catch (std::filesystem::filesystem_error& e) {
std::cout << e.what() << '\n';
}
return 0;
}
Use rename() function to move a file
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char oldname[] = "C:\\Users\\file_old.txt";
char newname[] = "C:\\Users\\New Folder\\file_new.txt";
/* Deletes the file if exists */
if (rename(oldname, newname) != 0)
perror("Error moving file");
else
cout << "File moved successfully";
return 0;
}
The only way for this to work only using std would be to read the file completely using a std::ifstream and then write it to the new location with a std::ofstream. This will however not remove the old file from disk. So basically you create a copy of the file. Its also much slower than a real move.
The optimal solution is to use OS specific APIs like win32 which e.g provide a MoveFile() function. Poco provides an platform independent abstraction of such APIs. See: http://www.appinf.com/docs/poco/Poco.File.html
Another way to move a file in Windows is using the MoveFile function as it is shown in the following code.
std::wstring oldPath = L"C:\\Users\\user1\\Desktop\\example\\text.txt";
std::wstring newPath = L"C:\\Users\\user1\\Desktop\\example1\\text.txt";
bool result = MoveFile(newPath.c_str(), oldPath.c_str());
if (result)
printf("File was moved!");
else
printf("File wasn't moved!");
under Windows run system call with batch commands:
system("move *text*.mp3 new_folder/");
system("move *word*.mp3 new_folder/");
Under Unix same with shell syntax.
This question already has answers here:
How do you get a directory listing in C?
(9 answers)
Recursive function for listing all files in sub directories
(10 answers)
Closed 10 years ago.
I need to enumerate all the file in a folder and then navigate to the subfolder and do the same (recursion? sure).
Ideally the algorithm should work in the same way on linux & macos
DISCLAIMER: I have asked a similar question on POSIX: I'm now aware of VFS but I'm puzzled to use VFS for enumerate dir. Any suggestion ? Should I open a dir as file ? The only way is to use a library cross platform like qt ?
UPDATE: so no VFS way to work on directory? "*V*irtual *F*ile *S*ystem provides a single API for accessing various different file systems" but no way to enumerate directory.
The "readdir" etc solution will do the trick on any type of *NIX ? And on windows nothing better than the huge MingW lib? or partial impletion working on only some win like:
https://github.com/xbmc/xbmc/blob/master/tools/TexturePacker/Win32/dirent.c
The BOOST seem to be a really cool solution but it's complex and academic. thnks in any case
LAST UPDATE:
I have found some more doc and now everything is a lot more clear.
This question is a duplicate!
opendir() and readdir() are the solution to enumerate and browse directory on linux. As shown on my example is quite easy to map them on windows (but the incoerent windowz fs make everything strange) and ntfw() is even more useful.
VFS (the virtual file switch) is a kernel feature that resolves this problem by creating an abstraction layer for file-system operations. closed doc here: linux programming interface
thnks!
You want to look at nftw. Here's an example that just recursively prints the contents of a directory in C (Untested):
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <ftw.h>
int
print( const char *path, const struct stat *s, int flag, struct FTW *f )
{
puts( path );
return 0;
}
int
main( int argc, char **argv )
{
while( *++argv ) {
if( nftw( *argv, print, 1024, FTW_DEPTH )) {
perror( *argv );
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
Here is how I do it using Boost.Filesystem:
#include "boost/filesystem.hpp"
#include <iostream>
int main () {
for ( boost::filesystem::recursive_directory_iterator end, dir("./");
dir != end; ++dir ) {
// std::cout << *dir << "\n"; // full path
std::cout << dir->path().filename() << "\n"; // just last bit
}
}
Or, more succinctly:
#include "boost/filesystem.hpp"
#include <iostream>
#include <iterator>
#include <algorithm>
int main () {
std::copy(
boost::filesystem::recursive_directory_iterator("./"),
boost::filesystem::recursive_directory_iterator(),
std::ostream_iterator<boost::filesystem::directory_entry>(std::cout, "\n"));
}
Unix/Linux/Windows all have versions of readdir(). You can use it to get what the file system knows about files.
I'm doing the stanford course cs106b in C++, and I'm stuck and I can't seem to get it right. This probably a very easy fix for someone who knows this kind of stuff.
I have three files, one main.cpp and a randword.h and randword.cpp. In randword.h I have #include "simpio.h" which is a stanford library where GetLine() is defined. I can get GetLine() to work in the main.cpp file but when I try to compile I get "undefined reference to 'GetLine()'" in randword.cpp.
I use codeblocks and I have used the "Add files..." function.
Here's the code for main.cpp:
#include "randword.h"
/* Private function prototypes */
/* Main program */
randword rw;
int main() {
rw.initDictionary();
}
randword.h:
#ifndef RANDWORD_H_INCLUDED
#define RANDWORD_H_INCLUDED
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "simpio.h"
#include "strutils.h"
using namespace std;
class randword{
public:
void initDictionary();
string chooseRandomWord();
string strArray[];
private:
};
#endif // RANDWORD_H_INCLUDED
random.cpp:
#include "randword.h"
using namespace std;
void randword::initDictionary(){
string fileName;
ifstream infile;
fileName = GetLine();
infile.open(fileName.c_str());
if(infile.fail()) cout << "Couldn't read file.";
return;
}
string randword::chooseRandomWord(){
string st1;
return st1;
}
Any help would be much appreciated! I suspect that this question was already posted, but I couldn't find it. Thanks!
try adding the library manually using code blocks
Open up your project
Right click your project and select build options..
select debugger
Go to linker settings
Under Link Librarys click "add"
Find your lib file, select it and keep as a relative path
Your project SHOULD run, if not reply here(as i explained something wrong)
randword.cpp does NOT have the library file needed to use GetLine, you may have included it inside your header file, but this does not carry over to randword.cpp. You need to include the library file just as you would in any other file in order to have access to it's functions.
//randword.cpp
#include <iostream>
#include "simpio.h" //include again!!!
//code here....
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);
}