Get the FULL version

Unity: list files in a directory

Unity: list files in a directory thumbnail

This Unity3D programming post explains how to create a C# script that lists the files in a directory. Additionally, for the sake of completeness, this post also shows a rudimentary method that allows to select one of the files from the list and how to deal with some of the potential IO errors.

Here’s a screenshot of the code in action:

Unity - List files in a directory - example project screenshot

Please bear in mind that the script featured in this post won’t load (import) the selected file into the engine, it just displays its full path on a GUI Label. Don’t worry about copying and pasting the code, an example project is available for download at the end of this post (created using Unity version 4.0.1f2).

Here’s the code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;

public class ListFiles : MonoBehaviour 
{	
	///Variables for listing the directory contents  
	//A string that holds the directory path
	public string directoryPath; 
	//A List of strings that holds the file names with their respective extensions
	private List<string> fileNames;
	//A string that stores the full file path
	private string fullFilePath;

	//A string that stores the selected file or an error message
	private string outputMessage = "";
	////

	///Variables for displaying the directory contents
	private string dirOutputString = "";

	//The initial position of the scroll view
	private Vector2 scrollPosition = Vector2.zero;
	////

    ///Variables for the file number index input
	private string fileNumberString = "0";

	// Use this for initialization
	void Start () 
	{
		//Append the '@' verbatim to the directory path string
		this.directoryPath = @"" + this.directoryPath;

		try
        {
			//Get the path of all files inside the directory and save them on a List
            this.fileNames = new List<string>( Directory.GetFiles(this.directoryPath) );

			//For each string in the fileNames List 
            for (int i = 0; i < this.fileNames.Count; i++)
            {
				//Remove the file path, leaving only the file name and extension
				this.fileNames[i] = Path.GetFileName( this.fileNames[i] );
				//Append each file name to the outputString at a new line
				this.dirOutputString += i.ToString("D5") + "\t-\t" + this.fileNames[i] + "\n";
            }	
        }
		//Catch any of the following exceptions and store the error message at the outputMessage string
        catch (System.UnauthorizedAccessException UAEx)
        {
			this.outputMessage = "ERROR: " + UAEx.Message;
        }
        catch (System.IO.PathTooLongException PathEx)
        {
            this.outputMessage = "ERROR: " + PathEx.Message;
        }
		catch (System.IO.DirectoryNotFoundException DirNfEx)
		{
			this.outputMessage = "ERROR: " + DirNfEx.Message;
		}
		catch (System.ArgumentException aEX)
		{
			this.outputMessage = "ERROR: " + aEX.Message;
		} 
	}

	void OnGUI () 
	{
		//If the outputMessage string contains the expression "ERRROR: "
		if( outputMessage.Contains("ERROR: ") )
		{
			//Display an error message
			GUI.Label(new Rect(25, Screen.height-50, Screen.width, 100), this.outputMessage);
			//Force an early out return of the OnGUI() method. No code below this line will get executed.
			return;
		}

		//Display the directory path and the number of files listed
		GUI.Label(new Rect(25, 25, Screen.width, 100), "Directory: " + this.directoryPath + "   Files found: " + this.fileNames.Count);

		//Begin GUILayout
		GUILayout.BeginArea (new Rect (25, 50, Screen.width - 50, Screen.height - 100));
			//Create a scroll view.
			this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, GUILayout.Width(Screen.width - 50), GUILayout.Height(Screen.height - 100));
				//Display all of the file names on a TextArea
				GUILayout.TextArea(this.dirOutputString);
			//End of the scroll view
			GUILayout.EndScrollView();
		//End of the GUI Layout
		GUILayout.EndArea();

		//Display a simple label that asks for a file number as input
		GUI.Label(new Rect(25, Screen.height - 40, 250, 30), "Input a file number:");

		//Assign the value of the fileNumberString with the value typed on the TextField
		this.fileNumberString = GUI.TextField(new Rect(140, Screen.height - 40, 60, 30), this.fileNumberString, 5);

		//If the "Select File!" button has been pressed.
		if(GUI.Button(new Rect(210, Screen.height - 40, 150, 30), "Select file!"))
		{
			//Convert the fileNumberString into an Interger
			int fileIndex = int.Parse(this.fileNumberString);

			//If the number that has been passed as an input is out of range
			if(fileIndex >= this.fileNames.Count)
			{
				//Display an error message
				this.outputMessage = "Index out of range. Please enter a number between 0 and " + (this.fileNames.Count - 1).ToString();
				//Force an early out return of the OnGUI() method. No code below this line will get executed.
				return;
			}

			//Concatenate the directory path with the file name
			this.fullFilePath = this.directoryPath + @"\" + this.fileNames[fileIndex];

			//If the file exists
			if( File.Exists( this.fullFilePath ) )
			{
				//Save its full path, name and extension on the outputMessage string
				this.outputMessage = "Selected file:  " + this.fullFilePath;
			}
			else
			{
				//The file must have been removed since the last time the directory had been listed. Display an error message.
				this.outputMessage = "ERROR: FILE NOT FOUND!";
			}
		}

		//Display the selected file path or an error message at the bottom of the screen
		GUI.Label(new Rect(380, Screen.height - 40, Screen.width, 300), this.outputMessage);
	}
}

Right at the start, we must flag that the System.Collections.Generic and System.IO libraries are going to be used. The former allows us to simply type List<> as opposed to System.Collections.Generic.List<> (line 3). The latter is the library that contains the Directory class, the one that lists the files on a given directory (line 4).

There are seven member variables on the above code, but don’t worry, only the first three are directly responsible for listing the files. The other ones are just for selecting and displaying the file path, and also for the GUI controls.

