1

I am looking to get the path to a file in my .net Maui app. I have set the file 'Build Action' to MauiAsset and 'Copy to Output Directory' to Copy if newer.

When deploying to Windows I can successfully get the path by using:

string fileName = $"{AppDomain.CurrentDomain.BaseDirectory}MyFolder\\myfile.txt"; 

which resolves as: "C:\Users\xxx\source\repos\myproject\myproject\bin\Debug\net6.0-windows10.0.19041.0\win10-x64\AppX\MyFolder\myfile.txt"

On android im trying to use:

string fileName = $"{AppDomain.CurrentDomain.BaseDirectory}/MyFolder/myfile.txt";

which resolves as: "/data/user/0/com.companyname.myproject/files/MyFolder/myfile.txt"

This is aparently not a usable path on android as the app then throws

System.IO.DirectoryNotFoundException: 'Could not find a part of the path '/data/user/0/com.companyname.myproject/files/MyFolder/myfile.txt'.'

when I try to access it using

System.IO.File.ReadAllLines(fileName);

It also looks like the start of the path is missing but how do I get that?

Adriaan
  • 17,741
  • 7
  • 42
  • 75
nimitz
  • 125
  • 1
  • 11
  • 2
    Please do not add answers to the question body itself. Instead, you should add it as an answer. [Answering your own question is allowed and even encouraged](https://stackoverflow.com/help/self-answer). Alternatively, ping @FreakyAli to update their answer with the additional information – Adriaan Oct 04 '22 at 07:32
  • 2
    Please stop to add irrelevant information to your posts. Stack Overflow strives to be a general knowledge base, with short and pointed questions and associated answers. Irrelevant information only distracts from the actual content and serves no purpose. Finally, rants aren't appropriate for professional discourse, nor on Stack Overflow. Please frame criticism in a polite way. – Adriaan Oct 04 '22 at 08:56

2 Answers2

1

Solution

Solution: So I finally found a solution to this. I have tried adding the MauiAsset in the project file (myproject.csproj) with the exact path as:

<ItemGroup>
<MauiAsset Include="MyFolder\myfile.txt" />
</ItemGroup>

Which simply DOES NOT WORK no matter how you twist and turn it. The only thing I can get to work is copying Microsoft's recursive folder include as:

<MauiAsset Include="MyFolder\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />

and then in c# set the filepath of the file located inside MyFolder as

string filePath = "myfile.txt"

Continue to the update section on details about reading.

Update

After going through the file system API as shown: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/storage/file-system-helpers?tabs=android

I think you need to use the OpenAppPackageFileAsync:

Something like below:

   public async Task<string> ReadTextFile(string filePath)
   {
      using Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync(filePath);
      using StreamReader reader = new StreamReader(fileStream);
      return await reader.ReadToEndAsync();
   }

OG ANSWER

One lesson that I have learned while using Xamarin also applies to Maui(probably). That handling path Cross-platform is annoying as hell, One incorrect move and you are doomed to find what you did wrong. What I like to do to avoid these mistakes is let C# handle based on Target Platform on how to get the correct path for my file(Not 100% foolproof but definitely easier).

Use Path.Combine to get your path to avoid issues with the different OS using different "/" "" kinds of brackets:

In your case, all you do is:

var fullPath = System.IO.Path.Comnbine(FileSystem.AppDataDirectory,"MyFolder","myfile.txt");
FreakyAli
  • 13,349
  • 3
  • 23
  • 63
  • This is definitely a better way to handle it, but im still getting the DirectoryNotFoundException though. It also resolves to the same path as what I was doing before did. – nimitz Oct 03 '22 at 14:14
  • Are you sure BaseDirectory is working on Android as well? may be try `FileSystem.AppDataDirectory` since that should be the correct path logically – FreakyAli Oct 03 '22 at 14:18
  • FileSystem.AppDataDirectory resolves to the exact same path as AppDomain.CurrentDomain.BaseDirectory – nimitz Oct 03 '22 at 14:20
  • Can you check my update see if that helps somehow – FreakyAli Oct 03 '22 at 14:34
  • await FileSystem.Current.OpenAppPackageFileAsync(filePath) throws FileNotFoundException – nimitz Oct 03 '22 at 14:40
  • If it's not asking too much can you add a sample on github, this could possibly be a bug – FreakyAli Oct 03 '22 at 14:50
  • 1
    I will try messing around with it a bit more and then look into doing a github sample after. – nimitz Oct 03 '22 at 14:57
1

So I finally found a solution to this. I have tried adding the MauiAsset in the project file (myproject.csproj) with the exact path as:

<ItemGroup>
<MauiAsset Include="MyFolder\myfile.txt" />
</ItemGroup>

Which simply DOES NOT WORK no matter how you twist and turn it. The only thing I can get to work is copying Microsoft's recursive folder include as:

<MauiAsset Include="MyFolder\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />

and then in C# set the filepath of the file located inside MyFolder as

string filePath = "myfile.txt"

and then FreakyAli's answer works for reading from the file.

Also when you set the build action of a file it really should automatically be added in the csproj file, which it currently does not.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
nimitz
  • 125
  • 1
  • 11