草庐IT

Unity C# 读取安卓persistentDataPath目录中的json文件

破道三十六 2023-10-10 原文

一.声明需要用到的命名空间 

using LitJson;       //用于读取Json文件
using System.IO;  //用于声明StreamReader类                                      

using System;      //用于声明序列化


二.编辑Json文件

  1.电脑中创建一个Text文本,命名为 TextData 

  2.填写Json内容

例:

整个json内容用{}圈起

SubjectData 和TeacherStudentDialogueData 是:类  内容用 [ ]  圈起

类中每个{}中的所有内容是:组   可以有多个

组{}中的每一行是:项    变量名和数量要保持一致

类,组,项 每添加一个要在上个的结尾添加 逗号 " , " 最后的类,组,项不需要添加都好

类,组,项 ,索引是从0开始

{
"SubjectData":[
{
"Questions":"让角色移动10步的指令属于哪一类的代码功能?",
"AnswerA"  :"外观",
"AnswerB"  :"运动",
"AnswerC"  :"控制",
"RightAnswer":"运动",
"Keyword1":"角色",
"Keyword2":"移动",
"Keyword3":"代码"
},
{
"Questions":"如何让程序开始运行?",
"AnswerA" :"点击绿旗",
"AnswerB" :"按下空格键",
"AnswerC" :"点击红色按钮",
"RightAnswer":"点击绿旗",
"Keyword1":"如何",
"Keyword2":"程序",
"Keyword3":"运行"
}
],
"TeacherStudentDialogueData":[
{
"TeacherDialogue":"上课",
"StudentDialogue":"起立",
"Keyword1":"上课",
"Keyword2":"",
"Keyword3":""
},
{
"TeacherDialogue":"请坐",
"StudentDialogue":"老师好",
"Keyword1":"请坐",
"Keyword2":"",
"Keyword3":""
},
{
"TeacherDialogue":"好,下课了",
"StudentDialogue":"老师再见",
"Keyword1":"好",
"Keyword2":"下课",
"Keyword3":""
}
]
}

3.填写完成后复制整段内容到 https://www.json.cn/ 这个网站去验证编辑的是否正确,如果正确,网站中会显示正确翻译内容,不正确会有错误提示

4.编辑完成,保存, 将文本的text格式改为json格式文件


三.C#脚本声明Json类 

1. json文件中有多少个类,C#脚本中就声明多少个类,C#脚本名和类名无关

2.每个类都要添加序列化索引[Serializable]不然读取不到

3.类名 组中每一项的变量名都要与Json文件中的类名和项的变量名保持一致,不然读取不到,注意大小写

4.类和组中的变量修饰符都为Public,数据类型为String

5.声明一个存储类,用于存储json文件中 指定类中每一组的数据,即下面脚本中的Root,注意 泛函数的数据类型与声明的数据类保持一致

6.如果发现哪一项数据内容没读取到,那大概率就是那一项的变量名没写对

例:

/// <summary>
/// 题目和答案
/// </summary>
[Serializable]
public class SubjectData
{
    public string Questions;//题目
    public string AnswerA;//选项A
    public string AnswerB;//选项B
    public string AnswerC;//选项C
    public string RightAnswer;//正确答案
    public string Keyword1;//关键字1
    public string Keyword2;//关键字2
    public string Keyword3;//关键字3
}

/// <summary>
/// 课堂上本人的对话
/// </summary>
[Serializable]
public class TeacherStudentDialogueData
{
    public string TeacherDialogue;//老师的对话
    public string StudentDialogue;//学生的对话
    public string Keyword1;//关键字1
    public string Keyword2;//关键字2
    public string Keyword3;//关键字3

}

/// <summary>
/// 存储分类数据
/// </summary>
[Serializable]
public class Root
{
    public List<SubjectData> SubjectData;
    public List<TeacherStudentDialogueData> TeacherStudentDialogueData;
}

7.在读取Json文件的脚本中声明存储类                                                                                         

声明写在继承MonoBehaviour的脚本

//声明存储类
 public  Root root;

如果在同一个脚本只需要声明就行,不需要实例化 


 四.Json文件放置位置

文件的放置路径为:此电脑\设备存储路径\Android\data\安卓软件包名\files

此文件路径就是 安卓persistentDataPath目录 也叫安卓沙盒目录安卓本地化持久目录

脚本读取这个路径时,指定代码为:Application.persistentDataPath 

这个文件夹是可供我们的读取和修改。

将Json放入files文件夹中,如果json文件过多,建议单独建一个文件夹

文件路径在第一次安装时是没有的,要安装好软件,打开软件,运行一次再退出,才会有。


五. 读取persistentDataPath目录中的json文件两种方法

  • 方法一  C# StreamReader 类读取

