Search code examples
c#jsonfilewindows-phone-8.1file-location

Window Phone 8.1: Confusing about file location and writing data


I'm trying to read and write data with json file. I created some class.

public class SimpleTask{...}
public class DayTask{...}
public class DataModel
{
    ...
    private async Task GetSimpleTaskAsync()
    {
        if (_daytask.Count != 0)
            return;
        string fileName = "a.json";
        Uri appUri = new Uri("ms-appx:///"+ fileName);
        StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(appUri);
        string jsonText = await FileIO.ReadTextAsync(file);
        JsonObject jsonObject = JsonObject.Parse(jsonText);
        JsonArray jsonArray = jsonObject["DayTasks"].GetArray();
        foreach (JsonValue daytaskValue in jsonArray)
        {
            JsonObject daytaskObject = daytaskValue.GetObject();
            ObservableCollection<SimpleTask> simpletask = new ObservableCollection<SimpleTask>();
            foreach (JsonValue simpletaskValue in daytaskObject["Tasks"].GetArray())
            {
                JsonObject simpletaskObject = simpletaskValue.GetObject();
                simpletask.Add(new SimpleTask(   simpletaskObject["StartTime"].GetString(),
                                                 simpletaskObject["EndTime"].GetString(), 
                                                 simpletaskObject["Description"].GetString()));
            }
            DayTask daytask = new DayTask(daytaskObject["Day"].GetString(),simpletask);

            this.DayTasks.Add(daytask);
        }
    }


}

As you can see, i have a method that gets data form a.json file. I created a.json file: enter image description here

In the MainPage.xaml.cs, there is a method which calls GetDayTaskAysnc() method and retrieves data :

private async void ReadData1(object sender, TappedRoutedEventArgs e)
    {
        string test = String.Empty;
        var daytask = await DataModel.GetDayTaskAsync();
        foreach (var tasks in daytask)
        {
            test += String.Format("Day:{0}:\n", tasks.Day);
            foreach (var simpletask in tasks.Tasks)
            {
                test += String.Format("\tStart Time: {0}\n", simpletask.StartTime);
                test += String.Format("\tEnd Time: {0}\n", simpletask.EndTime);
                test += String.Format("\tDescription Time: {0}\n", simpletask.Description);
            }
        }
        TextBlock.Text = test;
}

It worked fine ! But i want to write data to the same file, so i added data in hardcore way:

private List<DayTask> creatList()
    {
        List<DayTask> DayTasks = new List<DayTask>();
        ObservableCollection<SimpleTask> simpletask1 = new ObservableCollection<SimpleTask>();
        simpletask1.Add(new SimpleTask("6AM","7AM","Breakfast"));
        simpletask1.Add(new SimpleTask("8AM", "9AM", "Game"));
        ObservableCollection<SimpleTask> simpletask2 = new ObservableCollection<SimpleTask>();
        simpletask2.Add(new SimpleTask("6AM", "7AM", "Sleep"));
        simpletask2.Add(new SimpleTask("8AM", "9AM", "School"));
        DayTasks.Add(new DayTask ("3/8/2014",simpletask1));
        DayTasks.Add(new DayTask("4/8/2014", simpletask2));
        return DayTasks;
    }
    private async void WriteData(object sender, TappedRoutedEventArgs e)
    {
        string json = "a.json";
        List<DayTask> daytasks = creatList();
        var serializer = new DataContractJsonSerializer(typeof(List<DayTask>));
        var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(json, CreationCollisionOption.ReplaceExisting);
        using (stream)
        {
            serializer.WriteObject(stream, daytasks);
        }

        TextBlock.Text = "Write to Json file succeeded";
    }

When i ran my app with window phone emulator, Firstly, it wrote to the file. Then i clicked read data button to ensure data written correctly, the emulator showed data from a.json file without being modified by WriteData() method. I continued to creat the second read data method:

private async void ReadData2(object sender, TappedRoutedEventArgs e)
    {
        string test = String.Empty;
        string json = "a.json";
        string content = String.Empty;
        List<DayTask> mytasks = new List<DayTask>();
        var deserializer = new DataContractJsonSerializer(typeof(List<DayTask>));
        var stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(json);
        using (stream)
        {
            mytasks = (List<DayTask>)deserializer.ReadObject(stream);
        }
        foreach (var tasks in mytasks)
        {
            test += String.Format("Day:{0}:\n", tasks.Day);
            foreach (var simpletask in tasks.Tasks)
            {
                test += String.Format("\tStart Time: {0}\n", simpletask.StartTime);
                test += String.Format("\tEnd Time: {0}\n", simpletask.EndTime);
                test += String.Format("\tDescription Time: {0}\n", simpletask.Description);
            }
        }
        TextBlock.Text = test;
    }

I deployed my app several times, and this is my result:

  1. ReadData2() : 'System.IO.FileNotFoundException'
  2. WriteData() -> ReadData1(): Data from a.json was shown
  3. WriteData() -> ReadData2(): Data from creatList() was shown
  4. WriteData() -> ReadData1(): Data from a.json was shown -> ReadData2(): Data from creatList() was shown

So that, i have some question:

  1. Do i have 2 json files, one i created by adding into my project and the other one i created when ran WriteData() method ? What is their paths ?
  2. If my file is data.json in DataSource folder, how can i write data to it ? I can read data from it using uri like GetSimpleTaskAsync() but i don't know how to write to it correctly. (I tried to convert object into string to write but can't read it again, i guess i wrote it in wrong way)

Sorry for my long post and my bad english :) Thank you very much


Solution

  • But i want to write data to the same file, so i added data in hardcore way:

    Your are making confusion between ms-appx:/// and ms-appdata:/// folders (or ApplicationData.Current.LocalFolder )

    The ms-appx folder is read-only. You can't write to it. (or you could edit your app code without passing through the certification process)

    The file you wrote must be into the ms-appdata folder.