3

Currently I use something like:

#include <sys/stat.h>

#include "My_Class.h"

void My_Class::my_function(void)
{
  std::ofstream my_file;

  struct stat file_info; 

  if ( filename_str.compare("")!=0  &&
       stat(filename_str.c_str(),&file_info) == 0 )
  {
    my_file.open(filename_str.data(),std::ios::trunc);
    //do stuff
    my_file.close(); 
  }
  else if ( filename_str.compare("")==0 )
  {
    std::cout << "ERROR! ... output filename not assigned!" << std::endl;
  }
  else
  {
    std::cout << "ERROR! File :" << std::endl
          << filename_str << std::endl 
          << "does not exist!!" << std::endl;
  }
}

...is this a decent way to go, or is there a better alternative? Seems like I could run amuck of permissions if I don't have permissions to read the file.

This is NOT a homework, question, it is a question about best practice.

Jason R. Mick
  • 5,177
  • 4
  • 40
  • 69

3 Answers3

4

I'd use the boost::filesystem constructs. Not only are they cross platform, they're part of the next standard library.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • I knew at least one veteran coder at a former workplace that said Boost was a trainwreck, but granted I didn't fully understand/hear their logic as to why. You think it's a good idea? – Jason R. Mick Sep 01 '10 at 21:20
  • @Jason: Think about that one for a sec. Why would @Noah answer recommending Boost if he thought it a train wreck? – Billy ONeal Sep 01 '10 at 22:01
  • Possibly because Boost can make debugging somewhat difficult? I'm not really sure - Boost has always been good to my friends and I. – SubSevn Sep 01 '10 at 22:46
  • Well if you really understand something well, you can understand its criticisms as well. For example I can see where some of the molecular dynamics software packages I use could be maligned or praised for certain reasons, and could convey that reasoning, whether I recommend the product or not... – Jason R. Mick Sep 02 '10 at 15:39
  • 1
    I also worked somewhere that a "veteran" claimed similar things. Wouldn't let us use boost. The reasons where basically that: exceptions are slow, templates cause bloat, and I'm scared of anything I didn't personally write with hard coded array boundaries and C functions with well known problems. Sometimes people are veterans just because they convinced people that know nothing about programming that they do. It's pretty easy to be a god amongst people who've never seen a cell phone. – Edward Strange Sep 02 '10 at 16:15
  • @SubSevn - I'll give you that. There are things you can do in some debuggers to make things easier of course. Like widdling through a boost::function call to the actual function you assigned to it...or worse..through a bind. I've actually contemplated no longer allowing the use of boost::optional and just making our own because it's actually impossible (from what I can tell) to get the value that's been assigned to it. Of course, optional takes into account a bunch of things I just don't care about and don't need...that make it like it is. Some people need that behavior though. – Edward Strange Sep 02 '10 at 16:18
  • @Jason - you have to keep in mind that a lot of veterans didn't keep up and just don't understand the concepts used in boost and thus can't understand the code. Boost uses a modern approach to C++ development that most old-timers won't ever get unless they actually cared enough to continue learning while they were employed. In my experience that is a very rare attribute for any worker. So while they may survive in their own environment, throw anything new at them and they're toast...which is a pretty good reason to hate boost. – Edward Strange Sep 02 '10 at 16:23
3

Generally I think it is best to just try opening it and catch an error.

IMO, checking permissions is unwise because what if it's a Linux box and you check its attributes, decide you can't write to it, but the filesystem supports ACL's and they do grant you permission? (As a sysadmin I can't stand when apps do this. I like ACL's and if you're an app, don't tell me you can't write to a file unless you've tried first.)

Ken Simon
  • 1,514
  • 8
  • 11
  • Follow the mantra, "Keep it simple..". If your code looks complicated or not simple, most likely it is. – Thomas Matthews Sep 01 '10 at 21:16
  • So just use a simple try{ } catch block? – Jason R. Mick Sep 01 '10 at 21:20
  • I tried this code... http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/Readafileintrycatchblock.htm ....but when the file doesn't exist, my executable keeps dumping blank lines to my terminal. Ideas of why that example didn't work? I literally copied and pasted it into a main.cc file and just ran g++ with no flags on it and ran the resulting executable. – Jason R. Mick Sep 01 '10 at 21:30
0

Conceptually, I'd say it depends on what you're planning to do with that file..

  • If you need its contents, go ahead and try to open it, and be prepared to handle failure gracefully, for the reasons Ken detailed.
  • If you are not currently interested in its contents (for example, when enumerating directory contents, or only planning to access a file at some point in the future, etc.), you might be better off just checking attributes for now. Otherwise, nasty things like hierarchical storage management may trigger an expensive (=slow) recall of file contents from, say, a tape backup or network (whereas attributes may have been cached). You could try to avoid that by checking for respective file attributes, but that's additional complexity, too.

So as a best practice, I'd suggest to open files sparingly (i.e., if you're not immediately interested in the contents, contend yourself with file attribute-based information), AND handle failure strictly in response to the actual call that opens the file when you need it.

ig2r
  • 2,396
  • 1
  • 16
  • 17