就这一行代码就读取到了, 读取到后接下来就是转换数据的内容了 


// 声明一个读取文件类                          沙盒文件路径+Json文件名.json
StreamReader streamReader = new StreamReader(Application.persistentDataPath + "/" + "TextData.json");

测试时: 

在PC端Unity上运行时,为方便测试可以将路径换成 Application.streamingAssetsPath + "/" + "TextData.json,这时就可以在PC端上直接读取Json文件

streamingAssetsPath文件夹是只能读取,不可写入

将Json文件放入Unity文件面板中的StreamingAssets 文件夹即可,注意文件名一定要一致

一般在StreamingAsset文件夹中读取到,在安卓环境中也可以读取到

真机运行时:

文件路径改为:Application.persistentDataPath

脚本方法一:

 #region 读取安卓本地持久化目录中的json文件
    /// <summary>
    /// 读取安卓Application.persistentDataPath目录中的json文件
    /// </summary>
    public void GetJsonData()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据,,
        //StreamReader streamReader = new StreamReader( Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        StreamReader streamReader = new StreamReader(Application.persistentDataPath + "/" + "TextData.json");
        //转换json数据
        JsonReader js = new JsonReader(streamReader);
        //将数据赋值到Root类
        root = JsonMapper.ToObject<Root>(js);//读取
       
        //关闭数据流
        streamReader.Close();
    }
    #endregion

注意:此方法需要用到LitJson 插件,声明using LitJson命名空间;

而且要将Json数据Debug.log不报错打印出来会有些繁琐,还要加一行

 string srRTE = streamReader.ReadToEnd(); 

进行数据流到字符串的转换,然后再将

JsonReader js = new JsonReader(streamReader);//删除这一行代码

变更这行代码参数root = JsonMapper.ToObject<Root>(srRTE);//读取;

脚本方法二:

 public void GetJsonData2()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据,,
        StreamReader streamReader = new StreamReader(Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        //StreamReader streamReader = new StreamReader(Application.persistentDataPath + "/" + "TextData.json");
        //读取来自流的当前位置到结尾的所有字符。
        string srRTE = streamReader.ReadToEnd();
        //打印字符串数据
        Debug.Log("<color=#ff7f00>" + "Json配置文件内容:" + "</color>" + srRTE);
        //将Json数据字符串赋值到Root类
        root = JsonUtility.FromJson<Root>(srRTE);
        //关闭数据流
        streamReader.Close();
    }

注意:此方法采用Unity自带的Json读取方法,不需要litJson插件,不需要声明 using LitJson命名空间;,可以Debug.log()打印内容但功能没有Json插件多

  • 方法二 C# UnityWebRequest类 Web服务器通信方式读取

/// <summary>
    /// 读取安卓Application.persistentDataPath目录中的json文件
    /// Web服务器通信方式
    /// </summary>
    /// <returns></returns>
    IEnumerator GetJsonData3_IE()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据
        //UnityWebRequest request = UnityWebRequest.Get("file://" + Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        UnityWebRequest request = UnityWebRequest.Get("file://" + Application.persistentDataPath + "/" + "TextData.json");
        //开始与远程服务器通信。开始与安卓本地文件夹通信。成功后进入下一步
        yield return request.SendWebRequest();
        //打印返回系统从远程服务器下载的主体数据的字节数。(只读)
        Debug.Log("<color=#ff7f00>" + "Json配置文件数据字节数:" + "</color>" + request.downloadedBytes);
        //打印字符串数据
        //拥有对 DownloadHandler 对象的引用,该对象可管理此 UnityWebRequest 从远程服务器接收的主体数据。
        Debug.Log("<color=#ff7f00>" + "Json配置文件内容:" + "</color>" + request.downloadHandler.text);
        //将Json数据字符串赋值到Root类
        //通过 JSON 表示形式创建对象。
        root = JsonUtility.FromJson<Root>(request.downloadHandler.text); 
    }

注意: "jar:file://" +Application.persistentDataPath + "/" + "TextData.json"  这个路径是读取apk包里面的资源,不是安装好的软件不是读取本地持久化目录的里面的东西。

这三种脚本方法调用在Awake中就行,携程方法记得开启:StartCoroutine(GetJsonData3_IE());


六.调用存储到Root类中的数据

1.声明Root类

//存放Json数据
  public  Root root; 
//不需要实例化

如果想要在其他脚本中引用Root类,

先在其他脚本中声明这个类再在其他脚本中赋值这个脚本中的类,

不可以直接实例化这个类,这么做只会实例化一个空数据

例:

//其他脚本中引用Root类
public class GameObject_School : MonoBehaviour
{
   public Root root;//Json 数据存放
   void Start()
    {
      //其他脚本引用Root类数据
              //含有数据的Root类,在读取JSon脚本中
        root =ConfigurationLoad_school.Instance.root;
        
    }
}

 2.调用类中的数据

