System.ArgumentNullException for Xamarin.Forms using StreamReader - c#

In public ScenarioPage() of ScenarioPage.cs I have the following code to read from a json file:
var assembly = typeof(ScenarioPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("firstSession.json");
using (StreamReader reader = new StreamReader(stream)) // System.ArgumentNullException
{
var json = reader.ReadToEnd();
List<SessionModel> data = JsonConvert.DeserializeObject<List<SessionModel>>(json);
foreach(SessionModel scenario in data)
{
label.Text = scenario.title;
break;
};
}
I am getting an ArgumentNullException for the stream input. firstSession.json is in the same folder as ScenarioPage.cs, and it is set as an embedded resource. It seems like Visual Studio is not recognizing that my json file is there. Is this is a bug? Or is there something wrong with my code?

Where did you put the Json File, I put it in the Json File in the root Of PCL like following screenshot.
Then use following code to read the Json File.
void GetJsonData()
{
string jsonFileName = "firstSession.json";
ContactList ObjContactList = new ContactList();
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new System.IO.StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
//Converting JSON Array Objects into generic list
ObjContactList = JsonConvert.DeserializeObject<ContactList>(jsonString);
}
EmployeeView.ItemsSource = ObjContactList.contacts;
}
And here is running GIF.
I update my demo to you. you can test it
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/PlayMusicInBack.zip

Related

System.Text.Json.* & deserialization of streams

I have this original code:
public async Task<ActionResult> Chunk_Upload_Save(IEnumerable<IFormFile> files, string metaData)
{
if (metaData == null)
{
return await Save(files);
}
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(metaData));
JsonSerializer serializer = new JsonSerializer();
ChunkMetaData chunkData;
using (StreamReader streamReader = new StreamReader(ms))
{
chunkData = (ChunkMetaData)serializer.Deserialize(streamReader, typeof(ChunkMetaData));
}
string path = String.Empty;
// The Name of the Upload component is "files"
if (files != null)
{
foreach (var file in files)
{
path = Path.Combine(WebHostEnvironment.WebRootPath, "App_Data", chunkData.FileName);
//AppendToFile(path, file);
}
}
FileResult fileBlob = new FileResult();
fileBlob.uploaded = chunkData.TotalChunks - 1<= chunkData.ChunkIndex;
fileBlob.fileUid = chunkData.UploadUid;
return Json(fileBlob);
}
I converted it using only System.Text.Json.* to this:
public async Task<ActionResult> Chunk_Upload_Save(IEnumerable<IFormFile> files, string metaData)
{
if (metaData == null)
{
return await Save(files);
}
var ms = new MemoryStream(Encoding.UTF8.GetBytes(metaData));
ChunkMetaDataModel chunkData;
using (var streamReader = new StreamReader(ms))
{
// Here is the issues
chunkData = (ChunkMetaDataModel) await JsonSerializer.DeserializeAsync(streamReader, typeof(ChunkMetaDataModel));
}
// The Name of the Upload component is "files"
if (files != null)
{
foreach (var file in files)
{
Path.Combine(hostEnvironment.WebRootPath, "App_Data", chunkData!.FileName);
//AppendToFile(path, file);
}
}
var fileBlob = new FileResultModel
{
uploaded = chunkData!.TotalChunks - 1 <= chunkData.ChunkIndex,
fileUid = chunkData.UploadUid
};
return Json(fileBlob);
}
I get the error:
Argument 1: cannot convert from 'System.IO.StreamReader' to 'System.IO.Stream'.
By Argument 1, VS is pointing to the streamReader parameter and it's this line:
chunkData = (ChunkMetaData)serializer.Deserialize(streamReader, typeof(ChunkMetaData));
How do I convert this to the System.Text.Json API?
System.Text.Json is designed to deserialize most efficiently from UTF8 byte sequences rather than UTF16 strings, so there is no overload to deserialize from a StreamReader. Instead deserialize directly from the MemoryStream ms using the following:
chunkData = await JsonSerializer.DeserializeAsync<ChunkMetaDataModel>(ms);
Notes:
There is no reason to use async deserialization when deserializing from a MemoryStream. Instead use synchronous deserialization like so:
chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(ms);
And since you already have a string metaData containing the JSON to be deserialized, you can deserialize directly from it using the Deserialize<TValue>(ReadOnlySpan<Char>, JsonSerializerOptions) overload:
chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(metaData);
System.Text.Json will do the UTF16 to UTF8 conversion for you internally using memory pooling.
If you really must deserialize from a StreamReader for some reason (e.g. incremental integration of System.Text.Json with legacy code), see Reading string as a stream without copying for suggestions on how to do this.

Writing to a JSON File and reading from it

