คุณทำการแปลง Shapefiles ซึ่งเคยทำได้สำเร็จหลายร้อยครั้ง แต่ครั้งนี้หยุดทำงานด้วย TransformationException ไม่มีผลลัพธ์บางส่วนและไม่มีการบ่งชี้ที่ชัดเจนว่าบันทึกใดเป็นสาเหตุของปัญหา บ่อยครั้งสาเหตุคือพิกัดที่ไม่ถูกต้องหนึ่งจุดที่ซ่อนอยู่ท่ามกลางฟีเจอร์ที่ถูกต้องหลายพัน รายการนี้อธิบายว่าทำไมการแปลง Shapefile ถึงล้มเหลวด้วยข้อผิดพลาดนี้และวิธีแก้ใน C# โดยใช้ OperationErrorCollector ซึ่งเปิดตัวใน Aspose.GIS for .NET 26.6 คุณจะได้เรียนรู้วิธีทำให้การแปลงดำเนินต่อจนจบ เก็บฟีเจอร์ที่ถูกต้องทั้งหมด และรับรายงานที่แม่นยำของบันทึกที่ต้องการการตรวจสอบ

หากคุณต้องการเพียงโค้ดการแปลงพื้นฐานเท่านั้น ให้ดูที่ Convert Shapefile to KML in C#. คู่มือนี้ต่อยอดจากนั้นและมุ่งเน้นที่การจัดการข้อผิดพลาด.

ทำไมการแปลง Shapefile ถึงทำให้เกิด TransformationException

รูปแบบเป้าหมายส่วนใหญ่คาดหวังพิกัดในระบบพิกัดที่กำหนดเฉพาะ
เช่น KML จะใช้ลองจิจูดและละติจูด WGS 84 เสมอ
ระหว่างการแปลง Aspose.GIS จะทำการแปลงพิกัดทุกค่าจากระบบพิกัดต้นทางเป็นระบบพิกัดเป้าหมาย
หากพิกัดใดไม่สามารถแปลงได้ ไลบรารีจะโยนข้อยกเว้น TransformationException และการแปลงจะหยุดลง

สาเหตุที่พบบ่อยที่สุดคือ:

  • ค่าตัวแทน “ไม่มีข้อมูล”. บางเครื่องมือเขียนค่าตัวตรวจสอบแทนการปล่อยให้เรขาคณิตว่างเปล่า ตัวอย่างไฟล์ในบทความนี้มีจุดที่ (-1.7976931348623157E+308, -1.7976931348623157E+308), ซึ่งเป็นค่าต่ำสุดของ double ที่ไม่มีระบบพิกัดใดสามารถแปลงได้
  • พิกัดที่อยู่นอกช่วง. ค่าที่อยู่นอกพื้นที่ที่ถูกต้องของระบบพิกัดต้นทาง มักเกิดจากข้อผิดพลาดในการป้อนข้อมูลหรือการแปลงหน่วยที่ไม่ถูกต้อง
  • ไฟล์ .prj ที่ไม่ตรงกับข้อมูล. หากพิกัดที่ฉายเป็นเมตรถูกระบุเป็นพิกัดทางภูมิศาสตร์เป็นหน่วยองศา ค่าจำนวนมากจะอยู่นอกช่วงที่ถูกต้องอย่างมาก
  • บันทึกเรขาคณิตที่เสียหาย. การส่งออกแบบเก่าและไฟล์ที่เสียหายอาจมีค่าตัวเลขที่ไม่ถูกต้องในแต่ละบันทึก

ในทุกกรณี ปัญหามักจะจำกัดอยู่เพียงไม่กี่รายการเท่านั้น แต่พฤติกรรมเริ่มต้นจะละทิ้งการแปลงทั้งหมด

ทำไมคุณลักษณะนี้จึงสำคัญ

การหยุดที่ความล้มเหลวครั้งแรกนั้นปลอดภัย แต่มีค่าใช้จ่ายสูงในไพป์ไลน์จริง บันทึกที่ผิดพลาดหนึ่งรายการบังคับให้คุณต้องทำความสะอาดไฟล์ด้วยตนเองก่อนที่ข้อมูลใด ๆ จะถูกแปลง และข้อยกเว้นเพียงอย่างเดียวไม่บอกว่ามีบันทึกอื่น ๆ ที่ได้รับผลกระทบกี่รายการ เมื่อเปิดใช้งานการเก็บรวบรวมข้อผิดพลาด คุณสามารถ:

  • แปลงคุณลักษณะที่ถูกต้องทั้งหมดแทนที่จะสูญเสียไฟล์ทั้งหมดเป็นบันทึกที่เสียหายหนึ่งรายการ
  • บันทึกดัชนีและพิกัดของคุณลักษณะที่ถูกข้ามแต่ละรายการเพื่อให้สามารถซ่อมแซมข้อมูลต้นทางได้
  • รันการแปลงแบบแบตช์โดยไม่ต้องดูแลและงาน ETL โดยไม่เกิดการหยุดทำงานเมื่อรับอินพุตที่มีข้อผิดพลาด
  • ยอมรับ Shapefile ที่ผู้ใช้อัปโหลดในบริการเว็บและรายงานปัญหาข้อมูลกลับไปยังผู้ใช้

