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 (‘*‘);
    }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。