unable to open files c++ - c++

I'm really struggling at the moment, originally had other issues with eclipse itself, that seems to have been resolved. Code looks right to me (compared to example code for loading files) however I'm not able to load anything as the error I put in is always triggered. No building errors atm. What am I doing wrong? Tried with both eclipse (mac) and Code::blocks (win vm), both seem to be having issues. the data files themselves are in the same folder as the .cpp file.
#include <iostream>
#include <string>
#include <math.h>
#include <fstream>
using namespace std;
int main() {
cout << "Choose which data file to load (1-4)" << endl;
int file;
cin >> file;
ifstream data;
switch (file) {
case 1:
data.open("dataSet1.txt");
case 2:
data.open("dataSet2.txt");
case 3:
data.open("dataSet3.txt");
case 4:
data.open("dataSet4.txt");
}
if (!data) {
cerr << "File not Loaded" << endl;
return -1;
}
string FullData[61];
for (int i=0; i=60; i++){
data >> FullData[i];
cout << FullData[i] << endl;
}
return 0;
}
EDIT: Got the program to stop showing the error, and it seems to be loading the files, however my assign/display loop doesn't seem to be working now as it displays only the last data point over and over again.

the data files themselves are in the same folder as the .cpp file
Being in the same folder as the .cpp is not important, the dataset files should be in the same folder as the compiled binary program.
It can also be that there is a working directory setting that does not point on the directory where your dataset files are. All that is being passed into the open member function is a string which means that interpreting what that string means depends on the environment settings.

Same issue. In my case as #Gluk36 pointed, the problem was the working directory settings.
In that case, you must deselect "Use default settings" and set where the binary is. I attach you a screenshot for your reference from eclipse CDT 4.9 under linux.

You must have break statement after each case
like:
case1://something;
break;
and you must close the stream with close() function
data.close();

Related

ifstream won't find file even though it's in the same directory

I've got a method to read a vector of bools from a file:
std::vector<bool> OPCConnector::getAlarmVector() {
std::vector<bool> data;
std::ifstream DataFile(filepath);
if (DataFile) {
bool value;
while (DataFile >> value) {
data.push_back(value);
std::cout << value;
}
}
return data;
}
The filepath variable is an object property that is assigned through the constructor:
OPCConnector::OPCConnector(std::string fpth) {
filepath = fpth;
}
And in the main() function, the constructor is called:
std::vector<bool> activations;
std::string filepath = "alarmes.txt";
OPCConnector opcc = OPCConnector(filepath);
activations = opcc.getAlarmVector();
Now, I've checked what the folder of the executable is via GetModuleFileNameA(), and I made sure that the file is in the same directory and has the same name (also, I made sure that the extension isn't part of the file name, like "alarmes.txt.txt").
I debugged the first method getAlarmVector() and it never gets past the if (DataFile) condition, as if it won't find file.
I run the code using Visual Studio 2019, and nothing happens. The vector remains empty. Error is No such file or directory.
Default working directory is $(ProjectDir) and it's exactly where my file is.
Edit: I've also tried using both relative and absolute paths, none work.
Edit 2: I've also checked the directory using GetCurrentDirectory() and copied the .txt file there too, and it isn't working.
SOLUTION: Strangely enough, I deleted the file and created it again with the same name, and it worked. Thanks for the answers.
My guess: your current working directory isn't what you think it is, especially if you're running from an IDE. I know of several IDEs where the current working directory is some build directory (it varies by IDE) unless you specifically change it.
I'm fairly sure Visual Studio is one such IDE.
Here's a tiny example program I wrote;
$ cat Foo.cpp
#include <iostream>
#include <fstream>
int main(int, char **) {
std::ifstream file { "Foo.cpp" };
if (file) {
std::cout << "File opened.\n";
}
else {
std::cout << "File not opened.\n";
}
}
Compile and run it:
$ g++ --std=c++17 Foo.cpp -o Foo && Foo
File opened.
Current folder and folder-of-exe-file are different things (sometimes). Try to specify full name of file (with disk, all folders, etc.).
You can check errors of file open operation by calling
if (!DataFile) { ... }
The std::filesystem library can help you resolve file and path related issues.
#include <filesystem>
// (in some function)
std::filesystem::path filepath = "alarmes.txt";
if ( !exists(filepath) )
{
std::cout << "File path " << filepath << " at absolute location "
<< absolute(filepath) << " does not exist\n";
}
See it on Compiler Explorer
You can get an error code (and get a description of error in internet) if you use C-function fopen. If open is failed, you get the nullptr as result of fopen and errno will contain code of error.

C++ How do I delete files with _rmdir?

