Search Unity

DirectoryNotFoundException with existent path? How can that be?

Discussion in 'Scripting' started by Igor_Vasiak, Mar 7, 2018.

  1. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    So, I've got a DirectoryNotFound"Damn"Exception. I don't like when those occur, because I don't really understand them a lot. Don't get me wrong, I know that they mean that a directory wasn't found. But in my case the directory exists and there is no spelling. Actually, not only the directory exists, but if I check this in the same script that the error occurs (or in any other) THEY SAY THAT THE DIRECTORY IS THERE.

    I'm trying to add support to "infinite" saves in my game. This means that, as long as the computer has some space available, the player will be able to create new saves. The player can also delete those using:

    Directory.DeleteDirectory(path, true);


    And this is how I save the game:

    string newFile = JsonUtility.ToJson(managerJSON);
    File.WriteAllText(SaveDirectory + "game_manager.json", newFile);


    Is there a specific reason for the code not work? Of course, the error only comes when I'm trying to save for the first time (then the save file, a .json, doesn't exist), but shouldn't System.IO.File create the .json?

    Thanks in advance.
     
    Necronomicron likes this.
  2. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    Is SaveDirectory actually the same path as what you're looking for? Put it in Debug.Log() just to be sure.

    Also, System.IO.File will not create the directory if it doesn't exist, and you will get that DirectoryNotFound exception when trying to write to the file.

    Here's one way to ensure the directory exists before saving:

    Code (csharp):
    1.  
    2. System.IO.FileInfo file = new System.IO.FileInfo(filePath);
    3. file.Directory.Create(); // If the directory already exists, this method does nothing.
    4. System.IO.File.WriteAllText(file.FullName, content);
    5.  
    (code example shamelessly stolen from StackOverflow)
     
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Code (CSharp):
    1.  
    2. if (!Directory.Exists(Application.persistentDataPath + "/folderName/"))
    3.    Directory.CreateDirectory(Application.persistentDataPath + "/folderName/");
    4.  
    5. File.WriteAllText(Application.persistentDataPath + "/folderName/filename.json", text);
    6.  
    Code I use in a project. Checks if the folder exists, if not, create it. Then write to it.
     
  4. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    That's exactly what I do...

    @BlackPete yes, my SaveDirectory is what I'm looking for. I didn't said I wanted to create a directory using File. I said that it creates (usually) a File of the same type, when the file I'm looking for doesn't exists. And, about that stolen piece of code, I think I'm gonna use it, because my method to create a Directory path if it does not exists uses 4 for loops... Quite slow, huh?
     
  5. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    Here is the error, if you need more information (please don't get mad at be because of the bad formatting):

    DirectoryNotFoundException: Could not find a part of the path "C:\Users\multi\Desktop\Project P\Assets\StreamingAssets\Saves\A New Game\game_manager.json".
    System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/FileStream.cs:292)
    System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share)
    (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
    System.IO.StreamWriter..ctor (System.String path, Boolean append, System.Text.Encoding encoding, Int32 bufferSize) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/StreamWriter.cs:124)
    System.IO.StreamWriter..ctor (System.String path, Boolean append, System.Text.Encoding encoding)
    (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (string,bool,System.Text.Encoding)
    System.IO.File.WriteAllText (System.String path, System.String contents, System.Text.Encoding encoding) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:626)
    System.IO.File.WriteAllText (System.String path, System.String contents) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:621)
    MultipleGameStyles.Extensions.File_Extensions.SaveToJSON[GameManagerJSON] (.GameManagerJSON data, System.String path, System.String fileName) (at Assets/MGS.cs:61)
    GameManager+<ResetGameManager>c__Iterator0.MoveNext () (at Assets/GameManager.cs:114)
    UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    GameManager:LoadGame() (at Assets/GameManager.cs:89)
    SavesLoader:<Refresh>m__0() (at Assets/UI/SavesLoader.cs:63)
    UnityEngine.EventSystems.EventSystem:Update()
     
    xtinacs likes this.
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    You're trying to save to StreamingAssets? You should be saving out to the PersistentDataPath.
     
  7. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    I don't wan't to save to PersistentDataPath because I want my game to be "editable", @Brathnann .

    @BlackPete, your approach works really well. It not only creates the missing directories to the path faster than mine approach, as it also does create the file. Just wondering how... Thanks.
     
    BlackPete likes this.
  8. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    The problem is, StreamingAssets is not usable in some build platforms. You actually can't save to it on some platforms. Unless you are doing only build targets that support it.
     
    BlackPete likes this.
  9. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    Interesting... Well, since I'm only working with PC/Mac/Linux at the moment, I don't need to worry that much... But that's good to know. Thanks.
     
  10. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    Glad to hear it works now!

    I do have to agree that StreamingAssets path isn't really meant for save files. It's more intended for large assets that require streaming in on the fly at run time. Think large movie files, alembic files, etc. Anything that can run in the hundreds of megabytes (if not gigabytes) in size.

    If your want your game to be "editable", then I'd recommend you use persistentDataPath by default, and add an UI option to your game settings to let players override the destination folder to save files to.
     
  11. Igor_Vasiak

    Igor_Vasiak

    Joined:
    Dec 13, 2016
    Posts:
    44
    Probably in the future. At this moment my game is still on Pre Alpha 5b2... Anyway, thanks yall for helping me out! :)

    If someone knows how to close threads, go on!