51

I've been using windows in a class I've been taking but I am trying to run a basic code to figure out how to open/close/input/output from files on Xcode and the code I usually use on visual studios isn't working any idea why? thanks!

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream fin;
    ofstream fout;
    string input;

    fin.open("inputFile.txt");
    if(fin.fail())
        cout << "File failed to open." << endl;
    fin >> input;

    fout.open("outputFile.txt");

    fout << input;


}
zneak
  • 134,922
  • 42
  • 253
  • 328
user3473255
  • 511
  • 1
  • 5
  • 3
  • also #include it didn't copy... either way my output is "File failed to open." – user3473255 May 02 '14 at 23:23
  • 1
    Where is `inputFile.txt`? – zneak May 02 '14 at 23:23
  • Try to specify the absolute path to the file. XCode executes in another location that your source code is, so a relative path assuming the source directory won't work. – Appleshell May 02 '14 at 23:56
  • Welcome to Xcode. You're going to find [**this answer helpful**](http://stackoverflow.com/questions/14476655/code-runs-perfect-in-g-but-not-in-xcode-cannot-find-file/14478210#14478210), I'm almost sure of it. – WhozCraig May 03 '14 at 00:00

6 Answers6

85

Put your .txt files in the same directory where your main.cpp file is (or anywhere you like).

In Xcode go to Product > Scheme > Edit Scheme > Run (on the left) > Options (middle top)

Down under Options for "Working Directory" check “Use custom working directory” and set it to the directory where you .txt files are located.

enter image description here

To work with the files, you will have to specify just file names, e.g. in_file.open("inputFile.txt"); no path is necessary.

Vladislav Povorozniuc
  • 2,149
  • 25
  • 26
nepete
  • 911
  • 5
  • 6
  • But how could you do this if you are on git or svn and and the people are using the same xcode project file and they don't want to change the scheme for each user. – Evren Bingøl Feb 09 '17 at 07:13
  • @nepete can you please tell me why we have to do this every time we try to open a new file in c++? –  Sep 10 '19 at 23:33
  • 1
    @user11954047, it might be helpful to understand the difference between the workspace, project, target, and scheme first. Here is a [good explanation](https://stackoverflow.com/questions/20637435/xcode-what-is-a-target-and-scheme-in-plain-language). [bames53's answer](https://stackoverflow.com/a/27884234/3094345) in this thread might also be helpful. – nepete Sep 19 '19 at 06:08
  • 1
    This option isn't available in XCode 11 – Viliami Nov 29 '19 at 01:01
31

Here's a completely different approach: Have Xcode copy the input file for you.

  • Select your project in Xcode
  • Select Build Phases
  • Click the '+' button to create a new Build Phase

Steps 1-3

  • Select New Copy Files Build Phase

Step 4

  • Select Products Directory
  • Click the '+' button to add your file

Steps 5-6

  • Click Add Other

Step 7

  • Select your input file and click Open

Step 8

  • Check the Copy items… checkbox and click Finish

Step 9

Now every time you build your project, the input file will be copied to the same folder as the executable no matter where it is built. Of course, to see the output file, you'll still need to find the executable in Finder.

SSteve
  • 10,550
  • 5
  • 46
  • 72
9

The answers don't really explain the problem so I thought I'd do that.

When you pass a relative path like "inputFile.txt" to file APIs, it's treated as relative to the working directory when the program is executed. This is the same as the 'working directory' when you use cmd.exe or Terminal.app or command lines in general. The Unix command pwd ("print working directory") displays the current working directory. On Windows running the command cd with no arguments performs the same function. (On Unix running cd with no arguments will change the working directory to the user's home directory.)

When you run a program from the command line, the command line shell sets the program's working directory. When you run a program from within an IDE, the IDE sets the working directory. Since, unlike on a command line, there's no obvious answer for what the IDE should set as the working directory, Visual Studio and Xcode set the working directory to different locations by default: Visual Studio sets the working directory to $(ProjectDir), the directory containing the Visual Studio project file; Xcode sets the working directory to the build products directory, i.e. the location the executable was written to.

Some possible solutions to your problem are:

  1. Do not use a relative path, and therefore don't depend on the working directory. This isn't much help in making the program more portable, because the absolute paths will also differ between platforms, and so you will still have to 'configure' the program for each platform. In fact using an absolute path is worse, because it means your source code must differ, whereas it would be better to keep that difference confined to each platform's build configuration.

  2. Configure the IDE to use your desired working directory. Visual Studio can be configured by right clicking the project, selecting Configuration Properties > Debugging > Working Directory, and setting the working directory to the desired path (potentially using Visual Studio build variables).

    nepete's answer describes how to configure the working directly set by Xcode.

  3. Configure the IDE's build process to copy your data files to an appropriate location. In Visual Studio you would do this in a C++ project by configuring the project's Properties > Configuration Properties > Build Events.

    SSteve's answer covers how to configure additional build steps in Xcode.

Community
  • 1
  • 1
bames53
  • 86,085
  • 15
  • 179
  • 244
2

I'm guessing you have inputFile.txt in the folder that contains your source code. That's not going to work. You need to put it in the folder that contains the generated executable. To find that folder, right-click on your app under Products and select Show In Finder.

enter image description here

This image shows what it looks like for a command line program. It also shows the Finder window that was opened. As you can see, it is a different folder than the one containing the source code.

Command Line version

SSteve
  • 10,550
  • 5
  • 46
  • 72
  • Ok, it was in the same folder as my source code, however I'm a little confused by what you mean. I clicked show in finder in the "products" folder and it came up with only one file, the file that my source code is is already... is there something I'm doing wrong? – user3473255 May 02 '14 at 23:42
  • Don't right-click on the folder, open the folder and right-click on the item in the folder. I added a screenshot showing what it looks like for a command line program (called `asdf` in this case). – SSteve May 03 '14 at 06:24
2

As suggested by nepete, edit the scheme, but use $PROJECT_DIR as the custom working directory. Helps with moving the project around, or working in two different environments (e.g., home and office).

BTW. $PROJECT_DIR is one of the Xcode Environment Variables, and also helps with passing file names as command line arguments to programs (settable under "Arguments" in the scheme).

jendrek
  • 19
  • 1
0

I've struggled with the same problem today. I wanted to add C code to my Swift project and my file pointer was always NULL.

Unfortunately, in XCode 9 for iOS app, I couldn't change the working directory. Changing Build phases didn't help me either. After 4+ hours of trial and error, that's what I've come up with finally and it works:

  1. when copying files to XCode, I've chosen "Create groups", but I needed to choose "Create folder references":

enter image description here

  1. I created a new objective-c file (.m) and copied all my C code there.

  2. I left untouched .h files (XCode generated bridging header and my own .h file with public functions declaration). Now my project structure looked like this:

enter image description here

  1. In my dict.m file in place of previous plain c fopen part:

    FILE *dic = fopen("dictionary.txt", "r");
    

    I added obj-C code:

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"dictionary" ofType:@"txt"];
    FILE *dic = fopen([filePath cStringUsingEncoding: NSUTF8StringEncoding], "r");
    

And it works now without any problem! It's just amazing!

ps I decided to write this answer in case it will help someone like me and will save them some time. If you know how to change working directory in XCode 9 for iOS, please, leave me a comment - now I am really curious why I can't find it.

joliejuly
  • 2,127
  • 1
  • 21
  • 24