Loading .txt file in C# UWP - c#

I am trying to open a .txt file for my UPW app.
string text;
private async void OpenFile(string fileName)
{
StorageFolder localFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("Beginner");
try
{
StorageFile file = await localFolder.GetFileAsync(fileName + ".txt");
text = await FileIO.ReadTextAsync(file);
PrintMessage(text);
}
catch (Exception)
{
PrintMessage("Failed to load file");
}
}
public async void PrintMessage(string message)
{
//Writes message
MessageDialog msg = new MessageDialog(message);
await msg.ShowAsync();
}
public Main()
{
OpenFile("WordList");
PrintMessage(text);
}
The code runs fine when I have PrintMessage(text); after ReadTextAsync. When I delete it, the program will freeze most of the time. When I run it in debugger, it mostly gets done, but sometimes it freezes at line StorageFile file = await localFolder.GetFileAsync(fileName + ".txt");. I believe there is some problem with async magic.
Also, the text variable in Main() is almost always null even though it should contain text of the file.
All I need is a function that will reliably open a .txt file and return (either return return, or like this into global) content of that file. I tried using Task<> but I couldnt make it work either...
Edit:
I tried
string text { get; set; }
public async void OpenFileAssist(string fileName)
{
await OpenFile(fileName);
}
public async Task OpenFile(string fileName)
{
StorageFolder localFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFolderAsync("Beginner");
try
{
StorageFile file = await localFolder.GetFileAsync(fileName + ".txt");
text = await FileIO.ReadTextAsync(file);
}
catch (Exception)
{
PrintMessage("File does not exist");
}
}
But it still does not work... When I call OpenFileAssist() from Main() the text variable is still null. :( If I open it in debugger and go step by step it works, though.
I got solution by using
private async void Page_Loaded(object sender, RoutedEventArgs e)

See this page, especially the example using TaskScheduler.FromCurrentSynchronizationContext(). It helped me a lot.

Related

UWP c# reading Stream from StorageFile returns null. Why and how to fix?

I am trying to open a Stream from a StorageFile. However, I have tried several ways to program this and always seem to get stuck.
Currently, I am able to use a filepicker to get the storagefile, store its token and use that token to get to the storagefile again. But when I want to use the OpenStreamForReadAsync method, the result is a nullstream.
I tried an async method first, then a task (see code) but I can't figure out what is wrong. Can someone help me?
A strange thing is that the line `dummy = 1;' is never executed. The debugger steps to bool=breakpoint;
public class Workbook
{
private StorageFile exFile = null;
private Stream stream = null;
public SpreadsheetDocument exDoc = null;
long dummy = 0;
public Workbook(String faToken)
{
GetStreamFromToken(faToken);
//GetStream(exFile);
//exDoc = SpreadsheetDocument.Open(stream, false);
//var test = exDoc.WorkbookPart.Parts;
bool breakpoint = true;
}
async private void GetStreamFromToken(String faToken)
{
exFile = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(faToken);
stream = await GetStream(exFile);
dummy = 1;
}
public Task<Stream> GetStream(StorageFile exFile)
{
return exFile.OpenStreamForReadAsync();
}
}
Well, I found my mistake. I did not understand that await does not mean that the code waits for completion. So I have to use a wait method to wait for completion of a task.

Reading/Writing Async Files for Universal App

im trying to Reading/Writing Async Files for an Universal App in c#.
When i write and read a file for first time, it works... But when i retry it immeadiatly, there are two Errors: 1. UnauthorizedAccess 2. Handle with the OPLOCK has been closed
It seems that the methods arent finished yet and so the data is not free
(in my frame is a button which adds a new member to a List, then the list shall serialized in an XML data. When i reNavigate to that page, that XML sheet shall be deserialized back to that List, because the Content shall be displayed)
List<Immobilie> immoListe = new List<Immobilie>();
private const string FileName_ImmoObjects = "ImmoObjects.xml";
StorageFolder sFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
IStorageFile latestImmoListFile;
public Startmenue()
{
this.InitializeComponent();
immoListe.Add(new Immobilie()); // for testing creating an XML first
immoListe[0].adresse = "Foo1";
immoListe.Add(new Immobilie());
immoListe[1].adresse = "Foo2";
WriteImmoListAsync();
ReadImmoListAsync(); // These two steps working
WriteImmoListAsync(); // everything more causes error
ReadImmoListAsync();
}
public async void WriteImmoListAsync()
{
try
{
IStorageFolder folder = await sFolder.CreateFolderAsync("Saves", CreationCollisionOption.OpenIfExists);
latestImmoListFile = await folder.CreateFileAsync(FileName_ImmoObjects, CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream stream = await latestImmoListFile.OpenAsync(FileAccessMode.ReadWrite))
using (Stream outputStream = stream.AsStreamForWrite())
{
DataContractSerializer serializer = new DataContractSerializer(typeof(List<Immobilie>));
serializer.WriteObject(outputStream, immoListe);
}
}
catch (Exception e)
{
var d = new MessageDialog(e.ToString());
await d.ShowAsync();
}
}
public async void ReadImmoListAsync()
{
int i = 0;
try
{
IStorageFolder folder = await sFolder.GetFolderAsync("Saves");
i = 1;
latestImmoListFile = await folder.GetFileAsync(FileName_ImmoObjects);
i = 2;
using (IRandomAccessStream stream = await latestImmoListFile.OpenAsync(FileAccessMode.Read))
{
i = 3;
using (Stream inputStream = stream.AsStreamForRead())
{
i = 4;
DataContractSerializer deserializer = new DataContractSerializer(typeof(List<Immobilie>));
i = 5;
immoListe = (List<Immobilie>)deserializer.ReadObject(inputStream);
}
}
}
catch (Exception e)
{
var d = new MessageDialog("Fehler I = " + i + "\n" + e.ToString());
await d.ShowAsync();
}
}
So what can i do and why is it so difficult??(normal I/O is easy-peasy).-.
As I describe in my MSDN article on async best practices, you should avoid async void:
public async Task WriteImmoListAsync();
public async Task ReadImmoListAsync();
Once your methods are properly async Task, then you can await them:
await WriteImmoListAsync();
await ReadImmoListAsync();
await WriteImmoListAsync();
await ReadImmoListAsync();
You can't start the methods again until you wait for them to complete. What that above code is trying to do is to write to a file, but while that's processing, it tries to open the file and write to it while the first method call hasn't completed. You need to wait for those method calls to finish before running them again - using the await keyword would be helpful here
It might be that the process writing/reading the file are still attached to the file. You might want to take a look at this pattern for async file read/write from Microsoft:
https://msdn.microsoft.com/en-ca/library/mt674879.aspx
Also, note that if the read and write are done from differents process, you're going to have to use a mutex. Here's a great explanation on how it works:
What is a good pattern for using a Global Mutex in C#?

how to save image downloaded from url(server) to local folder in windows store app

i am trying to download images from server and save it in local file.
i tried
private async void save()
{
Uri source = new Uri("http://www.google.ca/intl/en_com/images/srpr/logo1w.png");
StorageFile destinationFile;
try
{
destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"downloadimage.jpg", CreationCollisionOption.GenerateUniqueName);
}
catch (FileNotFoundException ex)
{
System.Diagnostics.Debug.WriteLine("bingooooo"+ex.ToString());
return;
}
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(source, destinationFile);
await download.StartAsync();
ResponseInformation response = download.GetResponseInformation();
}
but it doesn't work any alternative
Your code is fine, it's just lacking Task as return type. You should use return type as Task rather than void if your method is asynchronous. If return type is string & method is asynchronous then return type should be Task<string>.
Change private async void save() to private async Task save().
When you call save() append await keyword.
Check out Diving deep with WinRT and await

Async File Deserialization

I'm at my first Windows Store App, and I'm having some issue with Deserialization/loading my application Data.
I'm using JSon to serialize my class object to a string, then I'm saving it to the Application Local App folder.
When it is time to load the data, once upon a time the load fail at run time, and no data are loaded. and my classes are instantiated as a new classes.
But when I'm running my code step my step in debug mode. the Desirialization work OK and my classes are correctly loaded.
I'm thinking that the problem come from my async implementation. but I can't tell where.
Can some one help me?
Save procedure:
public virtual void Save()
{
var data = JsonConvert.SerializeObject(this);
WriteTotextFileAsync("Cashier.Data.Config", data);
}
public static async void WriteTotextFileAsync(string fileName, string contents)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, contents);
}
Load procedure:
private async void LoadConfig()
{
string data;
if (Config == null)
{
data = await ReadTextFileAsync("Cashier.Data.Config");//.ConfigureAwait(false);
if (data != null && data.Length > 0)
try
{
System.Diagnostics.Debug.WriteLine(data);
Config = JsonConvert.DeserializeObject<Data.Config>(data);
System.Diagnostics.Debug.WriteLine(data);
}
catch (Exception ex)
{
var dlg = new MessageDialog("Desirialization erreur" + Environment.NewLine + ex.Message);
dlg.ShowAsync();
Config = new Config();
}
else
{
System.Diagnostics.Debug.WriteLine("Config = new Config();");
Config = new Config();
}
}
}
public static async Task<string> ReadTextFileAsync(string path)
{
var folder = ApplicationData.Current.LocalFolder;
try
{
var file = await folder.GetFileAsync(path);
var value = await FileIO.ReadTextAsync(file);
return value;
}
catch (System.IO.FileNotFoundException ex)
{
return string.Empty;
}
}
You should avoid async void. Change your LoadConfig and Save methods into async Task methods and have your calling code await the task they return.
One problem with async void is that the calling code cannot know when it has completed. E.g., the code that calls LoadConfig does not know when the config is actually loaded. By making LoadConfig return a Task, then the calling code can await that Task and know that the config is loaded when that task completes.
I finally fond what went wrong. When I was deserializing the string, I was casting it to the wrong object class type.

File access from a background task in a windows store app

I can't seem to read a file from a background task in a windows store app. Here's the code that reads the file content:
async private static Task<string> ReadAsync(string FileName)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync(FileName);
Windows.Storage.Streams.IRandomAccessStreamWithContentType inputStream = null;
try
{
inputStream = await file.OpenReadAsync();
}
catch (Exception ex)
{
throw (ex);
}
string content = string.Empty;
using (Stream stream = inputStream.AsStreamForRead())
{
using (StreamReader reader = new StreamReader(stream))
{
try
{
// *** program exits on this line
content = await Task.Run(() => reader.ReadToEnd());
}
catch(Exception ex)
{
// no error is caught
content = ex.Message;
}
}
}
return content;
}
The program exits on the line that calls ReadToEnd() on the StreamReader - no error is caught in the try catch block. In the output window I get:
The program '[8968] backgroundTaskHost.exe: Managed (v4.0.30319)' has exited with code 1 (0x1)
Is it possible to access files a background task? If so, where am I going wrong?
It would be helpful if you posted your IBackgroundTask code. Without seeing it I suspect you didn't call GetDeferral() inside it, e.g.:
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferral = taskInstance.GetDeferral();
var contents = await ReadAsync("MyFile.txt");
deferral.Complete();
}
You need to call GetDeferral() whenever you are making asynchronous calls inside your background task. This way you tell the runtime it needs to wait for the asynchronous call to complete and not stop the background task as soon as Run exits.
Once you're done, i.e. usually at the end of your Run method, you need to call Complete() on the deferral instance to notify the runtime that you're done.
There are already system classes (DataReader) to read file asynchronously, so I'm not sure why you decided to write your own.

Categories