ifstream not opening file - c++

In this function i am trying to open a file that contains a set of characters that i want to assign to my matrix array, however whenever i run this program the console displays an error that says that the file is not open. Another question, if i add that file to my resource folder how do i specify to access that file and not the one that i have in the root of my hard drive?
ifstream readSecondMap("C:\\map_2.txt", ifstream::in);
void Stage::populateStage(ifstream &myStage, char (&myArray)[mapXcor][mapYcor]) {
if(myStage.is_open()){
for(int a = 0; a < mapXcor+1; ++a){
for(int b = 0; b < mapYcor+1; ++b){
myArray[a][b] = (char) myStage.get();
}
}
myStage.close();
} else {
std::cout << "Error: Unable to open File" <<std::endl;
}
}

The issue is most likely one of the following:
1) map_2.txt does not exist in the location you specified in your ifstream declaration.
2) You do not have sufficient rights to access the root folder of your C drive.
I advise moving the file to the same folder that your code is stored in temporarily and trying to get it to work with that location first to verify that the issue is with file location or access rights rather than something you're doing in your code. Then move it to your resource folder, and use a relative path name to access it if it works. If it doesn't work when the file is in the same folder as your code and when you have the pathname written correctly, then you are probably doing something wrong in your code and would need to post a larger portion of the code to expose the issue to us.

