How to create a text file in subdirectory? [duplicate] - c++

This question already has answers here:
Create a directory if it doesn't exist
(10 answers)
Closed 3 years ago.
I need to create a text file in my program's subdirectory to write some data. The lines below do not work, the folder is not created. The file is not created even if I create the subfolder manually. Without subfolder in line this command works perfectly.
FILE* f;
if (fopen_s(&f, "/Sandbox/OUTPUT.txt", "w"))
return 1; // Nothing happens
if (fopen_s(&f, "//Sandbox//OUTPUT.txt", "w"))
return 1; // Nothing happens
if (fopen_s(&f, "\\Sandbox\\OUTPUT.txt", "w"))
return 1; // Nothing happens
if (fopen_s(&f, "\Sandbox\OUTPUT.txt", "w"))
return 1; // Nothing happens
if (fopen_s(&f, "Sandbox/OUTPUT.txt", "w"))
return 1; // Nothing happens
if (fopen_s(&f, "Sandbox\OUTPUT.txt", "w"))
return 1; // Creates a file named 'SandboxOUTPUT.txt'
How to code this correctly?

If you have a C++17 enabled compiler, make use of std::filesystem. Here's an introduction to some of the things you can do with it that should be pretty self-explanatory, but if anything is unclear, ask and I'll try to clarify.
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
int main() {
// create a path in an OS agnostic manner
fs::path dir_path = fs::path(".") / "Sandbox";
fs::directory_entry dir(dir_path);
if(dir.exists()) {
std::cout << dir << " already exists\n";
if(dir.is_directory() == false) {
std::cerr << "... but is not a directory\n";
return 1;
}
} else {
std::cout << "creating dir " << dir << "\n";
if(fs::create_directory(dir) == false) {
std::cerr << "failed creating " << dir << "\n";
return 1;
}
}
{
// create a path to your file:
fs::path filename = dir_path / "OUTPUT.txt";
std::cout << "creating file " << filename << "\n";
std::ofstream os(filename);
if(os)
os << "Hello world.\n";
else {
std::cerr << "failed opening " << filename << " for writing\n";
return 1;
}
}
}

I suppose you're working in a Windows environment.
In case the Sandbox folder is a subdirectory of the current directory, you should use "Sandbox\\OUTPUT.txt" or ".\\Sandbox\\OUTPUT.txt".
If it's a folder within the root of the drive, then use "C:\\Sandbox\\OUTPUT.txt".
In other words, a backslash needs to be escaped by means of another backslash.
If you want to create the directory first, then try:
mkdir(".\\Sandbox") or mkdir("C:\\Sandbox").

Related

fstream fails to write/open files on raspberry pi

