I want to write my current state of a game into a JSON file so that once the user comes back they can either resume or start new. I'm creating a hello world to take user input, store it in JSON and load it back in.
I currently can load JsonObject very quickly using this method
public JObject GetJsonData(string jsonFileName, string dirNameJsonLivesIn)
{
if (string.IsNullOrEmpty(jsonFileName))
throw new ArgumentNullException(jsonFileName);
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
var defaultPath = $"{assembly.GetName().Name}.{jsonFileName}";
var extendedPath = $"{assembly.GetName().Name}.{dirNameJsonLivesIn}.{jsonFileName}";
if (string.IsNullOrEmpty(dirNameJsonLivesIn))
extendedPath = defaultPath;
Stream stream = assembly.GetManifestResourceStream(extendedPath);
using (var reader = new StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
return JObject.Parse(jsonString);
}
}
With this method, I can access objects with ["strings"] just like python does very easily and painlessly.
Problem accures when I try to write to the file. I get an error Access denied... I have given permission on the manifest for Write_External_Files or something along the line. Still get the same error. I've also done some research and there has been a few line of code which people recommended to add to the MainActivity.cs but that didn't work either.
Using this method to write file
private void StoreData_Clicked(object sender, EventArgs e)
{
var jsonFileName = "Statefile.json";
var text = entryBox.Text;
var state = new Dictionary<string, string>();
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
var defaultPath = $"{assembly.GetName().Name}.{jsonFileName}";
state.Add("CurrentState", text);
var json = JsonConvert.SerializeObject(state, Formatting.Indented);
File.WriteAllText(defaultPath, json);
}
Could someone explain why this is happening? Why do I have the ability to read the external_resources but not write to them? Oh yeah, I have set my properties to Embedded Resource and also Always Copy.
Update - Error
System.UnauthorizedAccessException
Message=Access to the path "/HelloWorldXamarin.Statefile.json" is denied.
Related
I need to save and load a listview / observablecollection when I open and close the app.
I have search around here and other places, and tried some things, but nothing seems to work.
I've pasted the code I found, that I thought did the trick. maybe it does with some changes.
//This one is for adding items, and it works fine.
try
{
Tanknings.Add(new Tankning { Date = Dato.Date.ToString("dd-MM-yyyy"),
KmTaeller = KmTaeller.Text,
LiterTanket = Math.Round(Convert.ToDouble(LiterTanket.Text), 2).ToString(),
Pris = Math.Round(Convert.ToDouble(Pris.Text), 2).ToString(),
KmKoert = (Convert.ToInt32(KmTaeller.Text) - Convert.ToInt32(AktuelKmTaeller.Text)).ToString(),
PrisPrLiter = Math.Round((Convert.ToDouble(Pris.Text) / Convert.ToDouble(LiterTanket.Text)), 2).ToString(),
KmPrLiter = Math.Round(((Convert.ToDouble(KmTaeller.Text) - (Convert.ToDouble(AktuelKmTaeller.Text))) / Convert.ToDouble(LiterTanket.Text)), 2).ToString() });
}
catch
{
}
//This i what i tried to save and load the items.
private async void saveTankninger()
{
XmlSerializer xs = new XmlSerializer(typeof(ObservableCollection<Tankning>));
using (StreamWriter wr = new StreamWriter("Files/Tankninger.xml"))
{
xs.Serialize(wr, Tanknings);
}
/* Firstly we will use StorageFolder class from the Windows.Storage namespace
to get path to the LocalFolder for our application: */
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
/* Then we need to have reference to the file where we can store notes:
Note that if file exists we do not want to create another one: */
StorageFile notesFile = await storageFolder.CreateFileAsync("Tankninger.txt", CreationCollisionOption.OpenIfExists);
// Now we want to serialize list with the notes to save it in the JSON format ine the file:
var serializedNotesList = JsonConvert.SerializeObject(Tanknings);
// Last step is to write serialized list with notes to the text file:
await FileIO.WriteTextAsync(notesFile, serializedNotesList);
}
private async void loadTankninger()
{
/* Firstly we will use StorageFolder class from the Windows.Storage namespace
to get path to the LocalFolder for our application: */
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
/* Then we need to have reference to the file where we can store notes:
Note that if file exists we do not want to create another one: */
StorageFile notesFile = await storageFolder.CreateFileAsync("Tankninger.txt", CreationCollisionOption.OpenIfExists);
// Read serialized notes list from the file:
string serializedNotesList = await FileIO.ReadTextAsync(notesFile);
// Deserialize JSON list to the ObservableCollection:
if (serializedNotesList != null)
{
Tanknings = JsonConvert.DeserializeObject<ObservableCollection<Tankning>>(serializedNotesList);
tankningTable.ItemsSource = Tanknings;
}
}
Assuming that you are using newtonsoft JSON library and have populated List
Serialise :
using Newtonsoft.Json;
List<Class_name> aList = getListFromSomehwere();
string json = JsonConvert.SerializeObject(aList);
// Do whatever you want with string, e.g. save to file
Deserialise :
using Newtonsoft.Json;
string json = ReadFile(); // Your function to read all text from file
List<Class_name> aList = (JsonConvert.DeserializeObject<IEnumerable<Class_name>>(json)).ToList();
// Do whatever you want with this list
To save on close - just add event to your application closing event, serialise list and save it to file.
To open on load - add window_loaded event (or form shown or whatever you prefer), read all file, deserialise json. There's many ways to approach this and it is up to you to decide what you want to do.
Edit : JSON.NET DeserializeObject to List of Objects might help
I changed the name of my project and when I run it it runs fine but when it reaches the part where it does validation from json I get the following error:
Cannot find embedded resource: hot.json
but when I change the name back to the original name the error goes away. I have tried deleting the old one and then added another json file with different name and I still got the same error.
here is where the error is occurring in my code:
var assembly = Assembly.GetExecutingAssembly();
using (
var stream =
assembly.GetManifestResourceStream(
$"HotStuff.TestResources.Languages.{language}.json"))
{
if (stream == null)
throw new InvalidOperationException($"Cannot find embedded resource: {language}.json");
using (var reader = new StreamReader(stream))
{
var json = JObject.Parse(reader.ReadToEnd()).ToObject<JToken>();
var value = json.SelectToken(key.Replace(" ", "-"));
return value?.ToString() ?? string.Empty;
}
}
I want to store variables in a .txt file - like I always see in peoples config.txt files, where it's like:
var_name = ['"test url"']
I've got the code below that opens the file and reads it (at the moment just debugging and displays what's in the file, at the moment just 1 variable)
System.IO.StreamReader myFile = new System.IO.StreamReader("C:\\conf\\config.txt");
string myString = myFile.ReadToEnd();
myFile.Close();
MessageBox.Show(myString);
What's in the file is
file_name="C:\\test.txt"
Now I'd like to be able to use that variable in my functions in my VB form. How do I go about doing this? And also, how can I do multiple; so I can have basically a big list of vars that the form loads at launch?
So for example:
// Opens file and reads all variables
// Saves all variables to form
// Can now use varaible in form, e.g. messageBox.Show(file_name);
I'm new to C#, I imagine it's similar to an include but the include is local instead of part of the project.
Disclamer: standard practice (i.e. Settings) usually is the best policy, however the question has been asked and can be asnwered:
I suggest using dictionary, e.g.
Dictionary<String, String> MySettings = File
.ReadLines(#"C:\conf\config.txt")
.ToDictionary(line => line.Substring(0, line.IndexOf('=')).Trim(),
line => line.Substring(line.IndexOf('=') + 1).Trim().Trim('"'));
...
String testUrl = MySettings[var_name];
However, if you prefer "variables" you can try ExpandoObject:
dynamic ExpSettings = new ExpandoObject();
var expandoDic = (IDictionary<string, object>) ExpSettings;
foreach (var pair in MySettings)
expandoDic.Add(pair.Key, pair.Value);
...
String testUrl = ExpSettings.var_name;
I store and load data (or variables) with Json Deserialization/ serialization in c#.
Here is Serialiazation: I make an object (postlist which is an object list) that i want to save in a text file That way:
private void save_file()
{
string path = Directory.GetCurrentDirectory() + #"\list.txt";
string json = JsonConvert.SerializeObject(postlist);
File.WriteAllText(path, json);
Application.Exit();
}
You need to install Newtonsoft.Json: http://www.newtonsoft.com/json
.You can do it with the Nuget tool console.
Don"t forget to use:
using Newtonsoft.Json;
Here is a way to get all your data from the text file, this is the deserialization:
private void read_file_list()
{
string line;
try
{
using (StreamReader sr = new StreamReader("list.txt"))
{
line = sr.ReadToEnd();
}
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;
postlist = JsonConvert.DeserializeObject<List<Post>>(line, jsonSerializerSettings);
}
catch
{
// catch your exception if you want
}
}
And here is how i store all my text in my object list "postlist".
Newtonsoft is very usefull and easy to use, i mostly use it to get data from api's.
This my first answer I hope it will help you.
I'm pretty new to processing recorded sound.
I can successfully record audio into a .3gpp file, save it locally on my mobile device, and play it back.
The trouble I'm having is that I want to convert the sound file into binary so that I can stick it into a parseObject, and upload the file to a cloud. I then want to be able to access that file from a separate device, and stream it.
--UPDATE--- I'm not using binary anymore, I'm using a parseFile object. I now just need to pull the object down from the cloud.
Here's the code I'm using to record the audio (working):
string sName;
string path = "/storage/extSdCard/";
string newPath = "";
_start.Click += delegate {
_stop.Enabled = !_stop.Enabled;
_start.Enabled = !_start.Enabled;
sName = _edittext.Text;
if (sName.Equals(" "))
{
}
else
{
//user enters a name for ther audio file
newPath = path + sName + ".3gpp";
_recorder.SetAudioSource (AudioSource.Mic);
_recorder.SetOutputFormat (OutputFormat.ThreeGpp);
_recorder.SetAudioEncoder (AudioEncoder.AmrNb);
_recorder.SetOutputFile (newPath);
_recorder.Prepare ();
_recorder.Start ();
}
};
_stop.Click += delegate {
_stop.Enabled = !_stop.Enabled;
_recorder.Stop ();
// _recorder.Reset ();
_player.SetDataSource (newPath);
_player.Prepare ();
_player.Start ();
};
Here is the class I'm using to send the data to a cloud - this is executed on the click of a button and works, it currently sends hard coded strings into an object which i can successfully retrieve.
HOWEVER, I want the binary string to go into the testObject["audio"], so I can retrieve it.
async Task sendToCloud()
{
ParseClient.Initialize ("--I've put my keys here but I'm censoring them--", "--I've put my keys here but I'm censoring them--");
try
{
byte[] data =null;
ParseFile file = null;
using (StreamReader reader = new StreamReader(LoadPath))
{
data = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
file = new ParseFile("theaudio.3gpp", data);
}
Console.WriteLine("Awaiting reader");
await file.SaveAsync ();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
auidoParseObject["userName"] = "userName";
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
Any help would be GREATLY APPRECIATED.
EDIT2:
I've made some progress, I'm struggling, however, to get the audio file down from the cloud still.
here's my new code:
async Task sendToCloud(string filename)
{
ParseClient.Initialize ("censored", "censored");
var testObject = new ParseObject ("Audio");
string LoadPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string savetheFile = sName + ".3gpp";
string tempUserName;
LoadPath += savetheFile;
Console.WriteLine ("loadPath: " + LoadPath);
try
{
byte[] data = File.ReadAllBytes(LoadPath);
ParseFile file = new ParseFile(savetheFile, data);
await file.SaveAsync();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
if (ParseUser.CurrentUser != null)
{
tempUserName = ParseUser.CurrentUser.Username.ToString();
}
else{
tempUserName = "Anonymous";
}
//tempUserName = ParseUser.CurrentUser.Username.ToString();
Console.WriteLine("PARSE USERNAME: " + tempUserName);
auidoParseObject["userName"] = tempUserName;
auidoParseObject["userName"] = tempUserName;
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
catch (Exception e)
{
Console.WriteLine("Failed to await audio object! {0}" + e);
}
}
So currently, my objects have the following structure:
"auidoParseObject" contains two children: username (string) and file (ParseFile object)
"file" has two children: the name of the audio (entered by the user -string), and the data in bytes.
I need the audio to be placed into a mdeiaplayer player object, and played.
In the long run, I'll want to extract:
(forgive my pseudo-SQL, but I don't understand the querying documentation):
Select (all files) from (audioParseObject) where (the username = current user.username)
AND THEN
put those files into a listview
user selects a file from the listview and it plays.
ANY help or pointers would be great.
Thanks.
Parse has really good docs on their site with examples - have you read them?
First, you would use a ParseFile (not a ParseObject) to save your file
byte[] data = File.ReadAllBytes(path_to_your_file);
ParseFile file = new ParseFile("your_file_name_and_ext", data);
await file.SaveAsync();
After you save your file, you can add a reference to it in your ParseObject
testObject ["audio"] = file;
To retrieve the file later, you use the Url property from the ParseFile.
var file = testObject.Get<ParseFile>("audio");
byte[] data = await new HttpClient().GetByteArrayAsync(file.Url);
I try to upload a text file to my skydrive or at least create new text file in SD and edit it's content, through SkyDrive API in my Windows 8 application.
How can I do that?
I tried to do something like that:
LiveConnectClient client = new LiveConnectClient(session);
var fileData = new Dictionary<string, object>();
fileData.Add("name", "new_file.txt");
try
{
LiveOperationResult fileOperationResult = await client.PutAsync("me/skydrive", fileData);
this.infoTextBlock.Text = fileOperationResult.ToString();
}
catch (LiveConnectException exception)
{
this.infoTextBlock.Text = exception.Message;
}
but I get error
"The provided request is not valid. The root SkyDrive folder cannot be updated."
If I write something like "me/skydrive/" I get
"The provided URL is not valid. The requested path '' is not supported".
Method LiveConnectClient.PutAsync allows me only to update existing properties (but not it's content).
How it should be done properly?
Btw - Is content on LCDC(http://msdn.microsoft.com/en-us/library/live/hh826531.aspx) updated? I'm asking because some methods, which are in documentation, doesn't exist in dlls (f.e. LiveConnectClient.Upload. There's only BackgroundUploadAsync).
Thanks for help in advance,
Micheal
Close but as I wrote: I can't use client.upload method because LiveConnectClient class doesn't contain it. That's why I asked about site content update.
Anyway - I've got an answer:
//create a StorageFile (here is one way to do that if it is stored in your ApplicationData)
StorageFile file = awaitApplicationData.Current.LocalFolder.GetFileAsync("yourfilename.txt");
try {
client = new LiveConnectClient(session);
LiveOperationResult operationResult = await client.BackgroundUploadAsync("me/skydrive", file.Name, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException exception) {
//handle exception
}
You should use the Upload method on LiveConnectionClient. For example, see the Uploading Files example in the Live SDK. Something like ...
LiveOperationResult fileOperationResult =
await client.Upload("me/skydrive", /*file name here*/, /*file stream here*/);
Here's another way to upload a file from a console application using a SkyDriveApiClient downloaded from http://skydriveapiclient.codeplex.com/releases/view/103081
static void Main(string[] args)
{
var client = new SkyDriveServiceClient();
client.LogOn("YourEmail#hotmail.com", "password");
WebFolderInfo wfInfo = new WebFolderInfo();
WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
wfInfo = wfInfoArray[0];
client.Timeout = 1000000000;
string fn = #"test.txt";
if (File.Exists(fn))
{
client.UploadWebFile(fn, wfInfo);
}
}