2

使用OSMSharp我无法打开文件流(我可以按需提供)

错误发生在 PBFReader 中(第 104 行)

using (var tmp = new LimitedStream(_stream, length))
{
  header = _runtimeTypeModel.Deserialize(tmp, null, _blockHeaderType) as BlobHeader;
}

并指出:"ProtoBuf.ProtoException: 'Invalid field in source data: 0'"这可能意味着我在这个 SO question中读到的不同的东西。

该文件打开并使用QGis可视化,因此我认为没有损坏。

会不会是合同不匹配?OsmSharp/core 是否从此处更新为 OSM 的最新 .proto 文件(尽管不确定这是否是定义文件的真正原始来源)。

还有什么可能更有意义,我附加的文件是为 OSM PBF 规范 v2 生成的吗?

在异常行的代码中,我看到以下评论让我感到奇怪:

// TODO: remove some of the v1 specific code.
// TODO: this means also to use the built-in capped streams.

// code borrowed from: http://stackoverflow.com/questions/4663298/protobuf-net-deserialize-open-street-maps

// I'm just being lazy and re-using something "close enough" here
// note that v2 has a big-endian option, but Fixed32 assumes little-endian - we
// actually need the other way around (network byte order):
// length = IntLittleEndianToBigEndian((uint)length);

BlobHeader header;
// again, v2 has capped-streams built in, but I'm deliberately
// limiting myself to v1 features

所以这让我想知道 OSM Sharp 是否(仍然)是最新的。

我的沙箱代码如下所示:

using OsmSharp.Streams;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OsmSharp.Tags;

namespace OsmSharp
{
    class Program
    {
        private const string Path = @"C:\Users\Bernoulli IT\Documents\Applications\Argaleo\Test\";
        private const string FileNameAntarctica = "antarctica-latest.osm";
        private const string FileNameOSPbf = "OSPbf";
        private const Boolean useRegisterSource = false;
        private static KeyValuePair<string, string> KeyValuePair = new KeyValuePair<string, string>("joep", "monita");

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            //string fileName = $@"{Path}\{FileNameAntarctica}.pbf";
            string fileName = $@"{Path}\{FileNameOSPbf}.pbf";

            string newFileName = $"{fileName.Replace(".pbf", string.Empty)}-{Guid.NewGuid().ToString().Substring(0, 4)}.pbf";


            Console.WriteLine("*** Complete");
            string fileNameOutput = CompleteFlow(fileName, newFileName);

            Console.WriteLine("");
            Console.WriteLine("*** Display");
            DisplayFlow(fileNameOutput);

            Console.ReadLine();
        }

        private static string CompleteFlow(string fileName, string newFileName)
        {
            // 1. Open file and convert to bytes
            byte[] fileBytes = FileToBytes(fileName);

            // 2. Bytes to OSM stream source (pbf)
            PBFOsmStreamSource osmStreamSource;

            osmStreamSource = BytesToOsmStreamSource(fileBytes);

            osmStreamSource.MoveNext();

            if (osmStreamSource.Current() == null)
            {
                osmStreamSource = FileToOsmStreamSource(fileName);

                osmStreamSource.MoveNext();

                if (osmStreamSource.Current() == null)
                {
                    throw new Exception("No current in stream.");
                }
            }

            // 3. Add custom tag
            AddTag(osmStreamSource);

            // 4. OSM stream source to bytes
            //byte[] osmStreamSourceBytes = OsmStreamSourceToBytes(osmStreamSource);

            // 5. Bytes to file
            //string fileNameOutput = BytesToFile(osmStreamSourceBytes, newFileName);

            OsmStreamSourceToFile(osmStreamSource, newFileName);

            Console.WriteLine(newFileName);

            return newFileName;
        }

        private static void DisplayFlow(string fileName)
        {
            // 1. Open file and convert to bytes
            byte[] fileBytes = FileToBytes(fileName);

            // 2. Bytes to OSM stream source (pbf)
            BytesToOsmStreamSource(fileBytes);
        }

        private static byte[] FileToBytes(string fileName)
        {
            Console.WriteLine(fileName);

            return File.ReadAllBytes(fileName);
        }

