Unity中在移动平台读写配置文件注意事项

在window版时应该不会有太大问题这里就不叙述了

直接说在移动端时需要注意的
一、文件路径
文件路径网上已经很多介绍了,这里就简单的说下
参考地址:https://blog.csdn.net/wangshipeng409/article/details/93046648

1、Resources路径
Resources文件夹下的资源不管是否有用,全部会打包进.apk或者.ipa,并且打包时会将里面的资源压缩处理。加载方法是Resources.Load(文件名),需要注意:文件名不包括扩展名,打包后这个文件夹下的东西只能读不能写
2、application.dataPath路径 这个返回的是程序的数据文件所在文件夹的路径,但是在移动端它是完全没用。
3、application.streamingAssetsPath路径
这个用返回路径为相对路径,适合设置一些外部数据文件的路径。在Unity工程的Assets目录下起一个名为“StreamingAssets”的文件夹即可,然后用application.streamingAssetsPath访问,这个文件夹中的资源在打包时会原封不动的打包进去,不会压缩,在PC/MAC中可实现对文件的“增删改查”等操作,但在移动端是一个只读路径。不能写入
4、application.persistentDataPath路径
这个返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件。这个路径可读、可写,但是只能在程序运行时才能读写操作,不能提前将数据放入这个路径。注意:如果在Android设置保存在沙盒中,那么就必须root以后才能用电脑取出文件,因此建议写入sdcard里。一般情况下,建议将获得的文件保存在这个路径下,例如可以从StreamingAsset中读取的二进制文件或者从AssetBundle读取的文件写入PersistentDatapath。
5、application.temporaryCachePath路径
此属性返回一个临时数据的缓存目录,跟application.persistentDataPath类似,但是在IOS上不能被自动备份。
6、/sdcard/…路径 表示Android手机的SD卡根目录。
7、/storage/emulated/0/…路径(这个路径我查找了好久……) 表示Android手机的内置存储根目录。

以上各路径中的资源加载方式都可以用WWW类加载,但要注意各个平台路径需要加的访问名称,例如Android平台的路径前要加"jar:file://“,其他平台使用"file://”。以下是各路径在各平台中的具体位置信息:
Android平台 application.dataPath : /data/app/xxx.xxx.xxx.apk
application.streamingAssetsPath :
jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
application.persistentDataPath : /data/data/xxx.xxx.xxx/files
application.temporaryCachePath : /data/data/xxx.xxx.xxx/cache IOS平台
application.dataPath :
application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
application.streamingAssetsPath :
application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
application.persistentDataPath :
application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
application.temporaryCachePath :
application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches
Windows Web Player application.dataPath : file:///D:/MyGame/WebPlayer
(即导包后保存的文件夹,html文件所在文件夹) application.streamingAssetsPath :
application.persistentDataPath : application.temporaryCachePath :

二、不要写在移动端不能执行的代码
例如下面这段代码,下面这段是在resources文件夹里创建文件夹,但是一旦打包后resources文件夹就会被压缩,就没办法执行创建的事件。然后会导致这个脚本崩溃不在执行本脚本以及后面的代码。因此如果还在这脚本后面还写有读写的代码的话都不会执行。因此有时没有读写出数据其实并不是读写不了,而是因为脚本崩了导致没有执行读写代码。

void Awake()
    {
        判断是否有文件夹如果没有就创建文件夹
        //DirectoryInfo myResources = new DirectoryInfo(Application.dataPath + "/Resources");
        //DirectoryInfo myInfos = new DirectoryInfo(Application.dataPath + "/Resources/VariousInfos");
        //if (myResources.Exists)
        //{
        //    if (!myInfos.Exists)
        //    {
        //        Directory.CreateDirectory(Application.dataPath + "/Resources/" + "VariousInfos");
        //    }
        //}
        //else
        //{
        //    Directory.CreateDirectory(Application.dataPath + "/" + "Resources");
        //    Directory.CreateDirectory(Application.dataPath + "/Resources/" + "VariousInfos");
        //}
    } 