Just as #TianyunLing noted:
I've tested on KUbuntu 12.10:
Open error: if map_2.txt does not exist, the error will occur.
File path:
folder1
+------- file1
+------- file2
folder2
+------- program
+------- file3
for your program to visit file1, use "../folder1/file1", to visit "file3", use file3. (suppose that you don't change your program working directory)
One more thing, you don't need to specify ifstream::in for ifstream.

Related

Phantom \.txt file in windows

It seems like it is possible to create a file \.txt in windows that can be read, but I'm not able to access it any other way or see if it exists. This seems to only work for \.txt since I can't create other files with backslashes in it such as a\.txt
string filename = "\\.txt";
// make file
ofstream writer(filename);
writer << "This file exists" << endl;
writer.close();
// read file
ifstream reader(filename);
string line;
getline(reader, line);
cout << line << endl;
reader.close();
When I use ls -lia in bash, this file doesn't show up at all, but the program above reads it fine (I can remove the part that creates the file and run it later so the file does persists), how does this work?
On Windows, ofstream writer("\\.txt") creates a file named .txt in the root of the current drive. It is a perfectly valid file name.
ofstream writer("a\\.txt") tries to create a file named .txt in the a subdirectory of the current directory. The a directory must exist in order for it to succeed. Most likely it does not exist, therefore it fails for you.
To create a directory you can use either the mkdir function (which has compatibility problems with other OSes because Windows is not POSIX compatible), or the CreateDirectory WINAPI function, that is Windows specific. After calling CreateDirectoryA("a"), the "a\\.txt" path should work.

How to rename a file from ext4 file system to ntfs file system in C++

Have a query. I am always using the code in C++ (below) to move a file from one location to another in same drive (call it A drive)
rename(const char* old_filename, const char* new_filename);
Recently I need to amend the code to move it to another drive (call in B-Drive). It doesn't work but I could write code to write into that particular drive (B-drive). On investigation, I found that the drive (A-drive) on which I produce the result(the old file) is in ext4 file system but the drive i am writing/moving to is in NTFS (fuseblk)
How can i amend my code to move the file to NTFS. I am using C++ in ubuntu
Regards
--------------------------------------------------------------------
New Edit after heeding call from user4581301
This is the code I have written
int main()
{
std::string dirinADrive = "/home/akaa/data/test3/test_from.txt"; // this is the parent directory
std::string dirinBDrive = "/media/akaa/Data/GIRO_repo/working/data/test5/test_to.txt"; // this is where i want to write to
std::string dirinCDrive = "/home/akaa/data/test3/test_to.txt"; // this is where i want to write to
std::string dirinDDrive = "/media/akaa/Data/GIRO_repo/working/data/test5/test_to_write.txt";
bool ok1{std::ofstream(dirinADrive).put('a')}; // create and write to file
bool ok2{std::ofstream(dirinDDrive).put('b')}; // create and write to file
if (!(ok1 && ok2))
{
std::perror("Error creating from.txt");
return 1;
}
if (std::rename(dirinADrive.c_str(), dirinCDrive.c_str())) // moving file to same drive
{
std::perror("Error renaming local");
return 1;
}
if (std::rename(dirinADrive.c_str(), dirinBDrive.c_str())) // moving file to other drive
{
std::perror("Error renaming other");
return 1;
}
std::cout << std::ifstream(dirinBDrive).rdbuf() << '\n'; // print file
}
And I have gotten an error
Error renaming other: Invalid cross-device link
So what is invalid cross-device link??
Thanks
You can’t use rename across filesystems, because the data must be copied (and having a single system call do an arbitrary amount of work is problematic even without atomicity issues). You really do have to open the source file and destination file and write the contents of one to the other. Apply whatever attributes you want to preserve (e.g., with stat and chmod), then delete the source file if you want.
In C++17, much of this has been packaged as std::filesystem::copy_file. (There is also std::filesystem::rename, but it’s no better than std::rename for this case.)

C++ Can't Open&Read File

I can't open the file in c++. I saw a lot of page that asked same question but i can't figured it out. I opened new project for just open the file (As you can see). -I also tryed it with mingw but nothing changed. I try to put the file everywhere in the folder. Please help.
string sayi;
ifstream oku("sayilar.txt");
if (oku.is_open())
{
cout << "Opened";
}
else
{
cout << "Can't opened";
}
int x; cin >> x;
I can't find the real problem but i think it is about my OS settings (Win10). When i write "sayilar.txt.txt" instead of "sayilar.txt" it works.
I've tryed to uncheck "hide extensions of known file types" setting but it stil doesn't work. (There was no answer about that problem in StackOverflow, for that negative voters) So i'll work with "sayilar.txt.txt". Regards.
I think the problem is in your file name so you are hiding the file extension then the first .txt is considered to be a part of file name not extension so if you show file extension then you'll get your file sayilar.txt.txt so try to rename it correctly so:
either hide file extensions and rename the file to sayilar only without adding .txt because it is hidden.
or show file extensions and then rename the file to sayilar.txt so there's no extra extension.
if the problem persists then delete file and create a text file named sayilar : right click in your current folder or in any void place in the desktop -> New -> Text Document. enter the name sayilar.
I wish this will figure out your problem.

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.

Proper way to test for readability/writability of a folder

I have written a function to test for the readability/writability of a folder.
For unit testing it, I need to produce the different cases:
a folder with readable and writable files
a folder with readable files (not writable)
a folder not writable and not readable.
Here is the code for the function I came to, up to this point:
void FileUtils::checkPath(std::string path, bool &readable, bool &writable)
{
namespace bf = boost::filesystem;
std::string filePath = path + "/test.txt";
// remove a possibly existing test file
remove(filePath.c_str());
// check that the path exists
if(!bf::is_directory(path))
{
readable = writable = false;
return;
}
// try to write in the location
std::ofstream outfile (filePath.c_str());
outfile << "I can write!" << std::endl;
outfile.close();
if(!outfile.fail() && !outfile.bad())
{
writable = true;
}
// look for a file to read
std::ifstream::pos_type size;
char * memblock;
for (bf::recursive_directory_iterator it(path); it != bf::recursive_directory_iterator(); ++it)
{
if (!is_directory(*it))
{
std::string sFilePath = it->path().string();
std::ifstream file(sFilePath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
if (file.is_open())
{
size = file.tellg();
if(size > 0)
{
memblock = new char [1];
file.seekg (0, std::ios::beg);
file.read (memblock, 1);
file.close();
delete[] memblock;
if(!file.fail() && !file.bad())
{
readable = true;
}
break;
}
}
else
{
// there is a non readable file in the folder
// readable = false;
break;
}
}
}
// delete the test file
remove(filePath.c_str());
}
Now with the tests (done with Google tests):
TEST_F(FileUtilsTest, shouldCheckPath)
{
// given an existing folder
namespace fs = boost::filesystem;
fs::create_directory("/tmp/to_be_deleted");
bool readable = false, writable = false;
FileUtils::checkPath("/tmp/to_be_deleted",readable, writable);
fs::boost::filesystem::remove_all("/tmp/to_be_deleted");
EXPECT_TRUE(readable && writable);
}
I will add more for the other cases when I will have gone further.
Now the game is open to propose a better solution :-)
The foolproof way to check permissions is to literally check the file mode. In the case of directory permissions, the meaning of "readable" and "writable" might be surprising:
Read - allows you to list the contents of the directory
Write - allows you to create, rename, delete files from the directory, essentially modifying the list of contents (also requires execute)
Execute - allows you to access (both read and write) and change properties of files within the directory
So if you have a directory with just the execute bit set, you can still read and write to the files inside. By turning the execute bit off, you can disable access to the files. As far as the contained files are concerned, the most you can figure out from the directory permissions is:
--x or r-x: existing files can be read and written to
-wx or rwx: existing files can be read and written to, files can be created, renamed and deleted
otherwise: you have no access to the files at all
To determine if a file is readable but not writeable (or vice versa) you need to check the permissions of the file itself. The directory can only tell you if the files can be accessed in general.
You can use stat() or access() (see BЈовић's comment) to find out the permissions for a file or directory. Since you're already using boost, you can also use boost::filesystem::status() which simply wraps stat().
To be portable and correct, the only way to test for readability/writability of a file/directory is to read/write from/to it. Permission models can be quite complex and non-portable (ACLs for example), so you can't simply check the permissions on the parent directory. Also, checking, and then subsequently trying to write is a race condition as the permissions could change between the check and the write.
If instead what you want is a high probability that a write will succeed, such as if you're letting the user choose a scratch folder for your application, just try writing a file and then delete it afterwords. This lets you know that at the time of user selection the directory was writable.
To be robust, always assume that filesystem operations are going to fail and design so that when they do, something logical will happen instead of a crash. In particular, design a system so that a user can figure out where the permission error is -- as there's a myriad of ways permissions can be set wrong, helpful error messages go a long way.