วิธีแก้ไขข้อผิดพลาดการแปลง Shapefile ใน C# ด้วย Aspose.GIS

Aspose.GIS for .NET เป็นไลบรารีที่จัดการได้สำหรับการอ่าน, เขียน และแปลงรูปแบบข้อมูลเชิงพื้นที่ เช่น Shapefile, KML, GeoJSON, GML และ File Geodatabase โดยไม่ต้องติดตั้งซอฟต์แวร์ GIS อื่นใด ๆ การรวบรวมข้อผิดพลาดต้องใช้เวอร์ชัน 26.6 หรือใหม่กว่า ติดตั้งแพ็กเกจจาก NuGet:

dotnet add package Aspose.GIS

หรือใช้ Package Manager Console:

Install-Package Aspose.GIS

ประเภทต่อไปนี้ใช้ในบทแนะนำนี้:

  • VectorLayer (Aspose.Gis): เปิด, สร้างและแปลงเลเยอร์เวกเตอร์. VectorLayer.Convert ทำการแปลง.
  • ConversionOptions (Aspose.Gis): เก็บการตั้งค่าการแปลง รวมถึง DestinationDriverOptions และ DestinationSpatialReferenceSystem.
  • KmlOptions (Aspose.Gis.Formats.Kml): ตัวเลือกไดรเวอร์ KML. มรดกคุณสมบัติ ErrorCollector จาก DriverOptions.
  • OperationErrorCollector (Aspose.Gis.Operations): เก็บข้อผิดพลาดที่สามารถกู้คืนได้. เปิดเผย Errors, Count, HasErrors, Add และ Clear.
  • OperationError and TransformationError (Aspose.Gis.Operations): แต่ละข้อผิดพลาดมี Message และ Exception. TransformationError เพิ่ม FeatureIndex, X, Y และ Z.
  • TransformationException (Aspose.Gis.SpatialReferencing): ถูกโยนเมื่อพิกัดไม่สามารถแปลงได้และไม่มีคอลเลกเตอร์แนบ.

วิธีแก้ไข TransformationException ระหว่างการแปลง Shapefile

การแก้ไขมีสองส่วน.
ขั้นแรก ให้แนบ OperationErrorCollector เพื่อให้การแปลงข้ามฟีเจอร์ที่ไม่ถูกต้องแทนที่จะล้มเหลว.
ขั้นที่สอง ใช้รายงานที่รวบรวมเพื่อซ่อมหรือเอาบันทึกเหล่านั้นออกจากแหล่งข้อมูล.
ขั้นตอนด้านล่างใช้การแปลง Shapefile เป็น KML เป็นตัวอย่าง.

1. เตรียมสภาพแวดล้อม

  1. สร้างโครงการคอนโซล .NET และเพิ่มแพคเกจ NuGet Aspose.GIS 26.6+
  2. คัดลอกไฟล์ Shapefile และไฟล์ที่เกี่ยวข้อง (.shp, .shx, .dbf, และ .prj) ลงในโฟลเดอร์เดียวกัน ตัวอย่างนี้ใช้ data/light-traffics.shp.
  3. เพิ่มเนมสเปซที่จำเป็น:
using System;
using System.IO;
using Aspose.Gis;
using Aspose.Gis.Formats.Kml;
using Aspose.Gis.Operations;
using Aspose.Gis.SpatialReferencing;

2. สร้าง OperationErrorCollector

คอลเลกเตอร์บันทึกข้อผิดพลาดที่สามารถกู้คืนได้ทุกข้อที่เกิดขึ้นระหว่างการแปลง สร้างอินสแตนซ์ใหม่สำหรับแต่ละการแปลงเพื่อไม่ให้ข้อผิดพลาดจากไฟล์ต่าง ๆ ถูกผสมกัน

// Records recoverable errors instead of throwing them.
var errors = new OperationErrorCollector();

3. แนบ Collector ผ่าน ConversionOptions

