NullReferenceException while reading xml file in android device
I am trying to find and deserialize an xml file but this exception keeps showing "NullReferenceException: Object reference not set to an instance of an object". I read a lot of similar posts and I was expecting my solution to work. Here is my code:
XmlSerializer serializer = new XmlSerializer(typeof(Tips));
Stream reader = new MemoryStream((Resources.Load(file_path, typeof(TextAsset)) as TextAsset).bytes);
StreamReader textReader = new StreamReader(reader);
Tips tips = (Tips)serializer.Deserialize(textReader);
Debug.Log("is tips null?" + tips);
reader.Dispose();
This is the Tips class:
[XmlRoot("tips")]
public class Tips
{
[XmlElement("tip")]
public List<string> tip { get; set; }
}
The variable file_path is this:
file_path = "understanding_nutrition_tips";
Any ideas?
Answer by Bunny83 · Apr 20, 2020 at 02:48 PM
Well first of all you talk about reading an xml file but you actually use Resources.Load, so you're not reading a file but you read a serialized asset that has to be located in a Resources
folder in your project when you build your game. Resources.Load does not read any "files". So this is the first point where I'm not sure this is what you actually want to do here.
Second never, ever use an "as" cast if you're not going to add a null check afterwards. If you know 100% that the type returned should be a TextAsset, use a normal cast. An as-cast would hide type incompatibilities behind a null reference exception. It makes debugging much more difficult. Apart from that the Resources class has a generic version of the Load method which provides a way shorter syntax and does already return the right type. Of course this assumes you actually want to read an asset from Unity's resource database.
Next when you use classes / objects which implement the IDisposable interface, use the using statement. It's much clearer to understand the code and you can not forget disposing the object(s).
Finally I just took your code and done the few improvements on it and it looks like this:
void XmlTest()
{
string file_path = "TestData";
XmlSerializer serializer = new XmlSerializer(typeof(Tips));
var data = Resources.Load<TextAsset>(file_path).bytes;
using (var reader = new System.IO.MemoryStream(data))
using (var textReader = new System.IO.StreamReader(reader))
{
Tips tips = (Tips)serializer.Deserialize(textReader);
foreach(var tip in tips.tip)
Debug.Log(tip);
}
}
I created a file TestData.xml
inside my Resources folder (/Assets/Resources/TestData.xml) of my test project with the following content:
<tips>
<tip>Tip No1</tip>
<tip>Tip No2</tip>
<tip>Tip No3</tip>
</tips>
When I run that method in my test project I get 3 debug logs which print out those 3 strings
Tip No1
Tip No2
Tip No3
So everything does work as expected. My guess is that you probable don't want to use Unity's resources database but instead read an actual file on the target device. In that case you have to use ordinary System.IO.File
methods to read the data and use actual file path and names whereever you located the file on the target device. Keep in mind that an app on an android device consists only of a single file, the compiled apk file. So no other files will be shipped automatically.
It's difficult to give proper advice since we don't know where your xml file should be located and how it should get there. All we can say is that, even without any modifications to your code, it won't throw any errors as long as you have an xml file located inside the resources folder of your project that has this name you're looking for.
You guessed correctly, I want to read the file inside the target device. $$anonymous$$y xml file should be located inside the Resources folder without being in any sub folder, just on the root. I tried your code but it's giving me the same exception.
Answer by Priyanka-Rajwanshi · Apr 21, 2020 at 07:33 AM
@Kirki_333 If file is present in Resources Folder, use:
public void LoadDataFromResources()
{
string file_path = "understanding_nutrition_tips";
XmlSerializer serializer = new XmlSerializer(typeof(Tips));
string data = Resources.Load<TextAsset>(file_path).text;
using (StringReader reader = new StringReader(data))
{
Tips tips = (serializer.Deserialize(reader)) as Tips;
}
}
See this link for more info: http://codesaying.com/parse-xml-in-unity3d/