从Xamarin.Android项目中的文件中读取

时间:2016-08-17 12:35:08

标签: c# xamarin.android

我正在尝试从Xamarin Android中的MainActivity类访问.pbf文件。我尝试将文件添加到新的Maps文件夹中,我也尝试将其添加到Assets and Resources文件夹中。

我尝试使用不同的构建操作设置它们。但是总是生成此错误...“System.IO.FileNotFoundException:找不到文件”

using (var inputStream = 
   new FileInfo(@"Resources\ireland.osm.pbf").OpenRead())
{
...
}

如何将文件添加到项目中并使用FileInfo进行访问?

1 个答案:

答案 0 :(得分:2)

首先,您可能要做的是使用资产并按照Tutorial

进行操作

包含文件,因为您的应用程序无法像在文件系统上直接访问它们那样工作。现在,您无法从资产中获取FileInfo,但您将能够阅读它们。

首先将ireland.osm.pbf文件放在Assets目录中。接下来,您必须(并且通常在您选择添加现有项目时为您执行此操作)将构建操作设置为AndroidAsset。这将构建(打包)文件作为Android包的一部分。

通过AssetManager加载(访问)下一个资产。幸运的是,这可以通过this.Assets在活动上下文中找到。

阅读资产非常简单。

using (StreamReader sr = new StreamReader (Assets.Open ("ireland.osm.pbf")))
{
    //do as you wish with the stream reader.
}

编辑:

来自评论。

  

但我需要FileInfo来实现PBFOsmStreamSource(),如此处所示链接

我快速浏览了PBFOsmStreamSource()的源代码,并有构造函数:

/// <summary>
/// Creates a new source of PBF formated OSM data.
/// </summary>
/// <param name="stream"></param>
public PBFOsmStreamSource(Stream stream)
{
    _stream = stream;
}

现在,流阅读器是 NOT Stream我们需要将其转换为Stream但是具有属性BaseStream。现在,鉴于我没有测试环境,你应该可以打电话。

using (StreamReader sr = new StreamReader(Assets.Open("ireland.osm.pbf")))
{
    //do as you wish with the stream reader.
    var pbfStreamSource = new PBFOsmStreamSource(sr.BaseStream);

}

编辑2

StreamReader.BaseStream()不支持Seek()方法。进一步阅读PBFOsmStreamSource节目的来源。

private void Initialize()
{
    _stream.Seek(0, SeekOrigin.Begin);

    this.InitializePBFReader();
}

这就是您获得System.NotSupporte‌​dException例外的原因。因此,您需要构建支持Seek()方法的流。 Fortunatly MemoryStream能够改变位置并支持Seek()方法。

同样,我没有测试环境。

using (StreamReader sr = new StreamReader(Assets.Open("ireland.osm.pbf")))
{
    using (var ms = new MemoryStream())
    {
        sr.BaseStream.CopyTo(ms);
        var pbfStreamSource = new PBFOsmStreamSource(ms);
    }
}

最终修改

经过更多的审核并查看他们的示例后,我编写了一个示例控制台应用程序,它使用StreamReader与移动设备相同的功能。现在我稍微调整了一下,以便我们可以快速处理StreamReader,因为这些文件占用大量内存,并且不需要同时打开两个流。

using OsmSharp.Geo;
using OsmSharp.Osm.PBF.Streams;
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace Sample.GeometryStream
{
    class Program
    {
        static void Main(string[] args)
        {
            Test();
            Console.ReadLine();

        }
        static async Task Test()
        {

            await ToFile("http://files.itinero.tech/data/OSM/planet/europe/luxembourg-latest.osm.pbf", "test.pbf");

            var sr = new StreamReader("test.pbf");
            using (var ms = new MemoryStream())
            {
                try
                {
                    sr.BaseStream.CopyTo(ms);
                }
                catch
                {
                    //TODO: Handle exceptions
                }
                finally
                {
                    sr.Close();
                    sr.Dispose();
                }
                var pbfStreamSource = new PBFOsmStreamSource(ms);
            }
        }

        public static async Task ToFile(string url, string filename)
        {
            if (!File.Exists(filename))
            {
                var client = new HttpClient();
                using (var stream = await client.GetStreamAsync(url))
                using (var outputStream = File.OpenWrite(filename))
                {
                    stream.CopyTo(outputStream);
                }
            }
        }

    }
}