三、读写权限问题
移动端都会有个读写权限问题,如果读写不了可以能是没有读写权限
例如安卓平台,对应的要在Assets/Plugins/Android文件夹下放入权限的xml文件:AndroidManifest.xml
AndroidManifest.xml文件会在打包一次后在对应的项目目录下有个Temp/StagingArea文件下自动生成一个放到Plugins/Android文件夹中就行了,但是因为是自动生成的因此里面只会有一些默认的参数,如果没有自动生成的参数需要自行添加
参数参考链接:https://blog.csdn.net/linli1991/article/details/81531134

暂时就这么多,各位大佬如果还有补充的欢迎评论留言

下面附上我写的通过.net读和streamwriter写入的代码
(以下的读写xml代码是能在安卓端正常运行读写的)
写的不怎么好,请不要喷,里面有一些数据结构是自定义的,我没有整个脚本复制过来,如果复制我写的函数代码改写时请自行改对应的数据结构

//将数据文件复制到Persistent路径下
    public static void SetFileToPersistent()
    {
        FileInfo info = new FileInfo(Application.persistentDataPath + "/PlayerInfo.xml");
        if (!info.Exists)
        {
            try
            {
                TextAsset ts = Resources.Load("VariousInfos/PlayerInfo") as TextAsset;
                string content = ts.text;
                using (FileStream fs = new FileStream(Application.persistentDataPath + "/PlayerInfo.xml", FileMode.OpenOrCreate))
                {
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                    {
                        sw.Write(content);
                        sw.Close();
                    }
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                Debug.Log(ex);
            }
        }
    }
 //创建xml文件和根节点(文件名,路径,根节点名)
    public  bool CreateXml(string FileName = null, string FilePath = null, string RootName = null, bool IsUseXmlSave = false)
    {
        if (FileName == null) FileName = "PlayerInfo.xml";
        if (FilePath == null) FilePath = Application.persistentDataPath + "/";
        if (RootName == null) RootName = "PlayerInfoDatas";

        if (!File.Exists(FilePath + FileName))
        {
            XmlDocument xml = new XmlDocument();
            XmlElement root = xml.CreateElement(RootName);
            xml.AppendChild(root);
            //保存xml文件
            if (IsUseXmlSave)
            {
                xml.Save(FilePath+FileName);
            }
            else
            {
                using (FileStream fs = new FileStream(FilePath + FileName, FileMode.OpenOrCreate))
                {
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                    {
                        sw.Write(xml.OuterXml);
                        sw.Close();
                    }
                    fs.Close();
                }
            }
            return true;
        }

        return false;
    }
//添加节点(玩家金币,关卡Id,是否解锁,拥有的图片碎片数量,一共的图片碎片数量,文件名,文件路径,根节点名)
    public  bool AddPlayerDataToXml(int PlayerGold = 0, bool IsRefreshItem = false, int TipsItems = 0, int MaxTipsItems = 3, int RefreshItemTime = 1800, string SaveTime = null, bool IsFirstGetChip = true, int LevelId = 1, bool IsUnlock = false, int OwnedImageChipNumber = 0, int MaxImageChipNumber = 1,bool IsShowChipTipps=false, int PlayGameNumber=0,string FileName = null, string FilePath = null, string RootName = null,bool IsUseXmlSave= false)
    {
        if (FileName == null) FileName = "PlayerInfo.xml";
        if (FilePath == null) FilePath = Application.persistentDataPath + "/";
        if (RootName == null) RootName = "PlayerInfoDatas";
        if (SaveTime == null) SaveTime = System.DateTime.Now.ToString();
        if (IsRefreshItem == true && TipsItems <= 0) { TipsItems = MaxTipsItems; IsRefreshItem = false; }
        //有文件时
        if (File.Exists(FilePath + FileName))
        {
            try
            {
                //读文件
                if (xml.OuterXml == null || xml.OuterXml == string.Empty)
                {
                    XmlReaderSettings st = new XmlReaderSettings();
                    st.IgnoreComments = true;
                    XmlReader reader = XmlReader.Create(FilePath + FileName, st);
                    xml.Load(reader);
                    reader.Close();
                }
                //获取根节点
                XmlNode root = xml.SelectSingleNode(RootName);
                //获取根节点下的第一个节点
                XmlNode rootChild = root.FirstChild;
                XmlNodeList elementList = null;
                XmlElement element = (XmlElement)root.FirstChild;
                //判断根节点下的第一个节点是否存在
                if (element != null)
                {
                    element.SetAttribute("PlayerGold", PlayerGold.ToString());
                    element.SetAttribute("IsRefreshItem", IsRefreshItem.ToString());
                    element.SetAttribute("TipsItems", TipsItems.ToString());
                    element.SetAttribute("MaxTipsItems", MaxTipsItems.ToString());
                    element.SetAttribute("RefreshItemTime", RefreshItemTime.ToString());
                    element.SetAttribute("SaveTime", SaveTime);
                    element.SetAttribute("IsFirstGetChip", IsFirstGetChip.ToString());
                    element.SetAttribute("IsShowChipTipps", IsShowChipTipps.ToString());
                    element.SetAttribute("PlayGameNumber", PlayGameNumber.ToString());
                    elementList = rootChild.ChildNodes;
                }
                else
                {
                    element = xml.CreateElement("PlayerDatas");
                    element.SetAttribute("PlayerGold", PlayerGold.ToString());
                    element.SetAttribute("IsRefreshItem", IsRefreshItem.ToString());
                    element.SetAttribute("TipsItems", TipsItems.ToString());
                    element.SetAttribute("MaxTipsItems", MaxTipsItems.ToString());
                    element.SetAttribute("RefreshItemTime", RefreshItemTime.ToString());
                    element.SetAttribute("SaveTime", SaveTime);
                    element.SetAttribute("IsFirstGetChip", IsFirstGetChip.ToString());
                    element.SetAttribute("IsShowChipTipps", IsShowChipTipps.ToString());
                    element.SetAttribute("PlayGameNumber", PlayGameNumber.ToString());
                    elementList = element.ChildNodes;
                }
                //获取根节点下的第一个节点下的所有节点
                foreach (XmlElement child in elementList)
                {
                    int id = 0; int.TryParse(child.GetAttribute("LevelId"), out id);
                    if (id == LevelId)
                    {
                        child.SetAttribute("LevelId", LevelId.ToString());
                        child.SetAttribute("IsUnlock", IsUnlock.ToString());
                        child.SetAttribute("OwnedImageChipNumber", OwnedImageChipNumber.ToString());
                        child.SetAttribute("MaxImageChipNumber", MaxImageChipNumber.ToString());

                        //保存到XML
                        if (IsUseXmlSave)
                        {
                            element.AppendChild(child);
                            root.AppendChild(element);
                            xml.AppendChild(root);
                            xml.Save(FilePath + FileName);
                        }
                        else
                        {
                            DeleteXmlFile();
                            using (FileStream fs = new FileStream(FilePath + FileName, FileMode.OpenOrCreate))
                            {
                                using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                                {
                                    sw.Write(xml.OuterXml);
                                    sw.Close();
                                }
                                fs.Close();
                            }
                        }

                        return true;
                    }
                }
                //当根节点下的第一个节点下没有对应的节点时创建节点保存数据
                XmlElement elementchild = xml.CreateElement("LevelId");
                elementchild.SetAttribute("LevelId", LevelId.ToString());
                elementchild.SetAttribute("IsUnlock", IsUnlock.ToString());
                elementchild.SetAttribute("OwnedImageChipNumber", OwnedImageChipNumber.ToString());
                elementchild.SetAttribute("MaxImageChipNumber", MaxImageChipNumber.ToString());

                //保存到XML
                if (IsUseXmlSave)
                {
                    element.AppendChild(elementchild);
                    root.AppendChild(element);
                    xml.AppendChild(root);
                    xml.Save(FilePath + FileName);
                }
                else
                {
                    DeleteXmlFile();
                    using (FileStream fs = new FileStream(FilePath + FileName, FileMode.OpenOrCreate))
                    {
                        using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                        {
                            sw.Write(xml.OuterXml);
                            sw.Close();
                        }
                        fs.Close();
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                Debug.Log(ex);
                if (output != null)
                    output.text = ex.ToString();
            }
        }
        return false;
    }
 //读取Xml文件数据
    public bool ReadXml(ref PlayerInfo Datas, Text test=null, string FileName = null, string FilePath = null, string RootName = null)
    {
        try
        {
            if (FileName == null) FileName = "PlayerInfo.xml";
            if (FilePath == null) FilePath = Application.persistentDataPath + "/";
            if (RootName == null) RootName = "PlayerInfoDatas";
            //读文件
            if (xml.OuterXml == null || xml.OuterXml == string.Empty)
            {
                XmlReaderSettings st = new XmlReaderSettings();
                st.IgnoreComments = true;
                XmlReader reader = XmlReader.Create(FilePath + FileName, st);
                xml.Load(reader);
                reader.Close();
            }
            if (test != null)
                test.text = "runing this fun";
            XmlNode root =  xml.SelectSingleNode(RootName);

            int.TryParse(root.FirstChild.Attributes.GetNamedItem("PlayerGold").Value, out Datas.PlayerGold);
            bool.TryParse(root.FirstChild.Attributes.GetNamedItem("IsRefreshItem").Value, out Datas.IsRefreshItem);
            int.TryParse(root.FirstChild.Attributes.GetNamedItem("TipsItems").Value, out Datas.TipsItems);
            int.TryParse(root.FirstChild.Attributes.GetNamedItem("MaxTipsItems").Value, out Datas.MaxTipsItems);
            int.TryParse(root.FirstChild.Attributes.GetNamedItem("RefreshItemTime").Value, out Datas.RefreshItemTime);
            System.DateTime.TryParse(root.FirstChild.Attributes.GetNamedItem("SaveTime").Value, out Datas.SaveTime);
            bool.TryParse(root.FirstChild.Attributes.GetNamedItem("IsFirstGetChip").Value, out Datas.IsFirstGetChip);
            bool.TryParse(root.FirstChild.Attributes.GetNamedItem("IsShowChipTipps").Value, out Datas.IsShowChipTipps);
            int.TryParse(root.FirstChild.Attributes.GetNamedItem("PlayGameNumber").Value, out Datas.PlayGameNumber);

            XmlNodeList elementList = root.FirstChild.ChildNodes;
            foreach (XmlElement child in elementList)
            {
                LevelDataBase tempImageData = new LevelDataBase();
                int.TryParse(child.GetAttribute("LevelId"), out tempImageData.LevelId);
                bool.TryParse(child.GetAttribute("IsUnlock"), out tempImageData.IsUnlock);
                int.TryParse(child.GetAttribute("OwnedImageChipNumber"), out tempImageData.OwnedImageChipNumber);
                int.TryParse(child.GetAttribute("MaxImageChipNumber"), out tempImageData.MaxImageChipNumber);

                Datas.LevelDatas[tempImageData.LevelId] = tempImageData;
            }
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
            if (output != null)
                output.text = ex.ToString();
        }

        return true;
    }
    //删除Xml文件
    public  bool DeleteXmlFile(string FileName = null, string FilePath = null)
    {
        if (FileName == null) FileName = "PlayerInfo.xml";
        if (FilePath == null) FilePath = Application.persistentDataPath + "/";

        if (File.Exists(FilePath + FileName))
        {
            File.Delete(FilePath + FileName);
            return true;
        }
        else
        {
            return false;
        }
    } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TenderRain。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值