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来读取文件进行操作。

[C#] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
[/color][/font]
[font=微软雅黑][color=#9acd32]#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[/color][/font]
[font=微软雅黑][color=#9acd32]

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#] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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[i].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#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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('*');
}
}

(转) unity 在移动平台中,文件操作路径详解的更多相关文章

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

    今天,这篇文章其实是个老生常谈的问题咯,在网上类似的文章也比比皆是,在此我只是做个详细总结方便大家能够更好.更快的掌握,当然,如有不足的地方 欢迎指正!!! 相信大家在开发过程中,难免会保存一些文件在 ...

  2. net平台下c#操作ElasticSearch详解

    net平台下c#操作ElasticSearch详解 ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense Elasti ...

  3. ElasticSearch-.net平台下c#操作ElasticSearch详解

    ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...

  4. ElasticSearch第五步-.net平台下c#操作ElasticSearch详解

    前面我们讲解了关于ElasticSearch的安装配置,以及CRUD 本章我将讲解怎么使用c#操作ElasticSearch. 首先你需要一定的技术储备,比如:asp.net webapi,mvc,j ...

  5. c语言文件操作函数详解

    一.文件操作注意点: 1 打开文件时,如果打开方式加“+”,表示该文件可以“写” ; 2 退出程序一般用exit函数,正常退出参数为0,非正常退出参数为正零值 ; 3 文件的读写操作:按字符.字符串. ...

  6. day8文件操作作业详解

    1.day8题目 1,有如下文件,a1.txt,里面的内容为: 老男孩是最好的培训机构, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读 ...

  7. ASP文件操作(FSO)详解

    实例一:写入文件 语法 object.CreateTextFile([要建立的文件],[如存在,是否替代]) <% Set fs =Server.CreateObject("Scrip ...

  8. c#操作ElasticSearch5详解

    c#操作ElasticSearch详解 ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearc ...

  9. Multipart/form-data POST文件上传详解

    Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form ...

随机推荐

  1. [Angular 2] WebStorm - Managing Imports

    Some tips for import libaray by using webstorm: // Alt + Enter --> Auto Import // Ctrl + Alt + o ...

  2. qt 3d 绘图

    首先不得不说,要感谢北京邮电大学的阿科.感谢他慷慨的分享和极具科学态度的记录,将自己搜集到的众多资料收集整理发布,拯救众多苦逼寻找方案的程序员于苦海之中.因为最近接手新的项目,涉及到使用opengl做 ...

  3. 2.4 Git 基础 - 撤消操作

    2.4 Git 基础 - 撤消操作 撤消操作 任何时候,你都有可能需要撤消刚才所做的某些操作.接下来,我们会介绍一些基本的撤消操作相关的命令.请注意,有些撤销操作是不可逆的,所以请务必谨慎小心,一旦失 ...

  4. 将samba加入到windows域《转载》

    将samba加入到windows域 那什么是域呢? 一台Windows计算机,它要么隶属于工作组,要么隶属于域.所以说到域,我们就不得不提一下工作组,工作组是MS的概念,一般的普遍称谓是对等网. 工作 ...

  5. 先装Net Framework 后 装 IIS的处理办法

    先装IIS话,后面装Net Framework时候会自动注册 处理aspx和ashx等的处理扩展程序 先装Net Framework 后 装 IIS.扩展程序注册在命令:aspnet_regiis - ...

  6. .net framework版本以及服务器部署问题

    自己做了个官网,部署到服务器很多问题,发现targetframework为4.0,但是公司服务器的版本为:2.0.50727,但是公司一个项目用的lambda和linq就没有事,发现这个是3.5支持的 ...

  7. sealed 修饰符

    当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承. 在下面的示例中,类 B 从类 A 继承,但是任何类都不能从类 B 继承. class A {} sealed class B ...

  8. java equals 心得体会

    要记住最有用的一点: equals 在已经被系统定义好的类中 是已经被重写好了的 父类中的 equals方法是比较的两个对象是否指向同一引用 在被定义除了父类以外比较的是两个对象的内容 因此 人为定义 ...

  9. poj2378 树形DP

    C - 树形dp Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit ...

  10. Light oj 1030 概率DP

    D - Discovering Gold Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:32768 ...