Reputation:
Using Unity 5.6 here (I know, outdated =-(). How do I import a text file from outside the Assets folder? When I ask that, I do not mean through the Editor. It is going to be input entered by the user (my own custom modding system). I need to programmatically import the contents of the text file into a string variable.
Can anyone teach me how to do this?
Upvotes: 0
Views: 1765
Reputation: 90852
The problem with just doing something like
string pathToFile = @"C:\somepath\sometextfile.txt";
string textFromFile = System.IO.File.ReadAllText(pathToFile);
is that on many OS (e.g. Android, iOS, HoloLens) applications run in a sandbox with very limited access to the OSs' file system (if not explicitly granting).
So in Unity basically that is what the Application.persitentDataPath
is for. It can be accessed by both, the application and the OS (for example for changing a text file later).
To ease things up I usually would do this
private static string DataPath
{
get
{
#if UNITY_EDITOR
return Application.streamingAssetsPath;
#else
return Application.persistentDataPath;
#endif
}
}
This simply uses the folder <yourUnityProject>/Assets/StreamingAssets
while you are in the Editor in order to not bload
data into your PC's persistent data path while testing.
Later in a build it uses the App specific folder (depending on you OS - see link above).
In the Editor create the folder Assets/StreamingAssets
and place your .txt
file there.
You can read using
public static string ReadFromFile(string fileName)
{
var filePath = Path.Combine(DataPath, fileName);
//only needed if you choose option 1 in the next step
var copyFile = false;
// Check if file exists
if (!File.Exists(filePath))
{
// if the file does not exist (especially later in a build)
// you have multiple options
// I would decide between the following three
// OPTION 1
// read in the text from streaming assets instead
// the first time and create a new file from that content
filePath = Path.Combine(Application.streamingAssetsPath, fileName);
copyFile = true;
// Note: as fallback if this also does not exist use one of the other two options
// OPTION 2
// Alternatively you might rather want to instead create
// the file with some default content and change it later
WriteToFile(fileName, "some default content");
// OPTION 3
// simply throw an error an do nothing
Debug.LogErrorFormat("Error reading {0}\nFile does not exist!", filePath);
return null;
}
// Read in data from file
using (var file = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var streamReader = new StreamReader(file, Encoding.UTF8))
{
//this check is only needed for option 1
// otherwise only use the else part
if(copyFile)
{
var output = streamReader.ReadToEnd();
WriteToFile(fileName, output);
return output;
}
else
{
return streamReader.ReadToEnd();
}
}
}
}
and write using
public static void WriteToFile(string fileName, string content)
{
var filePath = Path.Combine(DataPath, fileName);
// Create file or overwrite if exists
using (var file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
using (var writer = new StreamWriter(file, Encoding.UTF8))
{
writer.Write(content);
}
}
Debug.LogFormat("Written to {0}", filePath);
}
You can put above code simply in a public static class
e.g. somthing like
public static class File
{
//...
}
than you can call it later from everywhere by simply using
File.ReadFromFile("MyFile.txt");
without having to reference.
Upvotes: 2
Reputation: 3410
You can read a text file with:
string pathToFile = @"C:\somepath\sometextfile.txt";
string textFromFile = System.IO.File.ReadAllText(pathToFile);
// Use the data
Upvotes: 1