1

From my iPad I try to save data to a text file and read it. The string from the textfile will be displayed in text field. On my MAC everything works fine, but if I try it on my iPad I always get the following error:

DirectoryNotFoundException: Could not find a part of the path

This is the code I am using:

Text txtField

public void SaveDataToTextFile()
{
    using(StreamWriter saveData = new StreamWriter(Application.dataPath + "/Resources/TextFiles/textfile.txt"))
    {
        saveData.Write("Some Text");
        saveDate.Close();

        ReadSavedData();
    }
    // I also tried it with Application.persistenDataPath and Application.StreamingAssets
    // But with both solutions I received the error above
}

public void ReadSavedData()
{
    using(StreamReader readData = new StreamReader(Application.dataPath + "Resources/TextFiles/textfile.txt"))
    {
        var fileContent = savedData.ReadToEnd();
        var lines = fileContent.Split(new char[] { '\n' });

        foreach(var line in lines)
        {
            var savedDataString = line.Split(new char[] { '\n' });
            txtField.text = string.Join("\n", savedDataString.Skip(1));
        }
    }
}

I know this question is similar to this question and even to this but non of them really helped me.

What do I have to change so that my iPad can write to and read from a text file?

Edit

I could manage to read my text file with my iPad with the following code:

public void ReadSavedData()
{
    // Read dueDates TextFile:
    var textFile = Resources.Load<TextAsset>("TextFilePath/textFileName");
    var lines = textFile.text.Split(new char[] { '\n' });

    foreach(var line in lines)
    {
        var savedDataString = line.Split(new char[] { '\n' });
        txtField.text = string.Join("\n", savedDataString.Skip(1));
    }
}

But I am still not able to write into my text file.

halfer
  • 19,824
  • 17
  • 99
  • 186
diem_L
  • 389
  • 5
  • 22

1 Answers1

1

Never use simple string concatenation for system paths!

And note that especially

Application.dataPath + "Resources/TextFiles/textfile.txt"

without any separator makes no sense as this would be a file outside of the

Application.persistentDataPath

folder since it results in something like

/rootfolder/applicationfolderResources/TextFiles/textfile.txt

You need either a \ or a / between them like e.g.

/rootfolder/applicationfolder/Resources/TextFiles/textfile.txt

So rather use Path.Combine which uses the correct path separators according to the running OS.

Path.Combine(Application.persistentDataPath, "Resources", "TextFiles", "textfile.txt")

Then further a special note regarding Resources:

From Unity's own Best Practices for theResources folder

Don't use it!

There are a lot of reasons for this you can all find in the link but most importantly for your case: Both the dataPath and the Resources folder are read-only after a build!

So yes you can use it for loading stuff if you really insist but only using Resources.Load, not directly via the file path, how you already figured out - but you won't be able to write to it anyway.

Rather use the Application.persistentDataPath instead like e.g.

Path.Combine(Application.persistentDataPath, "TextFiles", "textFile.txt")

to store this file on the device - visible for the user though so you might want to use some sort of encryption.


Then it is still possible/probable that the folder TextFiles simply actually doesn't exist yet. So create it. I would also go through File.Open which is a bit more secure (e.g. create the file if it doesn't exist etc)

private string folderPath => Path.Combine(Application.persistentDataPath, "TextFiles");
private string filePath => Path.Combine(folderPath, "textFile.txt");

public void SaveDataToTextFile()
{
    if(!Directory.Exists(folderPath)
    {
        Directory.CreateDirectory(folderPath);
    }

    if(File.Exists(filePath))
    {
        File.Delete(filePath);
    }

    using(var fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
    {
        using(war writer = new StreamWriter(fs))
        {
            writer.Write("Some Text");
        }
    }

    ReadSavedData();
}

And

public void ReadSavedData()
{
    if(!File.Exists(filePath)) return;

    using(var fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        using(var reader = new StreamReader(fs))
        {
            var fileContent = savedData.ReadToEnd();
            var lines = fileContent.Split(new char[] { '\n' });

            foreach(var line in lines)
            {
                var savedDataString = line.Split(new char[] { '\n' });
                txtField.text = string.Join("\n", savedDataString.Skip(1));
            }
        }
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I tried it with `StreamWriter saveData = new StreamWriter(Path.Combine(Application.persistentDataPath, "TextFiles", "textFile.txt"))` but I still get the same error message .. what am I doing wrong? – diem_L Mar 06 '20 at 06:38
  • well does the folder exist? – derHugo Mar 06 '20 at 06:42
  • When I run the app, it starts with `ReadSavedData()` which works fine and it uses the same folder path. So I think the folder exists. – diem_L Mar 06 '20 at 06:45
  • See added section at the bottom – derHugo Mar 06 '20 at 06:58
  • Now it works for one file .. thanks for that :) but unfortunately for a second file I get the following error even if I use your code `UnauthorizedAccessException: Access to the path is denied` – diem_L Mar 06 '20 at 07:51
  • What is the path you try and make sure according file is not opened anywhere else at the same time – derHugo Mar 06 '20 at 07:53
  • This is the path which works `Path.Combine(Application.persistentDataPath, "TextFiles", "DueDates");` and with this path I get the error `Path.Combine(Application.persistentDataPath, "TextFiles", "Lubrication");` .. checked twice, the file is closed all the time – diem_L Mar 06 '20 at 08:11
  • wrong information sorry, unfortunately I also get the error with the `DueDates` folder .. something thing from `using(var fs = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write))` seems to throw the error – diem_L Mar 06 '20 at 08:19
  • Did you try to add the file extension like ".txt"? Unfortunately I'm no iOs expert and code wise I don't see why this shouldn't work.. – derHugo Mar 06 '20 at 08:24
  • something still won't work, could find the mistake why I got the `UnautorizedAccessException` (used folderPath instead filePath) .. so I changed that, but now I get the `FileNotFoundException` – diem_L Mar 06 '20 at 08:28
  • 1
    Well for the writer as in my answer it should be `FileMode.OpenOrCreate` in order to create the file if it doesn't exist ;) – derHugo Mar 06 '20 at 08:31
  • I could manage it now .. thanks a lot, you helped me again a lot :) – diem_L Mar 06 '20 at 09:47