I made a simple program that deletes files, however, I don't know how to delete a directory. I saw a few posts saying I need to list all of the files in that directory, delete those files, and then delete the directory/folder itself. However, somebody suggested using _rmdir which as far as I understand, deletes a directory without any problems, however, it doesn't. Do I still need to list all of the files in a directory in order to delete it with _rmdir? Thanks!
Code:
#include <iostream>
#include <string>
#include <sys/stat.h>
#include <Windows.h>
#include <direct.h>
using namespace std;
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
inline bool fileExists(const string& filepath) {
struct stat buffer;
return (stat(filepath.c_str(), &buffer) == 0);
}
int main()
{
string filePath;
string fileAttribute;
cout << "[~] Enter a path to delete: ";
getline(cin, filePath);
cout << "\n[#] Checking if path exists..";
if (fileExists(filePath) == 1)
{
if (GetFileAttributes(filePath.c_str()) == FILE_ATTRIBUTE_DIRECTORY)
{
cout << "\n[!] Directory found!";
_rmdir(filePath.c_str());
cout << "\n[#] Deleting directory..";
}
else
{
cout << "\n[!] File found!";
remove(filePath.c_str());
cout << "\n[#] Deleting file..";
}
if (fileExists(filePath) == 0)
{
SetConsoleTextAttribute(h, 10);
cout << "\n[!] Deletetion successful!";
SetConsoleTextAttribute(h, 15);
}
else
{
SetConsoleTextAttribute(h, 12);
cout << "\n[!] Deletion unsuccessful!";
SetConsoleTextAttribute(h, 15);
}
}
}
You probably want the C++17 function std::filesystem::remove_all which deletes the contents of the directory and the contents of all its subdirectories, recursively, then deletes the directory itself as if by repeatedly applying the POSIX remove. Symlinks are not followed (symlink is removed, not its target).
Edit: As Eryk Sun pointed out in the comments, it's good to test that the recursive removal does not follow Windows junctions, which would lead to unwanted removal of everything the junction points at.
I made a test that used std::filesystem::create_directory_symlink to create a symlink and then use the WinAPI to check if that symlink became a junction, which it reportedly did - a junction has the FILE_ATTRIBUTE_REPARSE_POINT attribute and the reparse point tag IO_REPARSE_TAG_MOUNT_POINT. Interestingly it also had the IO_REPARSE_TAG_SYMLINK tag. When using normal DOS commands I noticed that the link was indeed reported as a plain <SYMLINKD> and not a <JUNCTION>.
I then used MKLINK /J to create a junction. That junction was indeed reported as a <JUNCTION> by DOS and running std::filesystem::remove_all() on it removed it, but not what it pointed at.
I also downloaded the sysinternals Junction utility and used that to create a junction.
That junction was also reported as a <JUNCTION> by DOS, but running std::filesystem::remove_all() on it had another effect. It did not remove it (or what it pointed at).
So remove_all() should be safe with regards to junctions - but perhaps even too safe. I didn't try to find out what the difference was between the MKLINK junction and the junction created by the sysinternals utility.
Do I still need to list all of the files in a directory in order to delete it with _rmdir?
Why don't you simply read the documentation?
It says:
The _rmdir function deletes the directory specified by dirname. The directory must be empty, and it must not be the current working directory or the root directory.
That's pretty much the case for any "remove directory" functionality. It's what your Windows Explorer UI is doing behind the scenes when you hit delete on your keyboard.
This is also the case for std::filesystem::remove, but std::filesystem::remove_all will do all that recursion for you.
You can use:
std::filesystem::remove_all("path/myDirectory");

std::ofstream does not show error when permission denied C++

The following code when path = "c:\" doesn't write to file c:\err.txt because permission is denied. But it doesn't generate an error at the same time. Rather, it outputs "OK".
How I can check whether the permissions would allow the write?
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
bool writeLineToErr(string path, string err_line){
std::ofstream outfile(path+"err.txt", std::ios_base::app);
if(!outfile){
cout<<"Error 1 "+path+"err.txt"+" can't open file!";
return false;
}
if(outfile.fail()){
cout<<"Error 2 "+path+"err.txt"+" can't open file!";
return false;
}
outfile << err_line << endl;
cout<<"OK";
outfile.close();
return true;
}
int main(int argc, char** argv) {
writeLineToErr("c:\\","Some Line");
return 0;
}
I'd say your code works and the write operation is actually done, but for the sake of it, add a check after the write too:
outfile << err_line << endl;
if(outfile.fail()) cout << "Error3\n";
else cout<<"OK";
On my system, I'll get your Error 1 ... can't open file if the file isn't opened for writing successfully.
Edit: Or are you running Windows with Compatibility Files virtualization still active? If so, the file will probably be in the Virtual Store, not in the real C:\err.txt path.
Example: C:\Users\username\AppData\Local\VirtualStore
If you find it there, you may find a lot of other stuff in there too. At least I did years ago when I had a similar problem. I decided to manually move (with admin rights) the few important files that some of my older programs had put there and then turn Virtual Store off. I can't find a good and simple official Microsoft link for how to turn off file and registry virtualization right now so perhaps this will do:
RegEdit:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\
Create a DWORD Key with the name EnableVirtualization and give it the value 0. If the key is already there, but set to something else than zero, change it.
There's more here:
UAC Group Policy Settings and Registry Key Settings

