• unity 在移动平台中,文件操作路径详解


    今天,这篇文章其实是个老生常谈的问题咯,在网上类似的文章也比比皆是,在此我只是做个详细总结方便大家能够更好、更快的掌握,当然,如有不足的地方 欢迎指正!!!


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

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

    这些问题的病症到底出现在什么地方?又该如何解决?
    其实,就是对文件保存的路径在平台间的适用性,有些路径在各个平台上是不能通用的。
    在此我对unity中路径操作做以下几种总结:
    一.在项目根目录中创建Resources文件夹来保存文件。
    可以使用Resources.Load("文件名字,注:不包括文件后缀名");把文件夹中的对象加载出来
    注:此方可实现对文件实施“增删查改”等操作,但打包后不可以更改了

    二.直接放在项目根路径下来保存文件
    在直接使用Application.dataPath来读取文件进行操作。
    注:移动端是没有访问权限的。

    三.在项目根目录中创建StreamingAssets文件夹来保存文件
    1.可使用Application.dataPath来读取文件进行操作。

    [C#] 纯文本查看 复制代码

    #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中路径的具体位置
    <ignore_js_op> 

    其实,在前面我已经发过一篇《Unity中的Path对应各平台中的Path》的文章,大家可以看看,详细了解下unity在移动平台中的可操作的具体路径。
    有直接给出各平台对应路径哟,方便调试查看。
    好了,unity路径的使用以及注意点都总结了,现在还是送点干料给大家吧,里面都有详细注释,都是开发中常用的东西

    1.对文件的操作类,主要就是文流读取操作的一些东西(包括Assetbundle)
    FileHelper.cs
    [C#] 纯文本查看 复制代码

    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
    [C#] 纯文本查看 复制代码

    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('*');
    }
    }
  • 相关阅读:
    执行存储过程 /创建存储过程:
    C# 设置本页面内所有TextBox为只读
    js 取得CheckBoxList的选中项的值
    把某些区域定为contentEditable="true"!
    如何在模态对话框中进行提交而不新开窗口?
    屏蔽 按键
    窗口与对话框之间的传值
    input button 的 onserverclick 事件
    checkbox js
    1.showModalDialog返回值给父窗口 2.winow.open开的窗口赋值给父窗口
  • 原文地址:https://www.cnblogs.com/harlan1009/p/4206142.html
Copyright © 2020-2023  润新知