Opening a directory in c++ - c++

I'm trying to write a program that moves files from one directory to another, so far I have this written.
void file_Move(ifstream in,ofstream out)
{
string name, name2;
int downloads;
cout << "Enter 1 if the file you wish to move is in downloads" << endl;
cin >> downloads;
if (downloads == 1)
{
opendir("F:/Downloads"); //supposed to open the directory so that the user can input the file they wish to be moved.
closedir("F:/Downloads");
}
}
Visual Studio doesn't have the dirent.h library which is necessary for opendir and closedir, so I was wondering if there was a similar or better way of doing what those do.

Your code doesn't make much sense as it stands right now.
On one hand, file_move takes an ifstream and an ofstream, which would imply that you've already found and opened the files you care about. Then it goes on to attempt to search for files...
For the moment, I'm going to assume you need to search for the files you care about. In this case, you probably want to use the filesystem library. With a really up to date compiler, this may be directly in std::. For a slightly older compiler, it may be in std::experimental. For one that's older still (predates the Filesystem TS) you'll probably need to use Boost Filesystem instead.
In any case, code to use this would run something like this:
#include <string>
#include <filesystem>
#include <iostream>
#include <iterator>
#include <algorithm>
void show_files(std::string const & path) {
// change to the std or Boost variant as needed.
namespace fs = std::experimental::filesystem::v1;
fs::path p{ path };
fs::directory_iterator b{ p }, e;
std::transform(b, e,
std::ostream_iterator<std::string>(std::cout, "\n"),
[](fs::path const &p) {
return p.string();
}
);
}
Of course, if you're going to copy files, you probably want to put the file names in a vector (or something on that order) rather than just displaying them--but presumably you know how to do what you want once you have file names to work with.
In any case, to call this you can just pass the path to the directory you care about, such as F:/Downloads:
show_files("f:/Downloads");
Of course, under a system that uses POSIX paths, you'll pass a different input string (e.g., might be something like "/home/some_user/Downloads" instead). Oh, and at least with its usual directory structure, with g++ the header will be experimental/filesystem instead of just filesystem.

Related

When to include the <string> header in your program?

Do you include the "string" header when a library such as "iostream" already provides a solution?
Example: Do you include the string library if you have already included the iostream library? Which is the right professional method?
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream fin;
fin.open("input.txt");
string data;
fin >> data;
cout << data << endl; // Works with <iostream>, and without <string>
fin.close();
return 0;
}
Example 2: Use string library if another library provides functionality, even if program compiles without string?
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
ifstream fin;
fin.open("input.txt");
string data;
fin >> data;
cout << data << endl; // Even though <iostream> allowed program to compile, we include the <string> library.
fin.close();
return 0;
}
Received points off my CSC 101 class programming assignment because even though program worked, teacher said when using the string datatype I needed to include the string library. Even though technically it was fine without it possibly. Thats the question.
Your teacher was correct.
Your program worked without <string> by chance. Your standard library implementation, of that version, on that platform, under those circumstances, on that day, transitively included what you needed via <iostream>. The standard library is just code, like yours, and it just so happens that your particular implementation contains, inside <iostream>, an #include <string>. It could be buried behind many other #includes but got there eventually. But that's honestly pure chance, and does not mean that this is something the language guarantees, or something that must always be the case even in practice.
You should always code to standards.
If you're using features from <string>, include <string>.
Just today I was trying to build my big project with a new toolchain and found a few places where I'd accidentally relied on transitive includes, and it broke the build as a result because the new standard library implementation had a slightly different arrangement of headers. I dutifully added the missing #includes and now the world is a better place for it.

C++ Searching in all files of a PATH

How should I go about searching the entire files/folders from a given PATH, and searching all of it's contents for a specific string for example?
I know I'd have to do it recursively somehow, unless there's a function to search for everything in a path. And that I'd have to open each file found and check for that specific string in it. But how does Visual Studio open files? Can it open any kind of files, or just text-based ones?
All I've managed to get so far is:
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = std::experimental::filesystem;
void ShowFiles(string path)
{
for (auto &p : fs::directory_iterator(path))
cout << p.path().filename() << '\n';
}
int main()
{
ShowFiles("D:/TEST/testFOLDER/");
}
Which only prints the folders/files in the given PATH, but not the ones inside folders of it.
EDIT: should i use DIR* and dirent* ? would it be any easier?
Use recursive_directory_iterator instead.
For reading the file, use std::ifstream. It has been updated to take a path object in C++17.