I need to save the information from an input page into a JSON File and output the information onto another page reading from the JSON File. I've tried many things and what seemed to work for me is using the specialfolder localapplication data.
Now, I don't quite understand how I can output the information and also check if the data is even put in correctly.
I previously used StreamReader to output the information on the JSON file and then put it on a ListView but this doesn't work if I have the file in the specialfolder. It says "stream cant be null". The commented out code is the code I tried in previous attempts.
Code:
ListPageVM (Read Page)
private ObservableCollection<MainModel> data;
public ObservableCollection<MainModel> Data
{
get { return data; }
set { data = value; OnPropertyChanged(); }
}
public ListPageVM()
{
var assembly = typeof(ListPageVM).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json"/"SaveUp.Resources.eintraege.json"/));
//var file = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
using (var reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
List<MainModel> dataList = JsonConvert.DeserializeObject<List<MainModel>>(json);
data = new ObservableCollection<MainModel>(dataList);
}
}
MainPageVM (Write Page)
public Command Einfügen
{
get
{
return new Command(() =>
{
// Data ins Json
_mainModels.Add(DModel);
Datum = DateTime.Now.ToString("dd.mm.yyyy");
//var assembly = typeof(ListPageVM).GetTypeInfo().Assembly;
//FileStream stream = new FileStream("SaveUp.Resources.eintraege.json", FileMode.OpenOrCreate, FileAccess.Write);
var file = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
//Stream stream = assembly.GetManifestResourceStream("SaveUp.Resources.eintraege.json");
if (!File.Exists(file))
{
File.Create(file);
}
using (var writer = File.AppendText(file))
{
string data = JsonConvert.SerializeObject(_mainModels);
writer.WriteLine(data);
}
});
}
}
you are trying to read and write resources, not files. That won't work. Instead do this
var path = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "eintraege.json");
File.WriteAllText(path, myjson);
to read the data back
var json = File.ReadAllText(path);

How to Read Json/Text Files from Asset Folder in Xamarin

I have a xamarin app where I need to read from a json file I have added in the Asset folder.
This is how the folder tree is in the solution explorer.
The code being used to read this json file is called from the User class in the Model folder.
This is how I have tried to access this file.
string path = Path.Combine(Directory.GetCurrentDirectory(), "..", "Assets", "data", "User.json");
var assembly = typeof(User).GetType().Assembly;
var stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{"User.json"}");
using (var reader = new StreamReader(stream))
{
string jsonString = await reader.ReadToEndAsync();
users = JsonConvert.DeserializeObject<List<User>>(jsonString);
}
The stream variable is null.
Please help out.
First check that you have set User.json file to Buid Action:EmbeddedResource.
then do like below:
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(User)).Assembly;
Stream stream = assembly.GetManifestResourceStream("TravulRecd.Assets.data.User.json");
string jsonString = "";
using (var reader = new System.IO.StreamReader(stream))
{
jsonString = reader.ReadToEnd();
}

Accessing a POSTed JSON File in Web API

I have created a Web API service that accepts a POSTed JSON file. With the service, I want to parse the JSON file using JSON.NET. I have seen multiple posts on the subject, however, I don't want to save the file to disk. I want to keep the file in memory, parse the file and dispose of the file in memory.
I'm also using .NET Framework 4.0.
EDIT: I should be more clear. When the file is POSTed, it is a file stream. The part I don't know is how to convert the stream to JSON.
public HttpResponseMessage Post()
{
HttpResponseMessage result = null;
int FileLen;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
string MyString = string.Empty;
var postedFile = httpRequest.Files[0];
FileLen = postedFile.ContentLength;
byte[] input = new byte[FileLen];
System.IO.Stream testStream = postedFile.InputStream;
testStream.Read(input, 0, FileLen);
for (int Loop1 = 0; Loop1 < FileLen; Loop1++)
MyString = MyString + input[Loop1].ToString();
CurrentRate.JSONSerializer(MyString);
}
Since JSON.NET has the ability to deserialize a file (converted to a stream) with the following code:
using (StreamReader file = File.OpenText(#"<pathToFile>"))
{
JsonSerializer serializer = new JsonSerializer();
MyObject myObject = (MyObject)serializer.Deserialize(file, typeof(MyObject));
}
By swapping out the stream from File.OpenText with something similar to the following
using (var stream = new MemoryStream(<FileByteArrayFromMemory>);
using (StreamReader file = new StreamReader(stream))
{
JsonSerializer serializer = new JsonSerializer();
MyObject myObject = (MyObject)serializer.Deserialize(file, typeof(MyObject));
}
we never have to deal with an actual file. There may be a more efficient way to create the MemoryStream or you may already have aStream and could initialize the and could skip that step.
EDIT 2: more explicitly showed swapping the StreamReader

ResXResourceWriter not writing to stream?

I'm trying to create a resx file and write it to a stream so that I might return it as a string instead of immediately saving it to a file. However, when I try to read that stream, it is empty. What am I doing wrong here? i did verify that the entries are not null. I can actually use the ResXResourceWriter constructor that saves it to disk successfully, but I'm trying to avoid using temp files. Also, I can see the stream is 0k before the loop and about 8k in length after the loop.
using (var stream = new MemoryStream())
{
using (var resx = new ResXResourceWriter(stream))
{
// build the resx and write to memory
foreach (var entry in InputFile.Entries.Values)
{
resx.AddResource(new ResXDataNode(entry.Key, entry.Value) { Comment = entry.Comment });
}
var reader = new StreamReader(stream);
var text = reader.ReadToEnd(); // text is an empty string here!
return null;
}
}
You need to flush and reset the output/stream before trying to read it. This should work, using Generate and Position:
resx.Generate();
stream.Position = 0;
var reader = new StreamReader(stream);
var text = reader.ReadToEnd();
return text;

Categories

Resources