Xcode c++ cant access file through code - c++

I have added an image "padimage.png" to my resources folder and set add to target and make copy if needed checked. Then in my c++ code I have the following code to check if it can reach the file
std::ifstream my_file("padimage.png");
if (my_file.good())
{
std::cout << "could read file \n";
} else {
std::cout << "could not read file \n";
}
This fails meaning I can't reach the file. I have checked in the debug build folder and the image is there under the resources folder, I have also tried alternative paths to the file like "resources/padimage.png" || Resources/padimage.png || ../Resources/padimage.png etc. etc.
I am fairly new to c++ still so I don't quite understand how it is suppose to find files or what path it searches relative to. Also I am sure this is quite an easy problem but I somehow can't solve it.
All help is much appreciated.

Just for your own sanity, do the following before anything else.
char wd[1024];
std::cout << getcwd(wd, sizeof(wd)) << std::endl;
You may be surprised at where you are, and thus why you can't open your file. When running from the IDE you can specify the location of your working directory under the Product/Edit Schemes... area of Xcode (among other places).

Thanks to a suggestion from WhozCraig I have managed to get it working by using the root of the project and then creating a standalone file next to the application like so:
./padimage.png
however this is not ideal. This means I would have resources outside of the project.
But after some trial and error I managed to navigate into the programs package contents by using .app to the package name;
./ProjectName.app/Contents/Resources/padimage.png

Related

how i could solve this problem with ifstream

when I run this code its only work with visual studio, in online compiler always tell me "cant opening file"
#include <iostream>
#include<fstream>
#include<string>
#include<iomanip>
using namespace std;
ifstream input("C:/Users/ACER/Desktop/words.txt");
if (!input.is_open())
{
cout << "cant opening file";
return 0;
}
An online compiler probably cannot open file on your computer using C++ code since that's not how the web works. It would have to route through some Javascript system, which is possible to create, however it seems the creators did not implement that when setting up their compiler.
You might try using file://C:/Users/ACER/Desktop/words.txt and double checking your path. Web browsers use that file:// thing when accessing local file i.e. if you had a web page on your computer it could be like file://C:/Users/ACER/Documents/index.html or something.
If that doesn't work, it just doesn't have the capability to load or save local files like that.
When you were attempting to use the code on an online compiler, most of the time you are actually compiling the code on their server, instead of on your computer.
What that means is that when you are trying to open "C:/Users/ACER/Desktop/words.txt", you are actually attempting to open a text file that is located on their server. And in most cases, you wouldn't be permitted to lookup any directory other than the one you are in. Even if you were permitted to do that for some reason, the chances they also have that text file on their server in the same location is gonna be really low.
Some comments above mentioned that many online compilers often don't have the facility to manipulate files. One that I often use do have the ability to do so in case you were looking for one: https://replit.com/#Ranoiaetep/IndianredSquigglyPrinters
.Note that the working directory is defaulted as your root directory.

How to check if any files are open in a directory?

