File System Access via C/C++

Jump to First Reply
Posted:
in Mac Software edited January 2014
OK, this might be a bit techie....



I'm a developer developing C++ on a Mac. I'm trying to do a simple thing, and I want to avoid using the Carbon API to do it. To open a file in the Windows world, you would do something like this:



#include <iostream>

#include <fstream>

...

const char* outputFileName = "C\\\somedirectory\\blah\\blah\\targetfile.t xt";

ofstream outFile(outputFileName);

...



Anyone know of a way, programatically, on a Mac, how to fully qualify a path and file name?



Thanks,



Jack
«1

Comments

  • Reply 1 of 21
    Just use the standard C fopen and fwrites... There is no lack of documentation (Kernighan and Ritchie, 'man flopen', etc...). This also works on the Windows side (and Unix, RTOS's, etc... it is part of the C standard).
     0Likes 0Dislikes 0Informatives
  • Reply 2 of 21
    rraburrabu Posts: 264member
    In C++:



    #include <iostream>

    #include <fstream>

    ...

    const char* outputFileName = "/somedirectory/blah/blah/targetfile.txt";

    ofstream outFile(outputFileName);

    ...
     0Likes 0Dislikes 0Informatives
  • Reply 3 of 21
    Thanks Karl. The problem I am having is that if I used a fully qualified path/file name to write a file, for instance, I get a file created in the directory of the application named as the full path + file instead of a file in the directory of the path.



    For example, if I specify:



    /somedir/filename.abc



    I get a file called "/somedir/filename.abc" in the current directory (where the app launched from), not a file called "filename.abc" in the "/somedir" directory. See what I mean? It's interpreting the path+file as the whole file name itself. With Windows, you can specify "C\\\somedir\\\\filename.abc" (two \\\\'s needed to "escape" the single \\) and get the desired results. Not sure how to do this in the Mac world.
     0Likes 0Dislikes 0Informatives
  • Reply 4 of 21
    Thanks, but unfortunately this creates a file called:



    /somedirectory/blah/blah/targetfile.txt



    in the current (app launch) directory instead of a file called:



    targetfile.txt in the



    /somedirectory/blah/blah/



    directory.



    There's gotta be an easy way to do this (read/write to hard-coded directories) without opening the Carbon API can of worms. If I needed to pop up Finder dialogs to allow the user to select directories and filenames, then I'd definitely need the Carbon API.



    Any other suggestions appreciated.
     0Likes 0Dislikes 0Informatives
  • Reply 5 of 21
    er ideally you should be using cocoa NOT carbon

    if you had any gui stuff



    btw apart from the mach kernel the rest of os x

    is freebsd 4.2 so your code in theory should work

    i'd compile that code under bsd or linux & see if it

    works & then compile under os x via gcc



    gcc is pretty std across all three platforms

    as is the stl unless you prefer boost or any other

    lib
     0Likes 0Dislikes 0Informatives
  • Reply 6 of 21
    Problems that come to mind are:

    Character encoding of the string (two bytes per char vs. one?)

    Backslashes vs. forward slashes



    Seeing the actual code would help.
     0Likes 0Dislikes 0Informatives
  • Reply 7 of 21
    Madmax, thanks. I'm locked into using Carbon because I'm writing C/C++, not Objective-C or Java. And I'm locked into using CodeWarrior and C/C++ because I'm developing plug-ins for a specific application, and the SDK I'm writing against was built using Codewarrior/C++. And my GUI stuff is created using a proprietary method developed by the developers of the SDK and parent application.



    Another problem with Carbon is that it is the official "procedural" API that is supposed to work with C and C++, and Cocoa is the object-oriented API, but it requires the use of Java or Objective-C. So...C++ is object-oriented, and that presents some interesting problems when the API needs to do a callback to a user-defined function pointer, because it's designed to call C functions, not C++ member functions... Never had so much difficulty with basic file I/O!!
     0Likes 0Dislikes 0Informatives
  • Reply 8 of 21
    Just as a note: You can use C++ code in Cocoa projects (and of course plain C), you just have to designate the files as ObjC++ and be careful when passing things between the ObjC and C++ objects (ie it has to be plain C calls/items).



    In this case I am not sure that Cocoa would be the right approach, because you are working on a plugin specifically... But if all your callbacks are pure C, then it is an option. But in any event I would encourage you to try out XCode's CodeWarrior import feature.



    And I have not had time to look at what is happening, and it has been a long time since I did C access.. but I think that 'fopen' should be opening things at absolute paths... I think there is something fishy here, and I too would like to see the code.
     0Likes 0Dislikes 0Informatives
  • Reply 9 of 21
    Gents,



    The code is this simple:



    \t\t\t\t\tconst char* outputFileName = "/Junk/somefile.abc";

    \t\t\t\t\tofstream outFile(outputFileName);

    \t\t\t\t for (int i=0;i<mSomeVariable;i++)

    \t\t\t\t outFile << somearray[i] << endl;



    This successfully creates a file with the desired contents, but in the wrong file in the wrong dir. Instead of somefile.abc residing in /Junk, I get a file called /Junk/somefile.abc in the app-launch directory.



    Maybe there's some escape sequence needed to make the system know the slashes mean directories instead of filename characters??? Or maybe I indeed need to use the File Manager stuff in Carbon API and use FSRef...
     0Likes 0Dislikes 0Informatives
  • Reply 10 of 21
    rraburrabu Posts: 264member
    Code:




    #include <iostream>

    #include <fstream>



    using namespace std;



    int main(int argc, char **argv)

    {

    const char* outputFileName = "/Users/blah/Desktop/test/junk.txt";

    ofstream outFile(outputFileName);



    for (int i=0;i<100;i++)

    outFile << i << endl;

    outFile.flush();

    outFile.close();



    return 0;

    };









    This works for me. Compiled at command line with "c++ test.cpp". Creates a file named junk.txt on blah's desktop.
     0Likes 0Dislikes 0Informatives
  • Reply 11 of 21
    Since you are using CodeWarrior, could they have done something wonky with their libraries to try and make code paths cross-platform? There would probably be something in some documentation about this somewhere... a quick google didn't turn up anything for me, but...
     0Likes 0Dislikes 0Informatives
  • Reply 12 of 21
    rraburrabu Posts: 264member
    They may be using something that is backwards compatible to pre OSX systems. I believe the character to use then would be the ':'.



    Try a path defined as:



    ":Some:directory:to:file.txt"



    Maybe some pre-OSX coders here could correct the above.
     0Likes 0Dislikes 0Informatives
  • Reply 13 of 21
    rrabu,



    Thanks for trying this. I just tried your application verbatim (with changes just to the path and file names) using CodeWarrior and I got the same result I got before: a file named "/Junk/junkfile.txt" in my current directory instead of "junkfile.txt" in "/Junk".



    When I try to compile from the command line terminal:



    > c++ myfile.cpp



    I get:



    > ld: can't locate file for: -lcrt1.o



    Is there anything **special** I need to do to get the Mac C++ compiler to work?
     0Likes 0Dislikes 0Informatives
  • Reply 14 of 21
    jbljbl Posts: 555member
    Do you have write permission to put stuff in /Junk ?



    Try rrabu's code without changing the path. My guess is that OS X is doing something funny because it doesn't like you writing outside your home directory.
     0Likes 0Dislikes 0Informatives
  • Reply 15 of 21
    Quote:

    Originally posted by JBL

    Do you have write permission to put stuff in /Junk ?



    Try rrabu's code without changing the path. My guess is that OS X is doing something funny because it doesn't like you writing outside your home directory.




    The librarie's actions in this case should be very specific: fail. It should not return a filehandle to somewhere else. I don't think that this is the issue. (I am still betting on a wonky cross-platform intended thing).
     0Likes 0Dislikes 0Informatives
  • Reply 16 of 21
    rraburrabu Posts: 264member
    I agree with Karl. In fact I had tried it with a path to a directory I didn't have permission to. The program didn't return any error (I didn't check for one, you may have noticed) and also didn't create any file at all.



    As to getting gcc working from the command line, there was nothing special I had to do. Installing the developer tools was all I did.
     0Likes 0Dislikes 0Informatives
  • Reply 17 of 21
    What editor are you using to create the source? Could the editor be translating characters somehow, so that the slashes aren't really the path-separator slashes?
     0Likes 0Dislikes 0Informatives
  • Reply 18 of 21
    Yeah, the thing is: it IS writing a file -- just to the "wrong" (unwanted) directory -- so it's not a permissions thing.



    I'm hunting through any information I can get on ofstream. The "open" member function takes two arguments: a const char* (the filename) and any number of bitwise-or'd ios::<somebitmask> mask values that define things like "open file for read", "open file for write", etc. I see nothing that allows for the specification of a file system path...so it must have to be in the const char* arg...somehow...



    (My Windows (sorry to use such profanity!) books say use:



    <C colon><backslash><backslash><dir><backslash><backs lash><dir>...<backslash><backslash><filename>



    Still stuck in the water on this one...thanks for all your help...
     0Likes 0Dislikes 0Informatives
  • Reply 19 of 21
    gongon Posts: 2,437member
    rrabu's code worked for me. OS 10.3, devtools 1.5. HTH.
     0Likes 0Dislikes 0Informatives
  • Reply 20 of 21
    When you debug it, what ascii values are being stored in outputFileName for the slashes?



    It still seems to me that the only way a file could be named with a slash is if it isn't really a slash. (Same glyph, different character code.)



    Also, have you tried the sample code in both Code Warrior and XCode (or even just gcc), and do you get the same result in both?
     0Likes 0Dislikes 0Informatives
Sign In or Register to comment.