กำหนดคอลเล็กเตอร์ให้กับ KmlOptions.ErrorCollector จากนั้นส่งตัวเลือก KML เป็น DestinationDriverOptions การตั้งค่า DestinationSpatialReferenceSystem เป็น WGS 84 เป็นตัวเลือกสำหรับ KML แต่จะทำให้ระบบพิกัดเป้าหมายชัดเจนในโค้ดของคุณ.

var options = new ConversionOptions
{
    // KML always uses WGS 84; stating it makes the reprojection explicit.
    DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84,
    DestinationDriverOptions = new KmlOptions
    {
        ErrorCollector = errors // Skip and record features that fail transformation.
    }
};

4. เรียกใช้การแปลง

เรียก VectorLayer.Convert พร้อมด้วยเส้นทางต้นทาง, ตัวขับ Shapefile, เส้นทางปลายทาง, ตัวขับ KML และตัวเลือกที่คุณเพิ่งกำหนดค่าไว้.

string sourcePath = Path.Combine("data", "light-traffics.shp");
string destinationPath = Path.Combine("output", "light-traffics.kml");
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));

VectorLayer.Convert(sourcePath, Drivers.Shapefile, destinationPath, Drivers.Kml, options);

เมื่อฟีเจอร์ไม่สามารถแปลงได้ ไดรเวอร์ KML จะเพิ่มข้อผิดพลาดลงในคอลเลกเตอร์ ข้ามฟีเจอร์นั้นและดำเนินการต่อกับฟีเจอร์ถัดไป ไม่ได้มีการโยน TransformationException

5. รายงานฟีเจอร์ที่ข้ามและตรวจสอบผลลัพธ์

การแปลงที่คืนค่าปกติอาจยังคงข้ามฟีเจอร์บางอย่างได้ ดังนั้นควรตรวจสอบคอลเลกเตอร์หลังจากนั้นเสมอ แปลงแต่ละข้อผิดพลาดเป็น TransformationError เพื่อรับดัชนีฟีเจอร์และพิกัดที่ล้มเหลว แล้วเปิดไฟล์ผลลัพธ์เพื่อยืนยันจำนวนฟีเจอร์ที่ถูกเขียน

if (errors.HasErrors)
{
    Console.WriteLine($"Skipped {errors.Count} feature(s):");

foreach (var error in errors.Errors)
    {
        if (error is TransformationError transformationError)
        {
            Console.WriteLine(
                $"  Feature #{transformationError.FeatureIndex} at " +
                $"({transformationError.X}, {transformationError.Y}, {transformationError.Z}): {error.Message}");
        }
        else
        {
            Console.WriteLine($"  {error.Message}");
        }
    }
}

using (var layer = VectorLayer.Open(destinationPath, Drivers.Kml))
{
    Console.WriteLine($"Features written to KML: {layer.Count}");
}

สำหรับไฟล์ตัวอย่าง ตัวเก็บข้อมูลบันทึกข้อผิดพลาดหนึ่งรายการสำหรับจุดตัวแทน และฟีเจอร์ที่เหลือ (อย่างน้อย 444 รายการ) จะถูกเขียนลงในไฟล์ KML

ดัชนีฟีเจอร์และพิกัดในรายงานนี้ทำให้การแก้ไขสมบูรณ์ เปิดไฟล์ Shapefile ต้นฉบับในกระบวนการทำความสะอาดข้อมูลของคุณ ค้นหารายการที่รายงานและแก้ไขหรือเอาออก หากหลายรายการล้มเหลวโดยมีค่าที่ดูสมเหตุสมผล ให้ตรวจสอบไฟล์ .prj ก่อน เนื่องจากระบบพิกัดที่ไม่ตรงกันเป็นสาเหตุที่เป็นไปได้

6. โค้ดตัวอย่างเต็ม

แอปพลิเคชันคอนโซลเต็มรูปแบบด้านล่างทำการแปลงสองครั้ง ครั้งแรกใช้การตั้งค่าเริ่มต้นและทำให้เกิด TransformationException ครั้งที่สองแนบ OperationErrorCollector ข้ามฟีเจอร์ที่ไม่ถูกต้องและพิมพ์รายงาน

using System;
using System.IO;
using Aspose.Gis;
using Aspose.Gis.Formats.Kml;
using Aspose.Gis.Operations;
using Aspose.Gis.SpatialReferencing;

