Accessing file in windows8 App using C# - c#

This is basically for windows 8 app and I'm writing a file using this method -
static async void WriteDataCords(int numDataCodewords)
{
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
var storageFile = await storageFolder.GetFileAsync("DataCodeWords.txt");
string data = numDataCodewords.ToString();
await FileIO.AppendTextAsync(storageFile, data);
}
and now I'm reading file using this method -
StorageFolder storageFolder7 = KnownFolders.DocumentsLibrary;
var storageFile7 = await storageFolder6.GetFileAsync("DataCodeWords.txt");
string text7 = await Windows.Storage.FileIO.ReadTextAsync(storageFile7);
but when I run this program it's throwing an error "Access denied or We can't access the file". Using this approach I'm writing many files and reading.Please let me know how to solve this problem.
Thanks in advance
My problem is when I'm accessing file to read and display at that time file is involve in writing process so thats why I'm unable to access that file and it's showing an error.
So. Is there any approach by which we only move forward when the file writing process is complete and than reading process will start?

You could use SemaphoreSlim which limits the number of threads that can access a resource.
Below is an example of a class that handles writing/reading for a file. You create an instance of it when you want to write a file and call the WriteDataCords method. Then you need some way to access the correct instance when you want to read and then call ReadDataCords:
public class FileReadWrite
{
public string FileName { get; set; }
public FileReadWrite(string fileName)
{
FileName = fileName;
}
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
public async Task WriteDataCords(int numDataCodewords)
{
await _semaphore.WaitAsync();
try
{
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
var storageFile = await storageFolder.GetFileAsync(FileName);
string data = numDataCodewords.ToString();
await FileIO.AppendTextAsync(storageFile, data);
}
finally
{
_semaphore.Release();
}
}
public async Task ReadDataCords()
{
await _semaphore.WaitAsync();
try
{
StorageFolder storageFolder6 = KnownFolders.DocumentsLibrary;
var storageFile7 = await storageFolder6.GetFileAsync(FileName);
string text7 = await Windows.Storage.FileIO.ReadTextAsync(storageFile7);
}
finally
{
_semaphore.Release();
}
}
}
And calling code:
public class ClientCode
{
public async void WriteFile()
{
var fileReadWrite = new FileReadWrite("DataCodeWords.txt");
await fileReadWrite.WriteDataCords(42);
}
public async void ReadFile()
{
var fileReadWrite = GetFileReadWriteForFile("DataCodeWords.txt"); //Method for retreiving correct instance of FileWriteRead class
await fileReadWrite.ReadDataCords();
}
private FileReadWrite GetFileReadWriteForFile(string fileName)
{
}
}
You could skip the FileWriteRead class (it adds complexity) and use SemaphoreSlim directly in the original code for writing/reading but then you could only write/read one file at a time (which might not be a problem).

Related

UWP c# creating a file in ApplicationData.Current.LocalFolder returns null

I created an app that needs to store user data in a file that is created on Application start and when I compile it, it shows me this System.IO.FileLoadException: Could not find or load a specific file. (Exception from HRESULT: 0x80131621) and this System.NullReferenceException: Invalid pointer.
When the Application starts it calls the Init() Method before everything.
public static class FilesManager
{
public static StorageFolder ROOT_DIRECTORY, USER_DIRECTORY;
public static StorageFile FILES_MANAGER_CACHE_FILE;
public static volatile string FILES_MANAGER_CACHE;
public static volatile StorageFolder FOLDER;
public static async Task Init()
{
try
{
FOLDER = await ApplicationData.Current.LocalFolder.CreateFolderAsync("DashData", CreationCollisionOption.OpenIfExists);
FOLDER = await ApplicationData.Current.LocalFolder.GetFolderAsync("DashData");
if (FOLDER == null) Debug.WriteLine("FOLDER IS NULL.");
FILES_MANAGER_CACHE_FILE = await FOLDER.CreateFileAsync("filesmanageruserdata.json", CreationCollisionOption.OpenIfExists);
FILES_MANAGER_CACHE_FILE = await FOLDER.GetFileAsync("filesmanageruserdata.json");
await LoadFilesManagerCacheAsync();
Debug.WriteLine("TEXT: " + FILES_MANAGER_CACHE);
}
catch(Exception e)
{
Debug.WriteLine("ERROR: " + e.ToString());
}
}
public static async Task LoadFilesManagerCacheAsync()
{
FILES_MANAGER_CACHE = await FileIO.ReadTextAsync(FILES_MANAGER_CACHE_FILE);
}
public static async Task storeUserData(string content)
{
try
{
await FileIO.WriteTextAsync(FILES_MANAGER_CACHE_FILE, content);
}catch(Exception e)
{
Debug.WriteLine("ERROR: " + e.ToString());
}
}
}

