zoukankan      html  css  js  c++  java
  • unity 在移动平台中,文件操作路径详解

    转载自:http://www.unitymanual.com/thread-23491-1-1.html

    相信大家在开发过程中,难免会保存一些文件在客户端进行本地化操作。如:配置文件,状态文件,Assetbundle文件等等...
    最近总有人问我:

    1. 保存了一个xml在客户端,能读取里面的数据,可是不能修改,甚至一修改就报错...
    2. 我在电脑上操作文件(xml、text、Assetbundle、json)都没问题,可是生成打包生成apk、ipa运行就出现各种问题,要么数据读不到,要么数据不能操作...

    这些问题的病症到底出现在什么地方?又该如何解决?其实,就是对文件保存的路径在平台间的适用性,有些路径在各个平台上是不能通用的。
    在此我对unity中路径操作做以下几种总结:

    • 在项目根目录中创建Resources文件夹来保存文件。

    可以使用Resources.Load("文件名字,注:不包括文件后缀名");把文件夹中的对象加载出来。
    注:此方可实现对文件实施“增删查改”等操作,但打包后不可以更改了

    • 直接放在项目根路径下来保存文件

    在直接使用Application.dataPath来读取文件进行操作。
    注:移动端是没有访问权限的。

    • 在项目根目录中创建StreamingAssets文件夹来保存文件

    1.可使用Application.dataPath来读取文件进行操作。

    #if UNITY_EDITOR
    string filepath = Application.dataPath +"/StreamingAssets"+"/my.xml";
    #elif UNITY_IPHONE
    string filepath = Application.dataPath +"/Raw"+"/my.xml";
    #elif UNITY_android
    string filepath = "jar:file://" + Application.dataPath + "!/assets/"+"/my.xml;
    #endif

    2.直接使用Application.streamingAssetsPath来读取文件进行操作。

    注:此方法在pc/Mac电脑中可实现对文件实施“增删查改”等操作,但在移动端只支持读取操作。

    • 使用Application.persistentDataPath来操作文件(

    该文件存在手机沙盒中,因为不能直接存放文件,
    1.通过服务器直接下载保存到该位置,也可以通过Md5码比对下载更新新的资源
    2.没有服务器的,只有间接通过文件流的方式从本地读取并写入Application.persistentDataPath文件下,然后再通过Application.persistentDataPath来读取操作。
    注:在Pc/Mac电脑 以及Android跟Ipad、ipone都可对文件进行任意操作,另外在IOS上该目录下的东西可以被iCloud自动备份

    • 使用Application.temporaryCachePath来操作文件

        操作方式跟上面Application.persistentDataPath类似。除了在IOS上不能被iCloud自动备份。

    下图是几种文件在Pc中路径的具体位置
           

    其实,在前面我已经发过一篇《Unity中的Path对应各平台中的Path》的文章,大家可以看看,详细了解下unity在移动平台中的可操作的具体路径。
    有直接给出各平台对应路径哟,方便调试查看。

    1.对文件的操作类FileHelper.cs,主要就是文流读取操作的一些东西(包括Assetbundle)

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

    /// <summary>
    /// 使用Application.persistentDataPath方式来创建文件,读写Xml文件.
    /// 注Application.persistentDataPath末尾没有“/”符号
    /// </summary>
    public class FileHelper: MonoBehaviour
    {

        /// <summary>
        /// 动态创建文件夹.
        /// </summary>
        /// <returns>The folder.</returns>
        /// <param name="path">文件创建目录.</param>
        /// <param name="FolderName">文件夹名(不带符号).</param>
        public string CreateFolder (string path, string FolderName)
        {
            string FolderPath = path + FolderName;
            if (!Directory.Exists (FolderPath)) { 
                Directory.CreateDirectory (FolderPath);
            } 
            return FolderPath;
        }

        /// <summary>
        /// 创建文件.
        /// </summary>
        /// <param name="path">完整文件夹路径.</param>
        /// <param name="name">文件的名称.</param>
        /// <param name="info">写入的内容.</param>
        public void CreateFile (string path, string name, string info)
        {
            //文件流信息
            StreamWriter sw;
            FileInfo t = new FileInfo (path + name);
            if (!t.Exists) {
                //如果此文件不存在则创建
                sw = t.CreateText ();
            } else {
                //如果此文件存在则打开
                sw = t.AppendText ();
            }
            //以行的形式写入信息
            sw.WriteLine (info);
            //关闭流
            sw.Close ();
            //销毁流
            sw.Dispose ();
        }

        /// <summary>
        /// 读取文件.
        /// </summary>
        /// <returns>The file.</returns>
        /// <param name="path">完整文件夹路径.</param>
        /// <param name="name">读取文件的名称.</param>
        public ArrayList LoadFile (string path, string name)
        {
            //使用流的形式读取
            StreamReader sr = null;
            try {
                sr = File.OpenText (path + name);
            } catch (Exception e) {
                //路径与名称未找到文件则直接返回空
                return null;
            }
            string line;
            ArrayList arrlist = new ArrayList ();
            while ((line = sr.ReadLine ()) != null) {
                //一行一行的读取
                //将每一行的内容存入数组链表容器中
                arrlist.Add (line);
            }
            //关闭流
            sr.Close ();
            //销毁流
            sr.Dispose ();
            //将数组链表容器返回
            return arrlist;
        }

        //写入模型到本地
        IEnumerator loadassetbundle (string url)
        {
            WWW w = new WWW (url);
            yield return w;
            if (w.isDone) {
                byte[] model = w.bytes;
                int length = model.Length;
                //写入模型到本地
                CreateassetbundleFile (Application.persistentDataPath, "Model.assetbundle", model, length);
            }
        }

        /// <summary>
        /// 获取文件下所有文件大小
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public int GetAllFileSize (string filePath)
        {
            int sum = 0;
            if (!Directory.Exists (filePath)) {
                return 0;
            }
            DirectoryInfo dti = new DirectoryInfo (filePath);
            FileInfo[] fi = dti.GetFiles ();
            foreach (FileInfo f in fi) {
                sum += Convert.ToInt32 (f.Length / 1024);
            }
            DirectoryInfo[] di = dti.GetDirectories ();
            if (di.Length > 0) {
                for (int i = 0; i < di.Length; i++) {
                    sum += GetAllFileSize (di.FullName);
                }
            }
            return sum;
        }

        /// <summary>
        /// 获取指定文件大小
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="FileName"></param>
        /// <returns></returns>
        public int GetFileSize (string FilePath, string FileName)
        {
            int sum = 0;
            if (!Directory.Exists (FilePath)) {
                return 0;
            } else {
                FileInfo Files = new FileInfo (@FilePath + FileName);
                sum += Convert.ToInt32 (Files.Length / 1024);
            }
            return sum;
        }

        void CreateassetbundleFile (string path, string name, byte[] info, int length)
        {
            //文件流信息
            //StreamWriter sw;
            Stream sw;
            FileInfo t = new FileInfo (path + "//" + name);
            if (!t.Exists) {
                //如果此文件不存在则创建
                sw = t.Create ();
            } else {
                //如果此文件存在则打开
                //sw = t.Append();
                return;
            }
            //以行的形式写入信息
            sw.Write (info, 0, length);
            //关闭流
            sw.Close ();
            //销毁流
            sw.Dispose ();
        }

        //读取本地AssetBundle文件

        IEnumerator LoadAssetbundleFromLocal (string path, string name)
        {
            print ("file:///" + path + "/" + name);
            WWW w = new WWW ("file:///" + path + "/" + name);
            yield return w;
            if (w.isDone) {
                Instantiate (w.assetBundle.mainAsset);
            }
        }

        /// <summary>
        /// 删除文件.
        /// </summary>
        /// <param name="path">删除完整文件夹路径.</param>
        /// <param name="name">删除文件的名称.</param>
        public void DeleteFile (string path, string name)
        {
            File.Delete (path + name);
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filesName"></param>
        /// <returns></returns>
        public bool DeleteFiles (string path, string filesName)
        {
            bool isDelete = false;
            try {
                if (Directory.Exists (path)) {
                    if (File.Exists (path + "\" + filesName)) {
                        File.Delete (path + "\" + filesName);
                        isDelete = true;
                    }
                }
            } catch {
                return isDelete;
            }
            return isDelete;
        }
    }
     
    2.随机操作类
    RandomHelper.cs
    using UnityEngine;
    using System.Collections;

    /// <summary>
    /// 随机操作类
    /// </summary>
    public class RandomHelper
    {
        private static char[] constant = {
            '0',
            '1',
            '2',
            '3',
            '4',
            '5',
            '6',
            '7',
            '8',
            '9',
            'a',
            'b',
            'c',
            'd',
            'e',
            'f',
            'g',
            'h',
            'i',
            'j',
            'k',
            'l',
            'm',
            'n',
            'o',
            'p',
            'q',
            'r',
            's',
            't',
            'u',
            'v',
            'w',
            'x',
            'y',
            'z',
            'A',
            'B',
            'C',
            'D',
            'E',
            'F',
            'G',
            'H',
            'I',
            'J',
            'K',
            'L',
            'M',
            'N',
            'O',
            'P',
            'Q',
            'R',
            'S',
            'T',
            'U',
            'V',
            'W',
            'X',
            'Y',
            'Z'
        };

        /// <summary>
        /// 字符串随机
        /// </summary>
        /// <param name="Length">要随机的位数</param>
        /// <returns></returns>
        public string GenerateRandomNumber (int Length)
        {
            System.Text.StringBuilder newRandom = new System.Text.StringBuilder (62);
            for (int i = 0; i < Length; i++) {
                newRandom.Append (constant [Random.Range (0, 62)]);
            }
            return newRandom.ToString ();
        }

        private static char[] constant1 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

        /// <summary>
        /// 数字随机
        /// </summary>
        /// <param name="Length">要随机的位数</param>
        /// <returns></returns>
        public string GenerateNumber (int Length)
        {
            System.Text.StringBuilder newRandom = new System.Text.StringBuilder (10);
            for (int i = 0; i < Length; i++) {
                newRandom.Append (constant1 [Random.Range (0, 10)]);
            }
            return newRandom.ToString ();
        }

        /// <summary>
        /// 字符串数组随机
        /// </summary>
        /// <param name="chars">数组</param>
        /// <param name="Length">随机的位数</param>
        /// <returns></returns>
        public string GetStrRandomSurname (string[] chars, int Length)
        {
            int count = chars.Length;
            System.Text.StringBuilder newRandom = new System.Text.StringBuilder (count);
            for (int i = 0; i < Length; i++) {
                newRandom.Append (chars [Random.Range (0, count)]);
            }
            return newRandom.ToString ();
        }

        /// <summary>
        /// 字符串*截取
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public string[] getStringToList (string str)
        {
            return str.Split ('*');
        }
    }
  • 相关阅读:
    java课后作业-4
    课堂练习
    16年9月27日上午
    《大道至简》第二章读后感
    《大道至简》-编程的精义读后感
    用Windbg来看看CLR的JIT是什么时候发生的
    如何调试什么时候SaveFileDialog会被Dispose
    针对C#程序做性能测试的一些基本准则
    要注意null合并运算符的优先级比+还要低
    实现GetHashCode时要遵循的规则
  • 原文地址:https://www.cnblogs.com/Yellow0-0River/p/4565251.html
Copyright © 2011-2022 走看看