How to use file strings as commands in c++

I am trying to make a program on Windows 10 using Visual Studio 2015 that would sim-link certain files to certain locations. I am trying to make a text file with the location of the files, and the sim-link destination to use.
This is an example of the file data that would be in the properties.txt file:
FileLocation: "Z:\Folder\file.txt"
FileMkdirLocation: "Z:\Folder2\file.txt"
I want to use something like system(mkdir "sim-link_file_location" "file_location") by changing the data that is in properties.txt. I want to be able to add more than 1 file, without recompiling the program and writing each command for each file, one by one.
The problem is that I don't know how to make the commands use the data in the file.
EDIT: I managed to find out a way, but I get errors when compiling the program. I use this code:
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdlib.h>
using namespace std;
//initialization of Properties File used
ifstream PropertiesFile ("PropertiesFile.txt");
int main()
{
//initialization of variables used
int input_option;
char FileLocation[256], Command[]="mklink ";
// string FileLocation, Command;
PropertiesFile >> FileLocation;
/* switch (input_option)
{
case "add all mods":
}
*/
cout << "FileLocation: " << FileLocation;
cout << endl;
strcat(Command, FileLocation);
Command[strlen(FileLocation)] = '\0';
cout << Command;
cout << endl;
//system(command);
system("pause");
return 0;
}
I know that i haven't used all variables yet.
It tells me that "strcat" is deprecated and to use "strcat_s" instead, and when i replace it with that, I get
"Debug Assertion Failed - Expression: (L"Buffer is too small" && 0)"
I had to make the "Command" char bigger than "FileLocation" because then strcat_s would not be able to copy the content. After that the program worked fine, and there were no other Assert Errors.
The command to create a soft link in linux is: ln -s <source> <destination>
You can use this in a system(""); call, BUT before you continue in your code, you will have to make sure that the kernel finished executing this command.
After that you can read the link as if it was the original file.

Unable to open file.txt with c++

I've looked up similar posts here, but none seem to be doing the job for my question. I'm basically trying take a sequence of words in a .txt file and put each word in a vector, and printing each value afterwards. For example, we have I love racing cars in array.txt, and I want my vector to have "I" at position 0, "love" at 1 and so on. Unfortunately, the code does not access "array.txt", so it never executes the code in the if condition.
Now I've heard that by using the fstream library it should work just fine, but the file is never found. I suspect that it doesn't work because it cannot find the path, but I have never opened files in C++. Also, I have not put my file anywhere in my project folder.
Some changes I've already tried:
file.open("array.txt");
omitting file.close();
include "C:\array.txt"; (with the # in front)
file.open("C:\array.txt")
And I'm using Windows 10, if this matters.
#include <iostream>;
#include <string>;
#include <vector>;
#include <fstream>;
//#include <"C:\Users\Samer El-Hage\Documents">;
using namespace std;
void main(){
vector<string> v (10);
ifstream file;
file.open("C:\array.txt", ios::in);
if (file.is_open())
{
for (int i = 0; i < 3; i++)
{
file >> v[i];
}
file.close();
}
else cout << "Could not access file.";
for (int i = 0; i < 3; i++)
{
cout << v[i] << " ";
}
}
This code prints "Could not access file."
The file cannot be opened because the file system can't find the file named "[Bell]rray.txt". the character sequence '\a' is the "Make my computer Beep" character.
Use either forward slashes: "C:/array.txt", an escaped backslash: "C:\\array.txt" or a raw string literal: R"(C:\array.txt)"
The file must also exist at the specified location. If you do not provide a drive and just say "array.txt" the location defaults to wherever the executable is (or in an IDE, the Working Directory).
Also, you have unnecessary semi-colons after your includes. (In fact, in a Treat Warnings as Errors setup, this won't compile!)
I got it! I had not put the .txt file in my folder with the source code, which, strangely enough, was not mentioned in my previous search results... I got to search better!
\a simply turns the computer beep on. Try writing "C:\\array.txt" instead in the open call.
Try not calling open explicitly:
ifstream file ("array.txt");
Look at the examples here:1