        private static PBFOsmStreamSource BytesToOsmStreamSource(byte[] bytes)
        {
            MemoryStream memoryStream = new MemoryStream(bytes);

            memoryStream.Position = 0;

            PBFOsmStreamSource osmStreamSource = new PBFOsmStreamSource(memoryStream);

            foreach (OsmGeo element in osmStreamSource.Where(osmGeo => osmGeo.Tags.Any(tag => tag.Key.StartsWith(KeyValuePair.Key))))
            {
                foreach (Tag elementTag in element.Tags.Where(tag => tag.Key.StartsWith(KeyValuePair.Key)))
                {
                    Console.WriteLine("!!!!!!!!!!!!!!      Tag found while reading           !!!!!!!!!!!!!!!!!!".ToUpper());
                }
            }

            return osmStreamSource;

        }

        private static PBFOsmStreamSource FileToOsmStreamSource(string fileName)
        {
            using (FileStream fileStream = new FileInfo(fileName).OpenRead())
            {
                PBFOsmStreamSource osmStreamSource = new PBFOsmStreamSource(fileStream);

                return osmStreamSource;
            }
        }

        private static void AddTag(PBFOsmStreamSource osmStreamSource)
        {
            osmStreamSource.Reset();

            OsmGeo osmGeo = null;

            while (osmGeo == null)
            {
                osmStreamSource.MoveNext();

                osmGeo = osmStreamSource.Current();

                if(osmGeo?.Tags == null)
                {
                    osmGeo = null;
                }
            }

            osmGeo.Tags.Add("joep", "monita");

            Console.WriteLine($"{osmGeo.Tags.FirstOrDefault(tag => tag.Key.StartsWith(KeyValuePair.Key)).Key} - {osmGeo.Tags.FirstOrDefault(tag => tag.Key.StartsWith(KeyValuePair.Key)).Value}");
        }

        private static byte[] OsmStreamSourceToBytes(PBFOsmStreamSource osmStreamSource)
        {
            MemoryStream memoryStream = new MemoryStream();

            PBFOsmStreamTarget target = new PBFOsmStreamTarget(memoryStream, true);

            osmStreamSource.Reset();

            target.Initialize();

            UpdateTarget(osmStreamSource, target);

            target.Flush();

            target.Close();

            return memoryStream.ToArray();
        }

        private static string BytesToFile(byte[] bytes, string fileName)
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                fs.Write(bytes, 0, bytes.Length);
            }

            return fileName;
        }

        private static void OsmStreamSourceToFile(PBFOsmStreamSource osmStreamSource, string fileName)
        {
            using (FileStream fileStream = new FileInfo(fileName).OpenWrite())
            {
                PBFOsmStreamTarget target = new PBFOsmStreamTarget(fileStream, true);

                osmStreamSource.Reset();

                target.Initialize();

                UpdateTarget(osmStreamSource, target);

                target.Flush();
                target.Close();
            }
        }

        private static void UpdateTarget(OsmStreamSource osmStreamSource, OsmStreamTarget osmStreamTarget)
        {
            if (useRegisterSource)
            {
                osmStreamTarget.RegisterSource(osmStreamSource, osmGeo => true);
                osmStreamTarget.Pull();
            }
            else
            {
                bool isFirst = true;

                foreach (OsmGeo osmGeo in osmStreamSource)
                {
                    Tag? tag = osmGeo.Tags?.FirstOrDefault(t => t.Key == KeyValuePair.Key);

                    switch (osmGeo.Type)
                    {
                        case OsmGeoType.Node:
                            if (isFirst)
                            {
                                for (int indexer = 0; indexer < 1; indexer++)
                                {
                                    (osmGeo as Node).Tags.Add(new Tag(KeyValuePair.Key + Guid.NewGuid(), KeyValuePair.Value));
                                }

                                isFirst = false;
                            }

                            osmStreamTarget.AddNode(osmGeo as Node);
                            break;
                        case OsmGeoType.Way:
                            osmStreamTarget.AddWay(osmGeo as Way);
                            break;
                        case OsmGeoType.Relation:
                            osmStreamTarget.AddRelation(osmGeo as Relation);
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
            }
        }
    }
}

我已经在 OSMSharp 的 GITHube 页面上发布了这个问题,链接在这里。任何帮助将不胜感激。

4

0 回答 0