Unity3D学习笔记(二十五):文件操作
文件是什么?
存储在硬盘上的最后的节点。
文件夹是什么?
文件的上级单位称为文件夹。
文件夹的基本结构?
文件夹是层级化结构的,对于同级的文件夹不可以重名,父文件夹和子文件夹可以同名》
IO:I是Input输入,O是Output输出
IO流:指数据的输入输出流。
命名空间:using System.IO;
Directory文件夹类:操作文件夹的类,静态类,静态方法,工具类,不能实例化,通过类名调用
API:Directory.GetCurrentDirectory();//获取当前应用程序(工程)的绝对路径
API:Directory.Exists()//;判断指定的文件夹路径是否存在
API:Directory.CreateDirectory();//创建文件夹
API:Directory.Delete();//删除文件夹
API:Directory.Move();//移动文件夹,可以通过这种方式来实现文件夹的重命名
API:获取指定路径下所有文件夹和文件的绝对路径的数组
API:Directory.GetFiles();//获取文件夹下的所有文件
API:Directory.GetDirectories();//获取指定路径下的所有文件夹
API:获得创建时间,最后访问和最后修改时间
GetCreationTime,GetLastAccessTime,GetLastWriteTime
API:设置创建时间,最后访问和最后修改时间
SetCreationTime,SetLastAccessTime,SetLastWriteTime
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LessonFile : MonoBehaviour { // Use this for initialization void Start () { //判断文件是否存在 if (File.Exists(@"D:\桌面\Directory\Text.txt")) { Debug.Log("文件存在"); } //删除文件,注意文件的后缀 File.Delete(@"D:\桌面\Directory\Text.txt"); //移动文件,可以通过这种方式来对文件进行重命名,注意后缀名 //文件名可以不同,后缀名也可以不同(改变文件的类型) File.Move(@"D:\桌面\Directory\JPG.jpg", @"D:\桌面\Directory\PNG.png"); //拷贝文件,前后名字可以不一致,后缀名也可以不一致 File.Copy(@"D:\桌面\Directory\PNG.png", @"D:\桌面\Directory\GIF.gif"); //创建文件 FileStream fsCreate = File.Create(@"D:\桌面\Directory\Create.txt"); fsCreate.Close();//关闭文件流 } // Update is called once per frame void Update () { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LessonDirectory : MonoBehaviour { // Use this for initialization void Start () { //获取当前应用程序(工程)的绝对路径 Directory.GetCurrentDirectory(); Debug.Log(Directory.GetCurrentDirectory()); //@取消转义 string str = @"\"; Debug.Log(str); //判断指定的文件夹路径是否存在 if (Directory.Exists(@"D:\桌面\Directory")) { Debug.Log("Directory文件夹存在"); } //创建文件夹 Directory.CreateDirectory(@"D:\桌面\Directory\File1"); Directory.CreateDirectory(@"D:\桌面\Directory\File2"); //删除文件夹,对于文件夹里有文件的情况,如果使用一个参数去删除会报错 //对于文件夹里有文件的情况,我们使用重载的第二个参数传入true表示强制删除 Directory.Delete(@"D:\桌面\Directory\File1"); //移动文件夹,可以通过这种方式来实现文件夹的重命名 Directory.Move(@"D:\桌面\Directory\File2", @"D:\桌面\Directory\File3"); //获取文件夹下的所有文件 string[] files = Directory.GetFiles(@"D:\桌面\Directory"); foreach (var item in files) { Debug.Log(item); } //获取指定路径下的所有文件夹 string[] directorys = Directory.GetDirectories(@"D:\桌面"); foreach (var item in directorys) { Debug.Log(item); } } // Update is called once per frame void Update () { } }
@取消转义
str="\n":默认情况下,“\”在字符串中表示转义符
str=@"\n":如果一个字符串前加了@符号,表示取消转义;那么“\”将作为字符存在,不代表转移符
"\\":单斜杠“\”在字符串里是转义符,双斜杠"\\"在字符串里表示单斜杠“\”
File文件类
命名空间:using System.Text;
API:File.Create();//创建文件
API:File.Open();//打开文件
FileMode
----Open:打开一个已有的文件,保证文件路径是正确的
----Create:创建一个新文件,如果该文件已经存在,那么新文件覆盖掉旧文件
----CreateNew:创建一个新文件,但是得保证该文件是不存在的,如果存在会报错
----OpenOrCreate:如果存在即打开文件,如果不存在即创建新文件
----Append:打开文件,并且文件的游标在最后,追加模式
创建文件,打开文件,返回的都是文件流
打开一个文件流之后,一定要关闭,否则会占用
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LessonFile : MonoBehaviour { // Use this for initialization void Start () { //判断文件是否存在 if (File.Exists(@"D:\桌面\Directory\Text.txt")) { Debug.Log("文件存在"); } //删除文件,注意文件的后缀 File.Delete(@"D:\桌面\Directory\Text.txt"); //移动文件,可以通过这种方式来对文件进行重命名,注意后缀名 //文件名可以不同,后缀名也可以不同(改变文件的类型) File.Move(@"D:\桌面\Directory\JPG.jpg", @"D:\桌面\Directory\PNG.png"); //拷贝文件,前后名字可以不一致,后缀名也可以不一致 File.Copy(@"D:\桌面\Directory\PNG.png", @"D:\桌面\Directory\GIF.gif"); //创建文件 FileStream fsCreate = File.Create(@"D:\桌面\Directory\Create.txt"); fsCreate.Close();//关闭文件流 } // Update is called once per frame void Update () { } }
字节数组的传递是引用传递,改变当前文本的值会改变原有文本的值
读取文本文件时:解析字节数组时,需要使用对应的编码格式
字符编码种类
1、ASCII:ASCII码是西欧编码的方式,采取7位编码,所以是2^7=128,共可以表示128个字符,包括34个字符,(如换行LF,回车CR等),其余94位为英文字母和标点符号及运算符号等。
2、GB2321:GB2312 是对 ASCII 的中文扩展。兼容ASCII。
3、GBK:GBK 兼容ASCLL 兼容 GB2312 是GB2312的扩展。
4、Unicode:Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。
5、UTF-8:UTF-8以字节为单位对Unicode进行编码。
乱码:
1、使用了不同的编码格式进行解析文本
2、读取的内容少了,也有可能出现乱码
UTF-8,3个字节表示1个汉字,缺少3个字节会少1个汉字,缺少2个字节会乱码
关闭文件的问题:代码运行中出错,没有执行最后关闭文件的代码
Try Catch:
先依次执行Try语句块的代码,一但发现有错误,不会继续执行Try里的代码,直接跳到Catch块里依次执行Catch块里的代码,Catch块里的代码执行完继续向下执行。如果Try里的代码没有错误,不会执行Catch里的代码,直接执行Catch块后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LessonTryCatch : MonoBehaviour { public GameObject obj; // Use this for initialization void Start () { Debug.Log("开始try"); try { Debug.Log("try 语句块!"); Debug.Log(obj.name);//这句话一定会报错,跳转catch Debug.Log("打印名字"); } catch (System.Exception e) { Debug.Log("catch 语句块!" + e); Debug.Log("错误信息:" + e); Debug.Log(obj.name);//如果catch报错,之后的代码都不会执行 } Debug.Log("结束try"); } // Update is called once per frame void Update () { } }
作业:读取文本内容,显示在UI的text组件上,并实现内容滚动
文本位置调整
文本自动扩容
读取文件
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Text; using UnityEngine.UI; public class LessonHomework : MonoBehaviour { public const string filePath = @"D:\桌面\1.txt"; private Text text; private void Awake() { text = transform.Find("Mask/Text").GetComponent<Text>(); } // Use this for initialization void Start () { FileStream fs = File.Open(filePath, FileMode.Open); try { byte[] bytes = new byte[fs.Length]; int ret = fs.Read(bytes, 0, (int)fs.Length); string str = Encoding.UTF8.GetString(bytes); text.text = str; } catch (System.Exception e) { Debug.Log(e.ToString()); } fs.Close(); } // Update is called once per frame void Update () { } }
写入文件
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Text; public class LessonWriteFile : MonoBehaviour { public const string filePath = @"D:\桌面\Directory\ReadFile.txt"; // Use this for initialization void Start () { //string filePath1 = Directory.GetCurrentDirectory(); //filePath1 = filePath1 + "\\Directory\\"; //写入文本文件 //1、打开文件 FileStream fs = File.Open(filePath, FileMode.Open); // FileStream fs = File.Open(filePath, FileMode.Append);//追加模式 Debug.Log("游标的位置:" + fs.Position); //第一个参数:向前移或向后移多少位,第二个参数:从什么位置开始移动 //对于想要把游标移动到文件的末尾 //方法1 fs.Seek(fs.Length, SeekOrigin.Begin); //方法2 fs.Seek(fs.Length - fs.Position, SeekOrigin.Current); //方法3 fs.Seek(0, SeekOrigin.End); //对于想要把游标移动到文件的开始 //方法1 fs.Seek(0, SeekOrigin.Begin); //方法2 fs.Seek(-fs.Position, SeekOrigin.Current); //方法3 fs.Seek(-fs.Length, SeekOrigin.End); Debug.Log("游标的位置:" + fs.Position); //为了保证文件打开之后一定能关闭,文件操作写在Try Catch里 try { //2、把要写入的内容转成字节数组 string str = "做一只快乐的小鱼苗~"; byte[] bytes = Encoding.UTF8.GetBytes(str); //3、写入文件 //第一个参数:写入文件的内容转换成的字符串 //第二个参数:从字节数组中的第几位开始写入 //第三个参数:从字节数组中写入多少位 fs.Write(bytes, 0, bytes.Length); } catch (System.Exception e) { Debug.Log(e.ToString()); } //最终关闭文件流 fs.Close(); } // Update is called once per frame void Update () { } }
文本读写器
文本读
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LessonStreamReader : MonoBehaviour { public const string filePath = @"D:\桌面\Directory\ReadFile.txt"; // Use this for initialization void Start () { //文本读写器 //打开文件,保证路径是正确的,有效的 StreamReader sr = new StreamReader(filePath, System.Text.Encoding.UTF8); try { //string str = sr.ReadLine();//只读取一行。 string str = sr.ReadToEnd();//从开始读到结尾 Debug.Log("读取的内容: " + str); } catch (System.Exception e) { Debug.Log(e.ToString()); } //最后一定要关闭文件 sr.Close(); } // Update is called once per frame void Update () { } }
文本写,不能操作游标,如果不使用追加模式,默认清空原有内容,重新写入
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LessonStreamWrite : MonoBehaviour { public const string filePath = @"D:\桌面\Directory\ReadFile.txt"; // Use this for initialization void Start () { //文本读写器 //1、打开文件 //这个重载,会把文件内容全部清除,重新写入内容 //StreamWriter sw = new StreamWriter(filePath); //这个重载,是追加模式,第二个参数指定是否追加,第三个参数是指定编码格式 StreamWriter sw = new StreamWriter(filePath, true, System.Text.Encoding.UTF8); try { sw.Write("Hello World!"); } catch (System.Exception e) { Debug.Log(e.ToString()); } //最后一定关闭文件 sw.Close(); } // Update is called once per frame void Update () { } }
文件拷贝
小文件的直接拷贝
大文件的线程拷贝
1、使用多线程的方式,防止文件过大,卡死主线程
2、多线程里面不能改变需要渲染操作的值(例如改变slider的进度条的值)
3、多线程里使用while循环,要设置跳出循环的条件
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Threading; public class LessonCopyFile : MonoBehaviour { public UnityEngine.UI.Slider slider; public const string sourceFilePath = @"D:\桌面\1.rar"; public const string targetFilePath = @"D:\桌面\2.rar"; private float maxValue = 1f; private float currentValue; private bool isStop = false; // Use this for initialization void Start () { //小文件的拷贝 //CopyFile(sourceFilePath, targetFilePath); //大文件的拷贝 //TestCopyFile(); //大文件的线程拷贝 //1.申请一个Thread的对象 Thread th = new Thread(TestCopyFile); //2.启动这个线程 th.Start(); } // Update is called once per frame void Update () { //滑动条赋值 slider.normalizedValue = currentValue / maxValue; } private void OnDestroy() { isStop = true; } //小文件的拷贝 void CopyFile(string sourceFile, string targetFile) { //拷贝,就把源文件的内容写入到新的文件中 //1.读取源文件的内容 FileStream source = File.Open(sourceFile, FileMode.Open); byte[] bytes = new byte[source.Length]; try { //读取内容 source.Read(bytes, 0, bytes.Length); } catch (System.Exception e) { Debug.Log(e.ToString()); } source.Close(); //2.写入新文件 FileStream target = File.Open(targetFile, FileMode.Create); try { //写入新文件 target.Write(bytes, 0, bytes.Length); } catch (System.Exception e) { Debug.Log(e.ToString()); } target.Close(); } void TestCopyFile() { Debug.Log("开始拷贝"); CopyBigFile(sourceFilePath, targetFilePath); Debug.Log("拷贝结束"); } void CopyBigFile(string sourceFile, string targetFile) { FileStream source = new FileStream(sourceFile, FileMode.Open); FileStream target = new FileStream(targetFile, FileMode.Create); byte[] bytes = new byte[100];//限制每次拷贝100 * 1024个字节大小的内容 maxValue = source.Length; try { long readCount = 0; //必须保证所有的内容都写入到另一个文件中了, 跳出循环 //只要保证每次读取的长度的累加值 大于等于 文件流的大小 while (readCount < source.Length) { int length = source.Read(bytes, 0, bytes.Length); target.Write(bytes, 0, length); readCount += length; currentValue = readCount; //当组件销毁时,停止多线程里的while循环,防止程序停止运行时,多线程仍在执行 if (isStop) { break; } } } catch (System.Exception e) { Debug.Log(e.ToString()); } source.Close(); target.Close(); } }
图片加载并显示UI组件中
方法一:
1、把图片转换成字节数组
2、把字节数组转换成图片,loadImage
方法二:
1、本地加载,加file:\\
2、网络加载,使用协程
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.UI; public class LessonLoadTexture : MonoBehaviour { public RawImage image; // Use this for initialization void Start () { image.texture = LoadFileTexture(@"D:\桌面\1.jpg"); image.SetNativeSize(); //加载网上的 //StartCoroutine(LoadTexture(@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1527592090920&di=60ad08a7d15d3f91e7a370a9479b5d50&imgtype=0&src=http%3A%2F%2Fimage.yy.com%2Fyywebalbumbs2bucket%2Ffa63ba48c11f46278f9f2be98a141138_1499771837216.jpeg")); //加载本地的 如果要www加载本地的图片,那么在路径前要加 file:// //StartCoroutine(LoadTexture(@"file://D:\桌面\1.jpg")); } // Update is called once per frame void Update () { } Texture LoadFileTexture(string filePath) { //把图片转换成字节数组 FileStream fs = File.Open(filePath, FileMode.Open); byte[] bytes = new byte[fs.Length]; try { fs.Read(bytes, 0, bytes.Length); } catch (System.Exception e) { Debug.Log(e.ToString()); } fs.Close(); //把字节数组转换成图片 Texture2D tex = new Texture2D(0, 0); if (tex.LoadImage(bytes))//把从字节数组中加载图片 { return tex; } else { return null; } } IEnumerator LoadTexture(string path) { WWW www = new WWW(path); yield return www;//图片加载完成后,在执行后面的步骤 //string.IsNullOrEmpty(error) 判断error不能为null 也不能为“” if (www != null && string.IsNullOrEmpty(www.error)) { image.texture = www.texture; image.SetNativeSize(); } else { Debug.LogError("加载错误"); } } }