跨平台读取xml文件

时间:2013-04-11 07:20:30

标签: c# android ios visual-studio xamarin.android

我在Windows Mobile上有一些Config文件作为我的解决方案的一部分。我将代码移植到MonoForAndroid和MonoTouch,所以我希望尽可能保持代码不变。

当加载这些xml文件时,在Windows Mobile上运行正常,在我的上一个原型中它也适用于iOS,但代码在MonForAndroid上不起作用

我有这些文件

/solution folder
    /My Documents/
        /Business
            App.Config
            Settings.Config

我将这些文件构建操作设置为Content,我可以看到它们被复制到/bin/Debug/但是当我尝试读取这些文件时,我得到以下异常:

System.IO.DirectoryNotFoundException

我发现在here中有一个类似的问题,但他们建议使用AndroidResources,我不想这样做,有很多位置需要这些文件,所以我做不想在很多地方改变它。

AndrodiResources,是不可能的,如果可能,我想避免使用EmbededResources

啊,我正在读它的方式,非常简单xmDoc.Load(filePath)我也试过File.ReadAllText()我确保filePath是正确的,我得到了使用Path.Combine()生成的路径以避免filePath / slashes的任何问题 以下是我构建文件路径的方法

var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, ""), "My Documents", "Business");
filePath = Path.Combine(filePath, "App.Config");

我可以在调试器中看到filePath是正确的 感谢您的帮助

1 个答案:

答案 0 :(得分:0)

在四处搜索之后,当他们的构建操作设置为Content时,我无法让MonoDroid加载(或包含)我的文件。

我必须创建一个名为FileHelper的实体,在Android上实现不同,然后我使用FileHelper.ReadAllText(string filename);

我将把我的实施放在这里,希望它能使其他人受益。

Windows Mobile和iOS

    public class FileHelper 
    {
        public static string ReadAllText(string filePath)
        {
            var path = filePath.GetFullPath();
            if (!File.Exists(path))
            {
                Logging.LogHandler.LogError("File " + path + " does not exists");
                return string.Empty;
            }
            using (var reader = new StreamReader(filePath))
            {
                return reader.ReadToEnd();
            }
        }
   }

Android版

public class FileHelper : BaseFileHelper 
{
    public static string ReadAllText(string filePath)
    {
        var entryAssemblyPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:", ""), "MyExecutableAssemblyName.dll");
        // This is because Assembly.GetEntryAssembly() returns null on Android... Booohhh
        var assembly = Assembly.LoadFrom(entryAssemblyPath);
        using (var stream = assembly.GetManifestResourceStream(filePath.GetFullPath()))
        {
            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

我有一个Constants的共享代码和一个路径的扩展方法,如下所示

Constants.cs

public static Class Constants
     {
        private static string _RootPath;
                private static string _iOSRootPath;
        private static string _AndroidResourcePath;

        public static string RootPath
        {
            get
            {
                if (string.IsNullOrEmpty(_RootPath))
                {
                    _RootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, "") + "\\My Documents\\Business";
                }
                return _RootPath;
            }
        }

        public static string iOSRootPath
        {
            get
            {
                          if (!string.IsNullOrEmpty(_iOSRootPath)) 
                          {
                       _iOSRootPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, "").Replace("file:", ""), Path.Combine("My_Documents", "Business"));
                  }
                          return _iOSRootPath;
                     }
        }

        public static string AndroidResourcePath
        {
            get
            {
                if (string.IsNullOrEmpty(_AndroidResourcePath))
                {
                    _AndroidResourcePath = "Leopard.Delivery.My_Documents.Business.";
                }
                return _AndroidResourcePath;
            }
        }
  }

PathExtentions.cs

public static class PathExtensions
    {
        public static string GetFullPath(this string filePath)
        {
            if (Platform.IsAndroid) // platform is a class that I have to tell me which platfrom I am at :)
            {
                return Constants.AndroidResourcePath + filePath;
            }
            if (Platform.IsIOS)
            {
                return Path.Combine(Constants.iOSRootPath, filePath);
            }
            return Path.Combine(Constants.RootPath, filePath);
        }
    }

设置完成后,我正在使用我的FileHelper,就像下面的

一样简单
string configuratinContents = FileHelper.ReadAllText(configruationPath); 

对于使用此代码的用户,请记住在Android上将构建操作设置为EmbededResources,并在iOS和Windows Mobile上将Content设置为{{1}}。