I am trying to run a cpp program on raspberry pi 3 b+ (from 'pi' user) but when I try to open a file with 'fstream' library it doesn't work.
I am using the following code (from main):
std::ios::sync_with_stdio(false);
std::string path = "/NbData";
std::ofstream nbData(path);
if (!nbData) {
std::cout << "Error during process...";
return 0;
}
nbData.seekp(std::ios::beg);
The program always fails there and stops because no file is created (I don't get a fatal error but the test fails and it outputs 'Error during process' which means no file was created).
I am compiling with the following command (there are no issues when I compile):
g++ -std=c++0x nbFinder.cpp -o nbFinder
I have already tried my program on Xcode and everything worked perfectly...
The problem is your path. You must put the file, you are using just the path and if the path do not exist will throw an error. In your case you just using std::string path = "/NbData";, that is you path not your file.
To be able to open your file you need make sure your path exist. Try use the code bellow, he will check if the path exist case not will create and then try to open your file.
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
int main() {
std::ios::sync_with_stdio(false);
std::string path = "./test_dir/";
std::string file = "test.txt";
// Will check if thie file exist, if not will creat
struct stat info;
if (stat(path.c_str(), &info) != 0) {
std::cout << "cannot access " << path << std::endl;
system(("mkdir " + path).c_str());
} else if(info.st_mode & S_IFDIR) {
std::cout << "is a directory" << path << std::endl;
} else {
std::cout << "is no directory" << path << std::endl;
system(("mkdir " + path).c_str());
}
std::ofstream nbData(path + file);
if (!nbData) {
std::cout << "Error during process...";
return 0;
}
nbData.seekp(std::ios::beg);
return 0;
}

c++ 17 filesystem copy_file access denied

I'm using visual studio 2017, running with the c++17 ISO Standard(not boost) set to be able to use <filesystem>. I'm running into a wall though because everytime I run, whether in debug or release, file_copy() gives me the error access denied. I've checked the other bits of my code and the only thing that isn't working is file_copy(). Does anyone know why I'm getting this error and how to fix it? I'm the administrative account on my PC.
std::vector<std::string> findAndCopyFiles()
{
std::vector<std::string> fileNames;
std::error_code errCode;
errCode.clear();
fs::current_path("C:\\Users\\kenny\\Desktop\\Engine", errCode);
std::cout << errCode.message() << std::endl; errCode.clear();
fs::path pa = fs::current_path();
pa += "\\TEMP";
std::cout << pa.string() << std::endl;
if (fs::create_directory(pa, errCode))//Create directory for copying all files)
{
std::cout << "Directory created successfully" << std::endl;
std::cout << errCode.message() << std::endl; errCode.clear();
}
fs::path tempDir(pa);
fs::path currentDirectory = fs::current_path();
fs::recursive_directory_iterator dirIter(currentDirectory);
for (auto &p : dirIter)
{
if (p.path().extension() == ".cpp" || p.path().extension() == ".h")
{
//std::string fileContents = getFileContents(p.path().string());
std::string fileName = p.path().stem().string();
if (!fs::copy_file(p.path(), tempDir, fs::copy_options::overwrite_existing, errCode))
{
std::cout << "failed to copy file: " << fileName << " from " << p.path().string() << " to " << tempDir.string() <<std::endl;
}
std::cout << errCode.message() << std::endl; errCode.clear();
//ensures file is a cpp file before adding it to list of fileNames
if (p.path().extension().string() == ".cpp")
{
auto it = std::find(fileNames.begin(), fileNames.end(), fileName); //seaches TEMP folder for file
if (it == fileNames.end())
{//if file was not found in vector of registered file names, add it
fileNames.push_back(fileName);
}
}
}
}
std::cout << "All files found. " << fileNames.size() << " files were found" << std::endl;
return fileNames;
}
As per the comments. You were trying to overwrite a directory with a regular file. From the documentation [trimmed]
o Otherwise, if the destination file already exists...
o Report an error if any of the following is true:
o to and from are the same as determined by equivalent(from, to);
o to is not a regular file as determined by !is_regular_file(to)
So you need to append the filename to the destination directory path using the `std::filesystem::operator/ overload (untested)...
if (!fs::copy_file(p.path(), tempDir / p.filename(), fs::copy_options::overwrite_existing, errCode))

is it possible to grab data from an .exe file in c++?

I am new at C/C++,
So basically I want to call an .exe file that displays 2 numbers and be able to grab those two numbers to use them in my code.
To call the .exe file I've used the system command, but I am still not able to grab those two numbers that are displayed by the .exe file
char *files = "MyPath\file.exe";
system (files);
I think this is better aproach:
Here you just create new process, and you read data that process gives you. I tested this on OS X 10.11 with .sh file and works like a charm. I think that this would probably work on Windows also.
FILE *fp = popen("path to exe","r");
if (fp == NULL)
{
std::cout << "Popen is null" << std::endl;
}else
{
char buff[100];
while ( fgets( buff, sizeof(buff), fp ) != NULL )
{
std::cout << buff;
}
}
You need to escapr back slashes in C++ string literals so:
// note the double "\\"
char* files = "MyPath\\file.exe";
Or just use forward slashes:
char* files = "MyPath/file.exe";
Its not very efficient but one thing you can to with std::system is redirect the output to a file and then read the file:
#include <cstdlib>
#include <fstream>
#include <iostream>
int main()
{
// redirect > the output to a file called output.txt
if(std::system("MyPath\\file.exe > output.txt") != 0)
{
std::cerr << "ERROR: calling system\n";
return 1; // error code
}
// open a file to the output data
std::ifstream ifs("output.txt");
if(!ifs.is_open())
{
std::cerr << "ERROR: opening output file\n";
return 1; // error code
}
int num1, num2;
if(!(ifs >> num1 >> num2))
{
std::cerr << "ERROR: reading numbers\n";
return 1; // error code
}
// do something with the numbers here
std::cout << "num1: " << num1 << '\n';
std::cout << "num2: " << num2 << '\n';
}
NOTE: (thnx #VermillionAzure)
Note that system doesn't always work everywhere because unicorn
environments. Also, shells can differ from each other, like cmd.exe
and bash. – VermillionAzure
When using std::system the results are platform dependant and not all shells will have redirection or use the same syntax or even exist!

String turns up empty after find_last_of() and substr()?

Self-teaching myself C++, and I know I'm missing something critical, but I can't for the life of me figure out what it is.
Forgive the huge block of code, I was tempted to trim it down to the critical elements, but I figured if I left it intact, you folks might have other educational criticisms about my coding style...
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
// main routine
int main(int argc, char *argv[]) {
// will store filetype here for later
string filetype = "";
string filename;
// if no arguments, die.
if (argc < 2) {
cout << "ERROR: Nothing to do." << endl;
return 1;
}
// if more than one argument, die.
else if (argc > 2) {
// TODO: support for multiple files being checked would go here.
cout << "ERROR: Too many arguments." << endl;
return 1;
}
// otherwise, check filetype
else {
string filename = argv[1];
cout << "Filename: " << filename << endl;
//searching from the end, find the extension of the filename
int dot = filename.find_last_of('.');
if (dot == -1){
// TODO: Add support for filenames with no extension
cout << "ERROR: Filename with no extension." << endl;
return 1;
}
string extension = filename.substr(dot);
if (extension == ".htm" || extension == ".html"){
filetype = "html";
}
else if (extension == ".c"){
filetype = "c";
}
else if (extension == ".c++" || extension == ".cpp") {
filetype = "cpp";
}
else {
cout << "ERROR: unsupported file extension" << endl;
// TODO: try to guess filetype from file headers here
}
}
cout << "Determined filetype: " << filetype << endl;
cout << "Filename: " << filename << endl;
return 0;
}
// All done :]
The issue I'm having is mysterious. I put the argument passed into a string like so:
string filename = argv[1];
and then search it for an extension, starting from the end and working my way to the beginning:
int dot = filename.find_last_of('.');
string extension = filename.substr(dot);
This all works as expected, but afterwards, when I try to output filename, it is mysteriously empty? I tried debugging with cout. When I print out the string BEFORE I search it, it prints properly. After, nothing prints. Like so:
$ g++ test.cpp -o test.out; ./test.out foo.html
Filename: foo.html
Determined filetype: html
Filename:
I remembered something about iterators in the past, and tried using filename.begin() to reset it, but this did nothing. Can someone shed light onto this puzzling issue?
You are declaring a second variable called filename here, after the else:
string filename = argv[1];
This goes out of scope by the time you get here:
cout << "Filename: " << filename << endl;
You are now printing the contents of the 1st variable you declared called filename, just under main.

C++: Error with Boost Filesystem copy_file

I'm running into some trouble with the copy_file function. My program is very simple, I'm just attempting to copy a text file from one spot to another.
The following code brings up a "Debug Error!" because abort() was called.
int main()
{
path src_path = "C:\\src.txt";
path dst_path = "C:\\dst.txt";
cout << "src exists = " << exists( src_path ) << endl; // Prints True
boost::filesystem::copy_file( src_path, dst_path );
return 0;
}
If I look at some other examples of code on Stackoverflow I cannot notice what I'm doing wrong. I feel like I'm missing something obvious here.
I have Boost v1.47 installed and I'm using Visual C++ 2010.
I'm guessing that the target file exists.
The docs:
template <class Path1, class Path2> void copy_file(const Path1& from_fp, const Path2& to_fp);
Requires: Path1::external_string_type and Path2::external_string_type are the same type.
Effects: The contents and attributes of the file from_fp resolves to are copied to the file to_fp resolves to.
Throws: basic_filesystem_error<Path> if from_fp.empty() || to_fp.empty() || !exists(from_fp) || !is_regular_file(from_fp) || exists(to_fp)
A simple test like so:
#include <iostream>
#include <boost/filesystem.hpp>
int main()
{
using namespace boost::filesystem;
path src_path = "test.in";
path dst_path = "test.out";
std::cout << "src exists = " << std::boolalpha << exists( src_path ) << std::endl; // Prints true
try
{
boost::filesystem::copy_file( src_path, dst_path );
} catch (const boost::filesystem::filesystem_error& e)
{
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
Prints:
src exists = true
Error: boost::filesystem::copy_file: File exists: "test.in", "test.out"
on the second run :)
I think if you are using boost::filesystem2 it should be
boost::filesystem2::copy(src_path,dest_path);
copy_file should have been deprecated.