namespace ShapefileTransformationErrors
{
    internal class Program
    {
        private static void Main()
        {
            string sourcePath = Path.Combine("data", "light-traffics.shp");
            string outputFolder = "output";
            Directory.CreateDirectory(outputFolder);

// -----------------------------------------------------------------
            // Run 1: default behavior. The first failed transformation aborts
            // the whole conversion with a TransformationException.
            // -----------------------------------------------------------------
            string failFastPath = Path.Combine(outputFolder, "fail-fast.kml");
            try
            {
                VectorLayer.Convert(sourcePath, Drivers.Shapefile, failFastPath, Drivers.Kml);
                Console.WriteLine("Default conversion finished without transformation errors.");
            }
            catch (TransformationException ex)
            {
                Console.WriteLine($"Default conversion aborted: {ex.Message}");
                Console.WriteLine($"Failing coordinate: ({ex.X}, {ex.Y}, {ex.Z})");
            }

// -----------------------------------------------------------------
            // Run 2: error-tolerant conversion. Invalid features are skipped
            // and recorded in the collector; valid features are written.
            // -----------------------------------------------------------------
            string destinationPath = Path.Combine(outputFolder, "light-traffics.kml");

var errors = new OperationErrorCollector();
            var options = new ConversionOptions
            {
                DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84,
                DestinationDriverOptions = new KmlOptions
                {
                    ErrorCollector = errors
                }
            };

VectorLayer.Convert(sourcePath, Drivers.Shapefile, destinationPath, Drivers.Kml, options);

// Report every skipped feature so the source data can be repaired.
            if (errors.HasErrors)
            {
                Console.WriteLine($"Conversion completed with {errors.Count} skipped feature(s):");

foreach (var error in errors.Errors)
                {
                    if (error is TransformationError transformationError)
                    {
                        Console.WriteLine(
                            $"  Feature #{transformationError.FeatureIndex} at " +
                            $"({transformationError.X}, {transformationError.Y}, {transformationError.Z}): {error.Message}");
                    }
                    else
                    {
                        Console.WriteLine($"  {error.Message}");
                    }
                }
            }
            else
            {
                Console.WriteLine("Conversion completed with no errors.");
            }

// Verify the output file.
            using (var layer = VectorLayer.Open(destinationPath, Drivers.Kml))
            {
                Console.WriteLine($"Features written to KML: {layer.Count}");
            }
        }
    }
}

7. ข้อผิดพลาดทั่วไปและวิธีหลีกเลี่ยง

PitfallReasonFix
ErrorCollector or OperationErrorCollector does not compileทั้งสองถูกเพิ่มใน Aspose.GIS for .NET 26.6.อัปเกรดแพคเกจ NuGet เป็นเวอร์ชัน 26.6 หรือใหม่กว่า.
The conversion still throws TransformationExceptionไม่มีคอลเลกเตอร์ที่แนบกับตัวเลือกไดรเวอร์ปลายทางตั้งค่า ErrorCollector บนวัตถุตัวเลือกไดรเวอร์ที่กำหนดให้กับ ConversionOptions.DestinationDriverOptions.
A “successful” conversion is missing featuresคอลเลกเตอร์ทำการระงับข้อยกเว้น ทำให้ Convert คืนค่าปกติตรวจสอบ errors.HasErrors หลังจากแต่ละครั้งเรียกและบันทึกผลลัพธ์.
Treating skipped features as fixedคอลเลกเตอร์ข้ามบันทึกที่ไม่ถูกต้อง; มันไม่ได้ซ่อมแซมใช้ดัชนีฟีเจอร์และพิกัดที่รายงานเพื่อแก้ไขหรือเอาบันทึกออกจากข้อมูลต้นทาง.
Hundreds of features fail at onceไฟล์ .prj น่าจะไม่ตรงกับพิกัดจริงตรวจสอบระบบพิกัดของแหล่งข้อมูลก่อนที่จะตรวจสอบบันทึกแต่ละรายการ.
Errors from several files appear in one reportอินสแตนซ์คอลเลกเตอร์เดียวกันถูกใช้ซ้ำในการแปลงหลายครั้งสร้าง OperationErrorCollector ใหม่ต่อไฟล์หนึ่งไฟล์ หรือเรียก Clear() ระหว่างการทำงาน.
File-lock errors on repeated runsเลเยอร์ที่เปิดด้วย VectorLayer.Open ไม่ได้ถูกทำลายห่อ VectorLayer.Open ด้วยบล็อก using.

รับใบอนุญาตฟรี

คุณสามารถรับใบอนุญาตชั่วคราวฟรีสำหรับ Aspose.GIS ได้จากหน้าใบอนุญาตชั่วคราวของ Aspose: https://purchase.aspose.com/temporary-license/

แหล่งข้อมูลเพิ่มเติมฟรี

สรุป