I am trying to delete all files in a folder, but if a file is left open, it will not delete. I need to check the folder for any open files, write their names to a text document, and then close the open files. As I don't have much experience, I am first trying to check one file in the same folder, then all in the same folder, then all in a different folder. I don't want to be to needy or demanding, so just some help with the first step would be nice.
I don't have a ton of experience coding, but I have tried using fstream and (name.is_open). I may be using them wrong, so I have not yet ruled them out.
// ifstream::is_open
#include <iostream> // std::cout
#include <fstream> // std::ifstream
void checkFiles() {
int done = 0;
while(done != 1){
std::cout << "Enter 0 for continue or 1 for done: ";
std::cin >> done;
std::ifstream ifs ("test.txt");
if (ifs.is_open()) {
// Print that file is open, then close
std::cout << "File is open\n";
std::ifstream.close():
}
else {
std::cout << "File not open\n";
}
}
For this bit of code, if the file is open, it should say "File is open."
If not, it should say "File not open"
Even if I force quit the .txt file, it still says that it is open.
Eventually, I want to have a new file that displays what files were open, as well as closing all the open files.
Standard C++ offers us the filesystem library to handle files and directories (standardized in C++17). However, checking which files are open is not - as far as I can tell - a feature of that library.
The is_open() method for std::fstream's is something completely different than what you're trying to check for: It tells you whether the particular stream object is in an open state (which would mean association with an open file) - and it doesn't use the OS to check which files are open. Typically, it's just a way to check whether you've closed it someplace else in your own program; at most, it might ensure that the OS has not unilaterally closed the OS-side file access handle. So, you won't get anywhere in that direction.
I also believe, though I'm not 100% certain, that Boost doesn't have a library which offers this capability, either. Boost's filesystem library is almost identical to std::filesystem, as the latter was based on it.
So, to the best of my knowledge, you either need to directly use operating-system-specific calls to do this, or look for a library offering this functionality, elsewhere.
If you haven't found anything else, you could track how this is currently done with what's available in userspace. There's a utility called lsof. It's available on some operating systems based on Linux, Darwin, FreeBSD and Solaris (e.g. available on MacOS). It's maintained here. The source code seems to be rather atrocious C. An intrepid developer could parse that mess, figure out what it does, extract the parts relevant for your specific use case, and refactor it into a reasonable, readable and short(ish) C++ function. I realize you (OP) might not be up for it at this point, but - maybe someone else reading this answer will get inspired to do it.
The pfiles command shows the open files for a process. You can run it for all or some processes.
However, Solaris (and UNIX) in general allows you to delete open files. The file can still be read and written while it is open (but deleted), but nobody else can open the same file and the file will be deleted when all processes have the file closed.

C++ char* relative file path? (Qt)

I am trying to play a .mod audio file in an executable. I am using the 3rd party BASSMOD .dll. I can get the audio file to play when I provide the full path to the file, but I cannot get it to play when providing a relative path. Here are some snippets.
main.cpp
#include <QCoreApplication>
#include "bassmod.h"
// define file location
const char* file = "C:/Users/Downloads/test4/console/music.mod";
void startMusic() {
BASSMOD_Init(-1, 44100, 0);
BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);
BASSMOD_MusicPlayEx(0,-1,TRUE);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
startMusic();
return a.exec();
}
bassmod.h (relevant snippet)
BOOL BASSDEF(BASSMOD_MusicLoad)(BOOL mem, void* file, DWORD offset, DWORD length, DWORD flags);
The function I'm concerned about is BASSMOD_MusicLoad. As this project stands, the .mod file will play no problem. However, when I try to change the absolute path of the .mod file to a relative path ("music.mod"), the file fails to play. Why is that? I have the .mod file in the same directory as the executable as well as in the directory containing the .pro file -- that didn't seem to be the issue.
Also, maybe I'm missing something related to how files are opened in C++. It looks like the MusicLoad function requires that the second parameter be of type void*. I'm sure there are many different things I could be doing better here. Ideally, I'd like to be able to have file store the relative path to the .mod file and have it play that way so I don't have to hard code an absolute path. In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc, but then I would have to use QFile, I believe, which won't work because I need the type to be void*.
Any help for a beginner would be much appreciated.
EDIT 01: Thank you all for your help! I got it to work (using relative file path, at least). There are two ways to do this. Here's what I did and how I tested it:
The first case makes the assumption that BASSMOD (or whatever external dll you're using) does not handle relative paths.
const char* file = "C:/debug/music.mod"; // same dir as .exe
QFileInfo info("music.mod");
QString path = info.absoluteFilePath();
const string& tmp = path.toStdString();
const char* raw = tmp.data();
Those are the test items I set up. When I run BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);, it works as expected. That's when I hard-code the full absolute path.
When I ran BASSMOD_MusicLoad(FALSE,(void*)raw,0,0,BASS_MUSIC_RAMPS);, it didn't work. So I decided to print out the values for everything to see where it's messing up:
cout << "Qstring path: ";
qDebug() << path;
cout << "string& tmp: ";
cout << tmp << endl;
cout << "raw: ";
cout << raw << endl;
cout << "full char* file: ";
cout << file;
startMusic();
...returns this:
Qstring path:
"C:/myApp/build-Debug/music.mod"
string& tmp:
C:/myApp/build-Debug/music.mod
raw:
C:/myApp/build-Debug/music.mod
full char* file:
C:/myApp/build-Debug/debug/music.mod
Note the difference? When I hard-code the full path to the file, I found that (thanks to #FrankOsterfeld and #JasonC) the current working directory was actually not where the .exe (/debug) or .pro files were located. It was actually in the same directory as the Makefile.
So I just changed it to this: QFileInfo info("./debug/x.m"); and it worked.
Even though the problem wound up being me not knowing where the current working directory was, the solutions by #Radek, #SaZ, and #JasonC helped to find another way to solve this (plus it showed me how to get the working dirs and convert between types). This is a good reference for people who would want to use QFileInfo to determine where you actually are in the filesystem. I would have used this solution if the dll I was using did not handle relative paths well. However...
I wondered if I could apply the same solution to my original code (without using QFileInfo and converting types, etc). I assumed that BASSMOD did not handle relative paths out of the box. I was wrong. I changed the file variable to const char* file = "./debug/x.m"; It worked!
Thanks for the help, everyone!
However, I would still like to get this to work using music.mod from a Qt resources file. Based on the replies, though, it doesn't look like that's possible unless the 3rd party library you're using supports the Qt resource system.
I have the .mod file in the same directory as the executable.
In Qt Creator the default initial working directory is the directory that the .pro file is in, not the directory that the .exe ends up in.
Either put your file in that directory (the one that probably has all the source files and such in it as well, if you used the typical setup), or change the startup directory to the directory the .exe file is in (in the Run Settings area).
Although, based on your new comment below, I guess the problem is deeper than that... I can't really tell you why BASS doesn't like relative filenames but you can convert a relative path to an absolute one before passing it to BASS. There's a lot of ways to do that; using Qt's API you could:
#include <QFileInfo>
...
const char* file = "music.mod"; // Your relative path.
...
BASSMOD_MusicLoad(...,
(void*)QFileInfo(file).absoluteFilePath().toAscii().data(),
...);
In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc
You won't be able to do that because loading resources from .qrc files is a Qt thing and BASS presumably does not use Qt internally (just like e.g. you could not open a resource with fopen), and doesn't understand how to load resources embedded by Qt. I am not familiar with BASS but a cursory glance at this documentation shows that it also has the ability to play data from an in-memory buffer. So one approach would be to use Qt to load the resource into accessible memory and pass that buffer instead.
In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc, but then I would have to use QFile, I believe, which won't work because I need the type to be void*.
Why do you only belive? Read Qt Doc. It will work. Don't use class QFile but QFileInfo.
QFileInfo info(:/resourcePrefix/name);
QString path = info.absoluteFilePath();
void* rawPtr = (void*)path.toStdString().c_str();

C++ directory search

So I'm trying to write a little C++ program to check whether or not a directory exists on a Windows platform (I am aware that other languages are more suited for this type of use, but I want to do it in c++).
This is what I have so far (it compiles):
std::string DirectorySelector::SpecifyDirectory(void)
{
std::cout << "Enter directory for file renaming: ";
std::cin >> directory;
if (ValidateDirectory(directory) == 1) { SpecifyDirectory(); }
else { return directory; }
}
int DirectorySelector::ValidateDirectory(std::string directory)
{
error = "Error 01: Directory not found.";
std::ifstream fin (directory);
if (!fin)
{
std::cerr << error << "\n\n";
fin.close();
return 1;
}
else
{
fin.close();
return 2;
}
}
So obviously I'm currently asking for the user to input their desired directory as a string, not sure if this is a wise choice?
I have done a little research into whether Windows folders (directories) have an extension, but it appears not.
I assume I am missing something obvious, such as a predefined C++ keyword to use somewhere?
If any answers could be fully explained as to what is going on that would be fantastic, as I don't like to use stuff which I don't understand.
Plus any tips to do with coding standards that I may not be adhering to would obviously be greatly appreciated.
Thanks in advance.
If you want to use DIRENT (unix method) in windows then see here, advantage is cross platform (dirent is pretty much everywhere except windows):
http://www.softagalleria.net/dirent.php
If you want to use the Windows API for this:
How to check if directory exist using C++ and winAPI
For a portable (across many platforms) file-management system you could use boost::filesystem
The documentation may look a bit complex for a relative beginner but they probably give you examples that will enable you to get going on what you want, and if you get stuck you can always come back here and ask specifics.
Your existing code is incorrect in its use of ifstream which is used to open a file for read-only. You cannot use this to open a directory (to list its contents or see if it exists).

What would cause ifstream code to fail on OS X?

I have the following code
string fileName = "assets/maps/main.json";
std::ifstream file(fileName);
std::string temp;
if(!file.good())
{
LOG(logERROR) << "Failed to open map file: " << fileName;
//return;
}
LOG(logDEBUG) << "file Char Count: " << file.gcount();
while(std::getline(file, temp))
{
mapString += temp;
}
file.close();
This code works superbly on Windows 8. When I take this program over to OS X, the file fails to open 100% of the time. Or to be more concise, file.good() never returns true. I intentionally commented out the return there to help debugging for later code.
Anyway, this has driven me insane. I cannot figure out why it's failing on OS X. I've tried different directories, re-created the file on OS X to make sure it wasn't an encoding or line-end issue, nothing at all.
What else can I do to debug, or what might I try as an alternative?
I've also checked the file permissions themselves and they are all fine. I have many other types of files in the same directory structure (images, music, fonts) and they all open fine, it's just this JSON file that fails, and any new derivatives of this file also fail.
When you start a program on Linux or MacOSX, the working directory will be wherever the user is. So, if your game needs to find files, you need to make use of the appropriate preference system. Mac has a concept of a 'bundle' that allows a program to come with data files and use find them, you'll have to learn how to make one. You can look inside all the '.app' directories in your /Applications directories for many examples.