Asynchronous WebDav upload

Could somebody explain why my code isn't working as I expected. So there are .net framework 4.7.2, console app. I have one method in Main which trigger sync void method of file worker. This file worker look for file in my folder on my disk, and if it find something upload them.
WebDav class has public Upload Method which do some work and trigger private method to upload files one by one to webdav.
So my problem is that code execute in two ways synchronous or doesn't execute at all. For upload files to webDav I'm using nuget WebDav.Client.
So how to achieve this behaviour for example I have 10 files I run from server request's for each file to upload to webdav and cut time of execution. So main problem what I trying to solve is cut time.
So there is my code sample:
private static void Main(string[] args)
{
AudioCopy TestWebDav = new(_folderCount);
TestWebDav.AsyncCopyToDav(_pathToSave);
}
public class AudioCopy : IDisposable
{
public void AsyncCopyToDav(string path)
{
DirectoryInfo di = new(path);
var task = Task.Run(() =>
{
foreach (FileInfo file in di.GetFiles())
{
WebDav.UploadAsync(file.Name, file.FullName);
}
});
task.Wait();
}
}
public static class WebDav
{
public static void UploadAsync(string filename, string sourceFilePath, int? part = null)
{
string webDavTarget = ...some logic...;
var task = Task.Run(() => UploadFileToWebDavAsync(webDavTarget, sourceFilePath));
}
}
private static async Task UploadFileToWebDavAsync(string path, string sourceFilePath)
{
WebDavClientParams #params = new()
{
Credentials = _credential,
BaseAddress = new Uri(path),
Timeout = new TimeSpan(0, 5, 0)
};
IWebDavClient client = new WebDavClient(#params);
FileStream stream = new(sourceFilePath, FileMode.Open);
WebDavResponse result = await client.PutFile(path, stream);
if (!result.IsSuccessful)
{
throw new Exception();
}
}

Exception while creating SQLite database

I develop a Universal app that use a local SQLite database. As I need to know the database version, I store an additional information that contains this information.
At the application startup, I check if the database exists, and if the database version has changed.
public sealed partial class App : Application
{
// DB Name
public static string DBFileName = "myDb.sqlite";
public static string DBpath;
// DB Version
public static string DBVersionFilename = "myDb.version";
public static string DBVersionPath;
public static string DBVersion = "1.1.0";
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
ManageDB();
}
private async Task ManageDB()
{
if (!CheckDbExist().Result)
{
CreateDb();
}
else
{
if (CheckDbVersionUpdated().Result)
{
await DeleteDb();
CreateDb();
}
}
}
private async Task<bool> CheckDbExist()
{
try
{
StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(DBFileName);
DBpath = storageFile.Path;
return true;
}
catch { }
return false;
}
private void CreateDb()
{
try
{
StorageFile storageFile = ApplicationData.Current.LocalFolder.CreateFileAsync(DBFileName, CreationCollisionOption.OpenIfExists).GetResults();
DBpath = storageFile.Path;
var dbconnection = new SQLiteAsyncConnection(DBpath, false);
dbconnection.CreateTableAsync<Article>();
//...
StorageFile file = ApplicationData.Current.LocalFolder.CreateFileAsync(DBVersionFilename, CreationCollisionOption.ReplaceExisting).GetResults();
FileIO.WriteTextAsync(file, DBVersion);
}
catch (Exception e)
{ }
}
private async Task<bool> DeleteDb()
{
try
{
StorageFile storageFile = ApplicationData.Current.LocalFolder.CreateFileAsync(DBFileName, CreationCollisionOption.OpenIfExists).GetResults();
await storageFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
return true;
}
catch { }
return false;
}
private async Task<bool> CheckDbVersionUpdated()
{
try
{
string userDBVersion;
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBVersionFilename);
userDBVersion = await FileIO.ReadTextAsync(file);
if (userDBVersion != DBVersion)
return true;
else
return false;
}
catch { }
return false;
}
}
There is a problem on CreateDB():
if I browse this code step by step, with breakpoint, there is no problem
but if I don't place breakpoint I meet an exception after calling var dbconnection = new SQLiteAsyncConnection(DBpath, false);:
System.InvalidOperationException: A method was called at an unexpected time.
A method was called at an unexpected time.
at Windows.Foundation.IAsyncOperation`1.GetResults()
at TestRating.App.CreateDb()}
Would you have an idea about the encountered problem? Is there another way to do this?
When I remove ".Results()" it seems that the "CreateDb()" function works correctly:
private async Task<bool> CreateDb()
{
try
{
StorageFile storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(DBFileName, CreationCollisionOption.OpenIfExists);
DBpath = storageFile.Path;
var dbconnection = new SQLiteAsyncConnection(DBpath, false);
dbconnection.CreateTableAsync<Article>();
//...
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(DBVersionFilename, CreationCollisionOption.ReplaceExisting);
FileIO.WriteTextAsync(file, DBVersion);
return true;
}
catch (Exception e)
{ }
return false;
}
Do you have an explanation?

Deserialize data from file NOT asynchronously

I just wantend to know if there is a possibility to deserialize data from file NOT asynchronously in WinRT application. It looks like I have to get StorageFile object to deserialize it and getting it must be async. Is that right? Or maybe you know if I can do it synchronously?
This the the async code that works, but it is ASYNC
public static async Task<StorageFile> GetFileFromAsync(string relativeFileName)
{
StorageFolder localAppDataFolder = ApplicationData.Current.LocalFolder;
try
{
StorageFile file = await localAppDataFolder.GetFileAsync(relativeFileName);
return file;
}
catch (FileNotFoundException)
{
return null;
}
}
public static async Task<T> ReadFromXmlInIsAsync<T>(string path) where T : class
{
T data;
StorageFile isolatedStorageFile = await IsolatedStorageHelper.GetFileFromAsync(path);
if(isolatedStorageFile == null) return null;
using (IInputStream sessionInputStream = await isolatedStorageFile.OpenReadAsync())
{
DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(T));
data = (T)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead());
}
return data;
}
No, there is not a way to do it synchronously.
All WinRT APIs are asynchronous to encourage developers to write responsive applications.

How can I return a string from an async operation?

I'm using PCLStorage and need a way to read a file. I'm going to use JSON for serialization, so I just need to read the saved content from the file:
public async string ReadFromFile(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder", CreationCollisionOption.OpenIfExists);
IFile file = await folder.GetFileAsync(filename);
string content = await file.ReadAllTextAsync();
return content;
}
But I cant return string, it has to be void, Task or Task.
Is there a easy way I can Return string from this method? maybe by invoking another method?
You need to return a Task<string>, like this:
public async Task<string> ReadFromFile(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder",
CreationCollisionOption.OpenIfExists);
IFile file = await folder.GetFileAsync(filename);
string content = await file.ReadAllTextAsync();
return content;
}

Categories

Resources