A TransformationException ระหว่างการแปลง Shapefile มักหมายถึงมีบันทึกจำนวนเล็กน้อยที่มีพิกัดที่ไม่สามารถแปลงได้ เช่น ค่าตัวแทน, ตัวเลขอยู่นอกช่วง, หรือข้อมูลที่ไม่ตรงกับไฟล์ .prj ของมัน. การแก้ไขใน C# ต้องทำสองขั้นตอน: แนบ OperationErrorCollector เพื่อให้ Aspose.GIS for .NET ข้ามฟีเจอร์ที่ไม่ถูกต้องและดำเนินการแปลงให้เสร็จ, จากนั้นใช้ดัชนีฟีเจอร์และพิกัดที่เก็บรวบรวมมาเพื่อซ่อมแซมข้อมูลต้นฉบับ. ผลลัพธ์คือ pipeline ที่ยังคงส่งออกผลลัพธ์ที่ถูกต้องในขณะที่เปลี่ยนความล้มเหลวที่รุนแรงให้เป็นรายงานคุณภาพข้อมูลที่สามารถดำเนินการได้.

คำถามที่พบบ่อย

  1. ทำไม TransformationException จึงเกิดขึ้นเมื่อแปลง Shapefile? มันเกิดขึ้นเมื่อพิกัดไม่สามารถแปลงจากระบบพิกัดต้นทางไปยังระบบพิกัดเป้าหมายได้ สาเหตุทั่วไปได้แก่ค่าตัวแทน “no data” ค่าพิกัดที่อยู่นอกช่วงที่ถูกต้องของระบบพิกัดไฟล์ .prj ที่ไม่ตรงกับข้อมูลจริง และบันทึกเรขาคณิตที่เสียหาย

  2. อะไรจะเกิดขึ้นโดยค่าเริ่มต้นเมื่อพิกัดไม่สามารถแปลงได้? VectorLayer.Convert ขว้าง TransformationException และการแปลงหยุดลง. เริ่มตั้งแต่เวอร์ชัน 26.6, ข้อยกเว้นยังเปิดเผยค่าของ X, Y, และ Z ของพิกัดที่ล้มเหลว.

  3. เวอร์ชันใดของ Aspose.GIS for .NET รองรับ OperationErrorCollector? OperationErrorCollector และคุณสมบัติ DriverOptions.ErrorCollector ถูกแนะนำใน Aspose.GIS for .NET 26.6. เวอร์ชันก่อนหน้านี้ไม่ได้รวมไว้

  4. OperationErrorCollector สามารถซ่อมแซมพิกัดที่ไม่ถูกต้องได้หรือไม่?
    ไม่ใช่. มันข้ามฟีเจอร์ที่ล้มเหลวในการแปลงและบันทึกไว้, ดังนั้นผลลัพธ์จะมีเฉพาะฟีเจอร์ที่ถูกต้องเท่านั้น. ใช้ดัชนีฟีเจอร์และพิกัดที่รายงานเพื่อแก้ไขหรือเอารายการที่ผิดพลาดออกจากข้อมูลต้นฉบับ.

  5. ฉันสามารถใช้ OperationErrorCollector กับรูปแบบผลลัพธ์ที่ไม่ใช่ KML ได้หรือไม่? ErrorCollector ถูกกำหนดในคลาสฐาน DriverOptions ดังนั้นทุกคลาสตัวเลือกไดรเวอร์จะเปิดเผยมัน ตัวอย่างที่อธิบายไว้ครอบคลุมปลายทาง KML และ MapInfo TAB; ทดสอบพฤติกรรมกับไดรเวอร์เป้าหมายของคุณเองก่อนพึ่งพาในสภาพแวดล้อมการผลิต

  6. รายละเอียดของแต่ละข้อผิดพลาดที่รวบรวมมีอะไรบ้าง?
    แต่ละ OperationError จะให้ Message และ Exception ที่เป็นพื้นฐานไว้ด้วย. การล้มเหลวของการแปลงจะถูกรายงานเป็นอ็อบเจกต์ TransformationError ซึ่งจะเพิ่ม FeatureIndex และค่าของ X, Y และ Z ของพิกัดที่ล้มเหลว.

  7. ฉันจะรู้ได้อย่างไรว่าการแปลงเสร็จสมบูรณ์โดยไม่มีข้อผิดพลาดใดๆ? ตรวจสอบคุณสมบัติ HasErrors หรือ Count ของ collector หลังจากที่ VectorLayer.Convert คืนค่า การแปลงที่เสร็จสิ้นโดยไม่เกิดข้อยกเว้นอาจยังคงข้ามฟีเจอร์บางส่วนอยู่

อ่านต่อ