c# - 加载图像表单 PersistenceDataPath
问题描述
我正在制作一个 Android 应用程序,它应该在开始时从 MySQL 数据库加载数据和从服务器加载一些图像。之后,用户将在外面,因此应用程序将离线工作。
我编写了代码以将所有数据库数据(它可以工作)和图像从服务器保存到 ApplicationPersistenceDataPath(不工作)。我已经在寻找我应该如何做到这一点。我拥有的代码不会引发任何错误。但是,当我尝试在应用程序上显示它时,图像是空白的。那是当我查看存储图像的文件夹时,我无法打开它们。
这是我必须保存图像的方法:
IEnumerator loadBgImage(string url, string file_name)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
yield return www.Send();
if (www.isNetworkError || www.isHttpError)
{
print("erro");
}
else
{
string savePath = string.Format("{0}/{1}", Application.persistentDataPath, file_name);
if (!File.Exists(savePath))
{
System.IO.File.WriteAllText(savePath, www.downloadHandler.text);
}
}
}
}
这是在图像中显示图像文件的代码:
string path = Application.persistentDataPath + "/" + nomeImagem;
imagem.GetComponent<SpriteRenderer>().sprite = LoadSprite(path);
这是调用的方法:
private Sprite LoadSprite(string path)
{
if (string.IsNullOrEmpty(path)) return null;
if (System.IO.File.Exists(path))
{
byte[] bytes = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
texture.filterMode = FilterMode.Trilinear;
texture.LoadImage(bytes);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);
}
return null;
}
我真的需要先保存图像,然后离线显示。有人可以告诉我我做错了什么吗?
更新 遵循@derHugo 回答的建议后,这是我必须保存图像的代码:
IEnumerator loadBgImage(string url, string file_name)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
yield return www.Send();
if (www.isNetworkError || www.isHttpError)
{
print("erro");
}
else
{
var savePath = Path.Combine(Application.persistentDataPath, file_name);
var data = www.downloadHandler.data;
using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
{
fs.Write(data, 0, data.Length);
}
}
}
}
它可以工作,但是在运行应用程序时我仍然看不到图像。在显示精灵的方法中,我添加了创建的精灵的返回。
第二次更新
我再次遵循@derHugo 的建议,我使用 rawImage 而不是 Image。它现在可以在 Unity 编辑器和 Android 设备上运行。这是我使用的方法:
private void LoadSprite(string path)
{
if (string.IsNullOrEmpty(path)) print("erro");
if (System.IO.File.Exists(path))
{
byte[] bytes = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
texture.filterMode = FilterMode.Trilinear;
texture.LoadImage(bytes);
imagem.texture = texture;
}
}
解决方案
一般来说,你应该宁愿使用Path.Combine
like
var path = Path.Combine(Application.persistentDataPath, FileName);
代替系统路径!可能是您的目标设备根本不理解/
为路径分隔符。
如果文件已经存在(可能是较新的版本?并且您已经下载了它),或者如果文件已经存在,您甚至不应该开始下载以节省带宽。
我也认为这WriteAllText
不是二进制图像数据的正确解决方案,因为www.downloadHandler.text
已经
解释为 UTF8 字符串
因此,由于图像很可能有一些字节无法在 UTF8 字符串中表示,因此您会在这里得到损坏的数据!
你宁愿直接使用
www.downloadHandler.data
它返回原始byte[]
而不是例如File.WriteAllBytes
(仅在UWP上)或将其FileStream
写入byte[]
文件的正确方法。就像是
var data = www.downloadHandler.data;
File.WriteAllBytes(path, data);
或者
var data = www.downloadHandler.data;
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
fs.Write(data, 0, data.Length);
}
比场景中的白色图像通常意味着精灵是null
.
如果没有错别字,那么您LoadSprite
总是会返回null
。您忘记返回创建的sprite
private Sprite LoadSprite(string path)
{
if (string.IsNullOrEmpty(path)) return null;
if (System.IO.File.Exists(path))
{
byte[] bytes = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
texture.filterMode = FilterMode.Trilinear;
texture.LoadImage(bytes);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);
// You should return the sprite here!
return sprite;
}
return null;
}
但是请注意,加载本地图像的更好方法实际上UnityWebRequestTexture
也是如此。它还采用本地文件路径作为 URL 和
与下载原始字节并在脚本中手动创建纹理相比,使用此类显着减少了内存重新分配。此外,纹理转换将在工作线程上执行。
但是也
仅支持 JPG 和 PNG 格式。
但这不应该是我想的问题,因为LoadImage
到目前为止您使用的也是相同限制的基础。
但是,这将是异步的,因此您必须等待纹理才能创建精灵。因此,与其重新调整,Sprite
我实际上宁愿传入相应Image
组件的引用并直接替换其sprite
. 就像是
private IEnumerator LoadLocalTexture(string path, Image receivingImage)
{
UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
var texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
var sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);
receivingImage.sprite = sprite;
}
}
如果您实际上并不一定要使用,Sprites
我总是建议您RawImage
改用可以直接使用的组件Texture2D
!而不是做类似的事情
private IEnumerator LoadLocalTexture(string path, RawImage receivingImage)
{
UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
var texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
receivingImage.texture = texture;
}
}
但是也
注意:请记住,使用 RawImage 会在每个 RawImage 存在时创建一个额外的绘制调用,因此最好仅将它用于背景或临时可见图形。
推荐阅读
- node.js - nodejs 12 升级后,node-grpc 的 npm install 失败。无法使用 msbuild 构建 grpc_node
- javascript - 我可以在不使用 AJAX 的情况下发送以发布重新排序的序列化排序列表吗?
- php - 如何修改此功能代码才能工作?
- google-apps-script - 这是 Google Apps Script SpreadsheetApp Range.copyTo 中的错误吗
- git - How do i clone work from the master branch to a new one?
- r - R:根据每行中两个值的最接近匹配和精确匹配合并查找表中的行
- java - 硬编码区域、城市、国家字符串
- css - 如何使用伪类更改多选列表中选定项目的背景颜色
- php - 如何将 json 对象传递给 PHP 7.1.x 中具有类型参数的方法
- amazon-web-services - 健康检查失败 - Terraform - ECS 集群 - 动态端口映射健康检查在 2 个端口中的 1 个上失败?