获取Json文件指定类中组的数量

//获取Json数据指定类中组的数量
//返回int类型
//数据存储类.泛型数组.总数
root.SubjectData.Count

//获取指定项的内容
//返回String 类型
//数据存储类.泛型数组指定索引.指定项
//数据存储类.Json数据中指定类中的索引组.项
root.SubjectData[i].AnswerA;
root.TeacherStudentDialogueData[i].TeacherDialogue

七.附整体代码: 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
using System.IO;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;

/// <summary>
/// 题目和答案
/// </summary>
[Serializable]
public class SubjectData
{
    public string Questions;//题目
    public string AnswerA;//选项A
    public string AnswerB;//选项B
    public string AnswerC;//选项C
    public string RightAnswer;//正确答案
    public string Keyword1;//关键字1
    public string Keyword2;//关键字2
    public string Keyword3;//关键字3
}

/// <summary>
/// 课堂上本人的对话
/// </summary>
[Serializable]
public class TeacherStudentDialogueData
{
    public string TeacherDialogue;//老师的对话
    public string StudentDialogue;//学生的对话
    public string Keyword1;//关键字1
    public string Keyword2;//关键字2
    public string Keyword3;//关键字3

}

/// <summary>
/// 存储分类数据
/// </summary>
[Serializable]
public class Root
{
    public List<SubjectData> SubjectData;
    public List<TeacherStudentDialogueData> TeacherStudentDialogueData;
}

public class ConfigurationLoad_school : MonoBehaviour
{
    public static ConfigurationLoad_school Instance;
    public  Root root;

    private void Awake()
    {
        Instance = this;
      //喜欢那种方法就调用哪种方法
        GetJsonData();
        //GetJsonData2();
        //StartCoroutine(GetJsonData3_IE());
    }
    public void Start()
    {
       
    }


    #region 读取安卓本地持久化目录中的json文件
    /// <summary>
    /// 读取安卓Application.persistentDataPath目录中的json文件
    /// </summary>
    public void GetJsonData()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据,,
        StreamReader streamReader = new StreamReader( Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        //StreamReader streamReader = new StreamReader(Application.persistentDataPath + "/" + "TextData.json");
        //转换json数据
        JsonReader js = new JsonReader(streamReader);
        //将数据赋值到Root类
        root = JsonMapper.ToObject<Root>(js);//读取
        //关闭数据流
        streamReader.Close();
    }

    /// <summary>
    /// 读取安卓Application.persistentDataPath目录中的json文件
    /// 自己改编
    /// </summary>
    public void GetJsonData2()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据
        StreamReader streamReader = new StreamReader(Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        //StreamReader streamReader = new StreamReader(Application.persistentDataPath + "/" + "TextData.json");
        //读取来自流的当前位置到结尾的所有字符。
        string srRTE = streamReader.ReadToEnd();
        //打印字符串数据
        Debug.Log("<color=#ff7f00>" + "Json配置文件内容:" + "</color>" + srRTE);
        //将Json数据字符串赋值到Root类
        root = JsonUtility.FromJson<Root>(srRTE);
        //关闭数据流
        streamReader.Close();
    }

    /// <summary>
    /// 读取安卓Application.persistentDataPath目录中的json文件
    /// Web服务器通信方式
    /// </summary>
    /// <returns></returns>
    IEnumerator GetJsonData3_IE()
    {
        //测试时使用,读取StreamingAssets文件夹中指定json文件数据
        UnityWebRequest request = UnityWebRequest.Get("file://" + Application.streamingAssetsPath + "/" + "TextData.json");
        //读取指定文件夹中指定json文件数据
        //UnityWebRequest request = UnityWebRequest.Get("file://" + Application.persistentDataPath + "/" + "TextData.json");
        //开始与远程服务器通信。开始与安卓本地文件夹通信。成功后进入下一步
        yield return request.SendWebRequest();
        //打印返回系统从远程服务器下载的主体数据的字节数。(只读)
        Debug.Log("<color=#ff7f00>" + "Json配置文件数据字节数:" + "</color>" + request.downloadedBytes);
        //打印字符串数据
        //拥有对 DownloadHandler 对象的引用,该对象可管理此 UnityWebRequest 从远程服务器接收的主体数据。
        Debug.Log("<color=#ff7f00>" + "Json配置文件内容:" + "</color>" + request.downloadHandler.text);
        //将Json数据字符串赋值到Root类
        //通过 JSON 表示形式创建对象。
        root = JsonUtility.FromJson<Root>(request.downloadHandler.text); 
    }

    #endregion


}

有关Unity C# 读取安卓persistentDataPath目录中的json文件的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  6. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  7. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  8. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  9. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  10. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

随机推荐