This code will do the trick and works on PC, Mac, iOS and Android:
string fileName = "";
#if UNITY_IPHONE
string fileNameBase = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf('/'));
fileName = fileNameBase.Substring(0, fileNameBase.LastIndexOf('/')) + "/Documents/" + FILE_NAME;
#elif UNITY_ANDROID
fileName = Application.persistentDataPath + "/" + FILE_NAME ;
#else
fileName = Application.dataPath + "/" + FILE_NAME;
#endif
fileWriter = File.CreateText(fileName);
fileWriter.WriteLine("Hello world");
fileWriter.Close();
[edit]
Since Unity 3.3, it is no longer necessary to use platform-specific code for simple file I/O. Use Application.persistentDataPath to do the trick.
This code would replace the code above:
string fileName = Application.persistentDataPath + "/" + FILE_NAME;
fileWriter = File.CreateText(fileName);
fileWriter.WriteLine("Hello world");
fileWriter.Close();
Thanks, erique, for pointing this out on the Unity forum.
[/edit]
Hi,
Thnx for the input.
How would you actually make this work?
Lets say I want to print positions of an object every 0.5 second into a txt file?
Krodil, something like this should do the trick:
Note that I’m writing the x, y and z coordinates separately. Basically, the way you write out data to a file is entirely up to you. If you want a more convenient way saving data you can use the PlayerPrefs class (or PreviewLabs.PlayerPrefs if you’re targeting iOS or android) in conjunction with ArrayPrefs.
Hey i have saved an image to persistentdatapath. How to I retrieve that image?
Hi Pat, you’ll have to use the WWW class for this:
Hi,
A great blog. No wonder you guys prototype fast. Simple clear way to do it for ios.
I do have one question though, the above relates to strings. Would it be possible to load/save ints, booleans and floats using this method, or is it limited to strings?
Thanks 🙂
Hi Hippocoder. Sure you can also save other data types. If you want to save in a human-readable text format, you have to cast these types to string when writing, and the other way around when reading. This should be okay for most uses. Please note that certain data types may be converted to strings differently depending on the language settings of the computer your game is running on. As far as I know, this only occurs for stand-alone games on mac and PC. To take care of it, you can override the language settings using the following line of code:
If you don’t care about reading / editing your saved data in a text editor, then you can also save your ints, booleans etc. in binary format. For this you could use methods as File.Create() and FileStream.Write().
Hey Bernard,
Thx for help, when I save / load on ipad I get a massive freeze is there a way to load while continuing animating the onscreen objects?
Cheers,
Tim
Hi Captnemo. You can use the WWW class in combination with local file URLs to avoid freezing your game. The line of code to create the WWW object is mentioned a bit higher in the comments, in a reply to Pat. You can use the isDone property every frame to know when the loading has finished, or use the yield statement as explained in the Unity documentation. The frame rate may drop a bit while loading; if this is an issue you can change the threadPriority value to a lower priority.
hey there, nice blogpost
just small correction
Path.Combine( Application.persistentDataPath, FILE_NAME);
should/might be used when creating filesystem path 🙂
hello all,
i am new in unity. and i want to create local database for iphone in unity3D game.
i had tried a lot with different blogs but no one work for iphone.
i am able to do that for MAC.(i am using Sqlite DataBase Browser for this)
can any one tell me the way to create/read/write Local database…
I’ve sent you a mail, to avoid going off topic too far.
If all you’re looking for is a convenient way of storing data and don’t really need to store it in a relational way, I’d reccomend to use the PreviewLabs.PlayerPrefs class, which will give you an easy-to-use and fast hashmap type of storage system. It’s available for free at http://www.previewlabs.com/writing-playerprefs-fast/.
hello Bernard
Thanks for the quick reply..
i just want to create a local database to read and write dynamic data.
and i am querious to know how we can do this in unity.
You could try siaqodb (there’s a version specifically for Unity3D, but it requires using LINQ instead of SQL to write queries).
Hi Bernard
Great thread
It is strange that there is no documentation about file I/O in unity scripting reference.
How do you save a http://www.texture to persistentDataPath ?
Actually I want to cache downloaded images, in stead of re downloading them each time I start unity. Do you know an equivalent way as http://WWW.LoadFromCacheOrDownload that only works with an AssetBundle and not with images.
Hi Franck. You can use File.WriteAllBytes to write the bytes from a WWW object to a file.
As the saved file won’t be in your Resources folder, you’ll have to use the WWW object again in combination with a local file URL in order to load the file back into memory for later use (using a local file URL is explained higher in the comments).
Let’s say you created an object ‘loadingImageWWW’. In your Update, you’ll be checking whether the download has completed, and if so, store the downloaded bytes in a file:
Note that this can be done with any type of file.
Hi Bernard, Thanks
I wonder how could I check if the file exists or not on the persistentDataPath?
(ex if file exist load from DataPath, else load from internet and write to DataPath)
How can I clear the cache (ex : del *.jpg) ?
Actually, you can use the .NET APIs for all file handling. Most is in the System.IO namespace, mainly in the File class.
For instance, to check if a file exists, you can use File.Exists.
Alternatively, you could use Unity’s PlayerPrefs class (or our improved version of it) to remember that the file has been saved.
does Application.persistentDataPath and File I/O work with unity web player ?
I got the following error :
BCE0019: ‘bytes’ is not a member of ‘UnityEngine.Texture2D’.
Did I miss Something ?
The ‘bytes’ array is a member of the WWW class…
As far as I know, it’s not possible to write files using the web player without a special per-title Unity license. Small amounts of data can be saved using Unity’s PlayerPrefs class.
I know Flash supports using a limited amount of local storage; perhaps this will be available for the upcoming Flash export option in Unity (due in a few weeks or months).
Ok I’m using the ios version for now
the images are well saved in the persistentDataPath
but I got this error loading them :
You are trying to load data from a www stream which had the following error when downloading.
malformed
var fileName : String = Application.persistentDataPath + “/ico_” + AppTextureLoading.AppId[nb] + “.jpg”;
var www : WWW;
if (File.Exists(fileName))
{
www = new WWW(fileName);
yield www;
}
if (www.isDone)
{
var tex = http://www.texture; // ERROR HERE
}
It’s strange, because sometime, one or two textures are well loaded, but almost no.
oups forgoten to add “file://”
www = new WWW(“file://”+fileName);
Worked perfectly
Thanks
Hi Bernard I found a way to delete all the files:
I just have to create a “Cache” directory and save my files there using :
Directory.CreateDirectory(Application.persistentDataPath +”/Cache”);
And to delete all the files:
var IconsFiles = Directory.GetFiles(Application.persistentDataPath +”/Cache”);
for (var iconsFiles in IconsFiles)
{
File.Delete(iconsFiles);
}
Directory.Delete(Application.persistentDataPath +”/Cache”);
On Android, I get:
Exception!System.IO.IsolatedStorage.IsolatedStorageException: Could not find a part of the path “/mnt/asec/com.xxx.yyy/pkg.apk/zzz.txt”
Every time I try to write to the filesystem. Is there some weird permissions setting somewhere for Android that doesn’t exist on iOS? This code works fine on iOS and the Editor.
Im looking for something like this for my app on android. I’m trying to create two scenes (One for writing to textfile and the other to read). The “write” scene will be used to add a user defined text to each of my prefabs. So, on this scene will be a list of the prefabs, and a text form to edit each one.
The second scene “Read” will call each prefab and show the user defined text (from the “write” scene.
Obviously i don’t want a ton of text files to read from…so how can i get it to read individual strings in the text file?
Hi Daz,
To avoid a lot of work, I suggest to use the PlayerPrefs class. This is a built in class of the Unity Engine, but we made an optimized version of it, especially interesting for Android. It’s freely available – see http://www.previewlabs.com/writing-playerprefs-fast/
In your example, you would use a different key for each of the values you want to store.
Having a devil of a time with saving files on Android. I Debug.Log where it thinks it will save:
Debug.Log (“Saving to:”+Application..persistentDataPath+”/myfile.png”);
and it fail to save it, my log says:
Saving to:/data/data/com.mycomp.myapp/files/myfile.png
then
Failed to open file at path: /data/data/com.mycomp.myapp/data/data/com.mycomp.myapp/files/myfile.png
which is REALLY messed up.
I also get /data/data/com.mycomp.myapp/data/data/com.mycomp.myapp/files/myfile.png
Looks like a Unity bug. Report it to Unity.
Hmm, no, problem for me was that Application.CaptureScreenshot on Android will not accept an absolute path, effectively prepending Application.persistentDataPath to whatever you pass to it.
Hi, I realize this is old but I have a question. Say I have preexisting txt or bin data files. I do not save to them while on the iOS device but I read from them. Where in unity to I place them exactly? Do I need to put the txt files in Resources and load them with Resources.load? PS> using text assets is not a good option for me. Thanks!
NMD: You’ll need to place the files in the folder you see if you do a "Debug.Log(Application.persistentDatapath);".
If you’re running your game in the Unity editor on Windows, it’s should be in the following folder:
C:Users<your user name>AppData
If you’re running your game in the editor on OS X, it’s somewhere in ~/Library/Caches/<Company Name>/<Product Name as configured in the Unity project>. The ‘~’ stands for your home folder.
Note that these folders are usually hidden folders, so if you’re using Explorer (Windows) or Finder (OS X) to access these, you need enable viewing hidden folders.
hi
i wand to read an acces database on android then i copy my data base files in AssetsStreamingAssets folder (when i export my APK file and i open my file with winrar ican see it in my apk file)
an i try to read it with this kind of path :
MyFinalpath= Application.persistentDataPath+ “/Database1.mdb”;
but it does not work i can not see my filed in my installed apk on my tablet what should i do?
(i can see result when i play on pc)
my codes :
//////////////////
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Data;
using System.Data.Odbc;
public class ACCESSREADER : MonoBehaviour {
public DataTable dtYourData;
// public static String MyFinalpath=Application.streamingAssetsPath ;
public static String MyFinalpath ;
// Use this for initialization
void Start () {
MyFinalpath= Application.persistentDataPath + “/Database1.mdb”;
Debug.Log(MyFinalpath);
// Access 2007 format
// readMDB(Application.dataPath + “/Database2.accdb”);
// readMDB(MyFinalpath+”/Database2.accdb”);
// Access 2003 format
readMDB(MyFinalpath);
}
// Update is called once per frame
void Update () {
}
// set this to internal so that we can hook into it from other parts of the program
internal void readMDB( string filetoread)
{
string con = “Driver={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=”+filetoread;
Debug.Log(con);
string yourQuery = “SELECT * FROM PlayersQuery”;
// our odbc connector
OdbcConnection oCon = new OdbcConnection(con);
// our command object
OdbcCommand oCmd = new OdbcCommand(yourQuery, oCon);
// table to hold the data
dtYourData = new DataTable(“YourData”);
try
{
// open the connection
oCon.Open();
// lets use a datareader to fill that table!
OdbcDataReader rData = oCmd.ExecuteReader();
// now lets blast that into the table by sheer man power!
dtYourData.Load(rData);
// close that reader!
rData.Close();
// close your connection to the database query!
oCon.Close();
// wow look at us go now! we are on a roll!!!!!
// lets now see if our table has the data in it, shall we?
}
catch (Exception ex)
{
Debug.Log(ex.ToString());
}
finally
{
if (oCon.State != ConnectionState.Closed)
oCon.Close();
oCon.Dispose();
}
if(dtYourData.Rows.Count > 0)
{
// do something with the data here
// but how do I do this you ask??? good question!
for (int i = 0; i < dtYourData.Rows.Count; i++)
{
// for giggles, lets see the column name then the data for that column!
Debug.Log(dtYourData.Columns[0].ColumnName + " : " + dtYourData.Rows[i][dtYourData.Columns[0].ColumnName].ToString() +
" | " + dtYourData.Columns[1].ColumnName + " : " + dtYourData.Rows[i][dtYourData.Columns[1].ColumnName].ToString() +
" | " + dtYourData.Columns[2].ColumnName + " : " + dtYourData.Rows[i][dtYourData.Columns[2].ColumnName].ToString() +
" | " + dtYourData.Columns[3].ColumnName + " : " + dtYourData.Rows[i][dtYourData.Columns[3].ColumnName].ToString()
);
}
}
}
}
Will the code above work for screen shots? We want to do a simple screenshot to the iOS/Android camera roll. Thank you!
@Shayan:
On Android, the assets inside the StreamingAssets folder are compressed and added to the apk file. You can’t access these files directly, you can only load them trough a WWW call.
I see the accessDriver expect a path to a file so this will not work together with the WWW object. I think you will first have to copy the file from the StreamingAssets folder to a file in the Application.persistentDataPath folder. This should only happen once. You can then connect to the copy. Here is an example on how this could be done.
@Vicky
You will need a native plugin to save images into the iOS/Android camera roll.
We have used the etcetera plugins from Prime31 to accomplish this in our projects.
Hey I’m making a Android camera application and I’m having some trouble saving the image to the SD card. I’m quite new to coding but I’m using Unity which makes it a lot easier. When I test the application inside Unity the saving works fine but I had to make a file called “SnapShots”. So how do I save an image to my android sd card without having to create a file on the android device manually (and having the android gallery automatically pick it up and put it in the gallery)
Heres my C# Code:
Hi Jeremy,
If you have troubles with saving files because the parent directories don’t exist, you can try the solution suggested at:
http://stackoverflow.com/questions/2955402/how-do-i-create-directory-if-doesnt-exist-to-create-file
Thank you! Ill post another comment letting you know how it goes! 😀
Hello. I am looking to create a fairly substantial dialog-tree system for my games, which will be very dialog heavy. My intentions are to deploy to iOS, Android, Windows Phone, and Windows. I am not sure what solution would best server my purposes. My feeling is that JSON or XML files would work best, but I do not know if this causes any problems for mobile platforms. Or would the PlayerPrefs solution mentioned above be a feasible solution for this? Or something else?
hi,
I work on a project, in which i will download audio file from server on persistent data path and
its download well and work on android but not is IOS, please help me lo play audio file.
/* load audio file */
IEnumerator LoadAudioFile(string fileName) {
WWW www = null;
AudioClip myAudioClip = null;
string path = Application.persistentDataPath + “/Audio/”+fileName;
www = new WWW(“file://”+path);
myAudioClip = http://www.audioClip;
while (!myAudioClip.isReadyToPlay)
yield return www;
tempClip = http://www.GetAudioClip(false);
StartCoroutine (PlayEffect());
}
and ios debug log is:- Path= file:///var/mobile/Applications/5D0EA96C-31C6-4351-AAE7-23A0B2AC85AE/Documents/Audio/compound_389.wav
please help me asap.
hi 🙂 im using ur playerprefs in JS script, everything works prettymuch well, only problem is im making scoore and saving it as integer, then in other ui obj im geting that int and setting that ui text render it… but i get 0 vallue allways, with old playerprefs it was working, i had put import PreviewLabs.PlayerPrefs; in top of every file using playerprefs and allso start each line with PreviewLabs.PlayerPrefs… :/ what is the prblem, i read coments and found that someone had this problem to but no sollution
Thank you 🙂
Hello,
I am working on unity3d and i want to export the data in the form of PDF. So, how can i do that and while saving the PDF, there should be dialog box like where i want to store the PDF file.