A running executable that modifies itself

I have a Visual Studio 2008 C++ project for Windows CE 5 where I would like the currently running executable to modify itself.
Specifically, I would like to be able to read/write some data stored within the exe file itself. I do not need (or wish to) modify executable code.
In regular windows, I could use a string resource and the UpdateResource function, but that doesn't exist in WinCE.
CreateFile, unfortunately, fails because the file is already in use.
Does anybody have any other suggestions?
First, why do you need to do this? You should be able to do this with other methods.
I'm not particularly familiar with Windows-CE, but if you need to, you can probably copy the file, edit the copy, delete the first, and then run the other. That's an inefficient way, but if you only need to do it once or twice in the span of the program and speed isn't a concern, I guess you could do it:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char * argv[]) {
// Check if this IS the copy:
if (argv[0].find(argv[1]) != string::npos) {
system("taskkill -IM myOLDfile.exe"); // Stop the old one running,
system("del myOLDfile.exe"); // Then delete it.
}
ifstream myself(argv[0]); // argv[0] is the program itself
string fullcode;
string line;
if (file.is_open()) {
while (file.good()) {
getline(myself, line);
line.append("\n");
fullcode.append(line);
}
}
myself.close();
// Do whatever you need to do to the code here.
ofstream newcode("myNEWfile.exe");
newcode.write(fullcode);
newcode.close();
system("myNEWfile.exe myNEWfile.exe"); // Starts new file. Also, not a typo.
}
Good luck on your project!

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.

mixing C and C++ file operations

I am writing a file splitting program, to assist with using large files with iPod notes. I want to use tmpfile() in cstdio but it returns a file* not an fstream object. I know it's not possible in standard C++ but does anyone know any libraries that work well with the standard that have the ability to convert a FILE* to an std::fstream object? Or, if not is tmpfile() functionality available in the standard, or another library?
Thanks!
My OS is Windows XP and I use either Dev-C++ 4.9.9.2 or MS Visual Studio 2008 as my compiler.
If all you want is a temporary file, use tmpnam() instead. That returns char* name that can be used for a temporary file, so just open a fstream object with that name.
Something like:
#include <cstdio>
#include <fstream>
...
char name[L_tmpnam];
tmpnam(name);
//also could be:
//char *name;
//name = tmpnam(NULL);
std::fstream file(name);
You do have to delete the file yourself, though, using remove() or some other method.
You can use the benefits of c++ streams by pumping your data via the << syntax into a std::stringstream
and later write it the .str().c_str() you get from it via the the C-API to the FILE*.
#include <sstream>
#include <cstdio>
#include <string>
using namespace std;
int main()
{
stringstream ss;
ss << "log start" << endl;
// ... more logging
FILE* f_log = fopen("bar.log", "w");
string logStr = ss.str();
fwrite(logStr.c_str(), sizeof(char), logStr.size(), f_log);
fclose(f_log);
return 0;
}
Even if you manage to convert a FILE* to an std::fstream, that won't work as advertised. The FILE object returned by tmpfile() has a special property that, when close()'d (or when the program terminates), the file is automatically removed from the filesystem. I don't know how to replicate the same behavior with std::fstream.
You could use tmpnam mktmp to obtain a temporary file name, open it with a stream and then delete it with remove.
char *name;
ifstream stream;
name = mktmp("filename");
stream.open(name);
//do stuff with stream here.
remove(name);//delete file.
Instead of using std::fstream, you could write a simple wrapper class around FILE*, which closes it on destruction. Should be quite easy. Define operators like << as necessary.
Be sure to disallow copying, to avoid multiple close() calls.
g++ has __gnu_cxx::stdio_filebuf and __gnu_cxx::stdio_sync_filebuf, in ext/stdio_filebuf.h and ext/stdio_sync_filebuf.h. It should be straight-forward to extract them from libstdc++ if your compiler is not g++.