-2

I´m new to using System.IO and I cannot figure out why my code is causing this exception. I want to check if a directory and a file exist, and if not, I want to create them. After that, I want to write something on the file i just created. Here it throws the exception. I am very sure that the creation causes the exception when im trying to use a StreamWriter, because if the file already exists, I can do not get an execption. Also, when I am clicking the button that calls this funktion a second time after one failed attemp, there is no exception and everything is working fine (looks like my programm is realizing there is no open process, after it refreshed the UI). I do not understand, what other process is seemingly accessing the file, i thought i don´t need to close any stream or so after using the FileInfo.Create() funktion.

Here is my code:

public static void Save_map(int[,] p_temp_map_property, string p_filename)
    {
        temp_map_property = p_temp_map_property;
        try
        {
            DirectoryInfo MapsDirectory = new DirectoryInfo("Maps");
            DirectoryInfo Map = new DirectoryInfo(@"Maps\" + p_filename);
            FileInfo file = new FileInfo(@"Maps\" + p_filename + @"\" + p_filename + ".txt");
            if (!MapsDirectory.Exists)
            {
                MapsDirectory.Create();
            }

            if (!Map.Exists)
            {
                Map.Create();
            }

            if (!file.Exists)
            {
                file.Create();
            }

            StreamWriter sw = new StreamWriter(@"Maps\" + p_filename + @"\" + p_filename + ".txt", false);
            
            for(int n = 0; n < 140; n++)
            {
                for(int m = 0; m < 90; m++)
                {
                    sw.WriteLine(p_temp_map_property[n, m]);
                }
            }
            sw.Close();
            sw.Dispose();
            MessageBox.Show("Map saved successfully!");
        }
        catch(Exception e)
        {
            MessageBox.Show(e.ToString());
        }
    }

An the exception:

Exception thrown: "System.IO.IOException" in mscorlib.dll
System.IO.IOException: The procces cannot acsses "C:\Users\User\source\repos\Map Editor TD\Map Editor TD\bin\Debug\Maps\test\test.txt" because it is accsessed in another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.StreamWriter.CreateFile(String path, Boolean append, Boolean checkHost)
   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize, Boolean checkHost)
   at System.IO.StreamWriter..ctor(String path, Boolean append)
   at Map_Editor_TD.Save_to_File.Save_map(Int32[,] p_temp_map_property, String p_filename) in C:\Users\User\source\repos\Map Editor TD\Map Editor TD\Save_to_File.cs:Zeile 39.

I hope someone more experienced than me can help me with that. Thanks in advance.

Azuro
  • 31
  • 6
  • You are opening the file twice 1) FileInfo file = new FileInfo(@"Maps\" + p_filename + @"\" + p_filename + ".txt"); 2) StreamWriter sw = new StreamWriter(@"Maps\" + p_filename + @"\" + p_filename + ".txt", false); – jdweng Mar 08 '21 at 22:18
  • 2
    Partially correct. Initializing the `FileInfo` class doesn't open the file stream, but calling `.Create()` does. – Tolga Evcimen Mar 08 '21 at 22:20
  • Side note. You don't need all those tests on directory existence. Just call DirectoryInfo.Create with the fullpath to the last directory you want to create. The method will create the directories for you if they don't exist – Steve Mar 08 '21 at 22:23
  • For future reference: all error messages **must** be copy/pasted into your question **verbatim**. As a corollary, before posting a question involving any error message, you should search the site for the exact text of the error message and see whether the available information addresses your problem. The error you ran into here is **very** common, and there is a wealth of information present already that you can use to help solve the problem without needing to post a new question. – Peter Duniho Mar 09 '21 at 00:48

2 Answers2

2

file.Create(); leaves the file open, and returns a handle. Either close it first, or use it to write things to it.

Below code uses it:

public static void Save_map(int[,] p_temp_map_property, string p_filename)
{
    temp_map_property = p_temp_map_property;
    try
    {
        DirectoryInfo MapsDirectory = new DirectoryInfo("Maps");
        DirectoryInfo Map = new DirectoryInfo(@"Maps\" + p_filename);
        FileInfo file = new FileInfo(@"Maps\" + p_filename + @"\" + p_filename + ".txt");
        if (!MapsDirectory.Exists)
        {
            MapsDirectory.Create();
        }

        if (!Map.Exists)
        {
            Map.Create();
        }

        using (FileStream fileStream = file.Exists ? file.OpenWrite() : file.Create())
        using (StreamWriter sw = new StreamWriter(fileStream, false))
        {
            for (int n = 0; n < 140; n++)
            {
                for (int m = 0; m < 90; m++)
                {
                    sw.WriteLine(p_temp_map_property[n, m]);
                }
            }
        }
        
        MessageBox.Show("Map saved successfully!");
    }
    catch(Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}
Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
1

Try implementing the "using" statement as it closes the object after the instructions:

   string path = @"c:\MyTest.txt";
  FileInfo fi = new FileInfo(path);
  using (FileStream fs = fi.Create())
        {
            Byte[] info =
                new UTF8Encoding(true).GetBytes("This is some text in the file.");

            //Add some information to the file.
            fs.Write(info, 0, info.Length);
        }