The first one is a string, and it stores the directory’s full path (line 10). This variable’s visibility has been set to public, so that its value can be changed at the Inspector. The second one is a List (line 12). It’s where all the full paths of all files are being stored. The List is data structure that works just like an array with auto expanding capabilities and some other nifty features, that comes in handy when the required size of the array is not known. For more information on the List class, please refer to this link.

The third variable is a string that stores the full path of the selected file, including its name and extension (line 14). That’s all which is necessary to list the contents of a directory. But, for this example, there are some additional member variables that are worth explaining in detail, like the outputMessage string, which stores any IO errors that can occur when listing the contents of a directory or the selected file path. This string is the one displayed at the bottom of the screen. Next, there are three variables that will be responsible for displaying the list of files correctly, as well as for reading the user input on the TextField (lines 21 through 28).

Inside the Start() method, the directoryPath is preceded with the @ verbatim. It makes the backslash ( \ ) to be interpreted as a regular character on directory paths, and not as an escape character. In other words, without it, a path such as “C:\Folder\text.txt” would have to be be re-written as “C:\\Folder\\text.txt” (line 34).

Next, the Directory.GetFiles() method is called (line 39). It retrieves the file names (including each file’s full path and extension) as a string array. At this same line, the returned array is being used to initialize the filenames List. Since the GetFiles() method can throw exceptions, it has been surrounded with a try catch block (lines 36 through 66).

The for loop inside the try code block strips the full path from each string leaving only the file names, and dumps them into the dirOutputString added with their respective indexes (lines 42 through 48). This is being done for a better readability by displaying only the file names and their indexes at the file list, and not the full file path. Finally, there are four catch blocks that handles four types of different exceptions that the GetFiles() method can throw (lines 51 through 66). These catch blocks simply concatenate the character sequence “ERROR: “ with the exception error description and stores the result in the outputMessage.

Now, the only thing that’s left to do in this script is to display the file list and render the GUI elements that allows the user to select one file. This is a job for the OnGUI() method.

Inside this method definition, there’s an if statement that checks for the contents of the outputMessage member property (lines 72 through 78). If the character sequence “ERROR: ” is found, a Label is rendered at the bottom of the screen, which displays the exception and makes OnGUI() method return prematurely (lines 75 and 77). Therefore, if an error happened while listing the directory, there’s no pointing continuing the OnGUI() method execution, so it exits early.

Next, at line 81, the directory path and number of files listed are displayed. Lines 84 through 92 define a GUILayout area, so that the size of the ScrollView will match exactly the contents of the TextArea that displays file list. And that’s exactly what happens at line 88: the files with their respective indexes stored at the dirOutputString array are displayed in a TextArea. The GUILayout class is pretty useful, specially when you don’t know the exact size or number of the GUI elements. For more information on this class, please refer to this link and this other one.

The final four elements that are rendered on the screen are a pair of Label elements, a TextField and a Button. The first Label instructs the user to type the desired file index number on the TextField (lines 95 and 98).

The Button, when pressed, checks if the number entered at the TextField is within the fileNames index range. That being false, an error message is displayed to the user and, if that’s true, the code continues by concatenating directoryPath with the file name stored at the fileNames[index]. With that, the directory path is once again joined with the file’s respective name and extension given by the file index that the user has passed as an input (line 116).

This results in a string containing the full file path and extension, which can be passed as a parameter to the File.Exists() method on line 119. It’s pretty clear what this method does: it checks whether the file exists given by a path passed as a string. Moving on, if the file exists, the outputMessage will have the same value as the fullFilePath string preceded with the character sequence “Selected file: “. If it doesn’t exist, the outputMessage will store an error message (lines 122 and 127). The last GUI element rendered is a Label, that displays the contents of the outputMessage (line 132).

That’s it!

Additional Notes

There are two paths that are worth mentioning. The Application.DataPath and the “.” path. The Application.DataPath will point to the following folders, according each different platform, as found on Unity’s scripting reference:

  • Unity Editor: <path tp project folder>/Assets
  • Mac player: <path to player app bundle>/Contents
  • iPhone player: <path to player app bundle>/<AppName.app>/Data
  • Win player: <path to executablename_Data folder>
  • Web player: The absolute url to the player data file folder (without the actual data file name)
  • Flash: The absolute url to the player data file folder (without the actual data file name)

Although not listed on the official documentation, when running on Linux, the Application.Data should point to <path to executablename_Data folder> as in Windows. This is due to the fact that Application.DataPath is the path to parent directory of the Resources folder.

The path “.” (without the quotes, obviously) is the root directory of the aforementioned folders for every platform, but this path doesn’t work on the Web player or the Flash player.

Downloads

4 Comments to “Unity: list files in a directory”

  1. r61 says:

    Use Path.Combine for concatenating directory path with filename
    the @”\” separator does not work outside of windows, making the whole multiplatform Unity thing somewhat obsolete :)
    but thanks otherwise, kudos especially for catching the exceptions while listing the directory )

  2. Seyyed says:

    Hi…
    I’d put the cheat code in the game….
    Please help me.

    I’ve already asked you this question but did not answer….

  3. neliuz says:

    Hi, Looks good thanks!

    But is there a way to list the files in a folder somewhere online?
    Like f.eks an ftp-server or dropbox ?

    Thanks

  4. Wir können als lokaler Schlüsseldienst in Frankfurt schnelle Anfahrtszeiten und kurze Anfahrtswege garantieren, die allein von der Verkehrslage beeinflusst werden. Unsere Mitarbeiter
    haben den Umgang mit Schlössern und Sicherheitstechnik professionell erlernt und haben dadurch Zugriff auf schonende
    Öffnungstechniken.
    Deswegen sind unsere Preise auch so günstig und transparent gehalten. te Kosten oder Feiertags- bzw.
    Wochenendzuschläge.

Leave a Comment

Post Comments RSS