คุณทำการแปลง 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. เตรียมสภาพแวดล้อม
- สร้างโครงการคอนโซล .NET และเพิ่มแพคเกจ NuGet Aspose.GIS 26.6+
- คัดลอกไฟล์ Shapefile และไฟล์ที่เกี่ยวข้อง (
.shp,.shx,.dbf, และ.prj) ลงในโฟลเดอร์เดียวกัน ตัวอย่างนี้ใช้data/light-traffics.shp. - เพิ่มเนมสเปซที่จำเป็น:
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. ข้อผิดพลาดทั่วไปและวิธีหลีกเลี่ยง
| Pitfall | Reason | Fix |
|---|---|---|
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/
แหล่งข้อมูลเพิ่มเติมฟรี
- เอกสาร: https://docs.aspose.com/gis/net/
- อ้างอิง API: https://reference.aspose.com/gis/net/
- แอปเว็บฟรี: https://products.aspose.app/gis/family
สรุป
A TransformationException ระหว่างการแปลง Shapefile มักหมายถึงมีบันทึกจำนวนเล็กน้อยที่มีพิกัดที่ไม่สามารถแปลงได้ เช่น ค่าตัวแทน, ตัวเลขอยู่นอกช่วง, หรือข้อมูลที่ไม่ตรงกับไฟล์ .prj ของมัน. การแก้ไขใน C# ต้องทำสองขั้นตอน: แนบ OperationErrorCollector เพื่อให้ Aspose.GIS for .NET ข้ามฟีเจอร์ที่ไม่ถูกต้องและดำเนินการแปลงให้เสร็จ, จากนั้นใช้ดัชนีฟีเจอร์และพิกัดที่เก็บรวบรวมมาเพื่อซ่อมแซมข้อมูลต้นฉบับ. ผลลัพธ์คือ pipeline ที่ยังคงส่งออกผลลัพธ์ที่ถูกต้องในขณะที่เปลี่ยนความล้มเหลวที่รุนแรงให้เป็นรายงานคุณภาพข้อมูลที่สามารถดำเนินการได้.
คำถามที่พบบ่อย
ทำไม TransformationException จึงเกิดขึ้นเมื่อแปลง Shapefile? มันเกิดขึ้นเมื่อพิกัดไม่สามารถแปลงจากระบบพิกัดต้นทางไปยังระบบพิกัดเป้าหมายได้ สาเหตุทั่วไปได้แก่ค่าตัวแทน “no data” ค่าพิกัดที่อยู่นอกช่วงที่ถูกต้องของระบบพิกัดไฟล์
.prjที่ไม่ตรงกับข้อมูลจริง และบันทึกเรขาคณิตที่เสียหายอะไรจะเกิดขึ้นโดยค่าเริ่มต้นเมื่อพิกัดไม่สามารถแปลงได้?
VectorLayer.Convertขว้างTransformationExceptionและการแปลงหยุดลง. เริ่มตั้งแต่เวอร์ชัน 26.6, ข้อยกเว้นยังเปิดเผยค่าของX,Y, และZของพิกัดที่ล้มเหลว.เวอร์ชันใดของ Aspose.GIS for .NET รองรับ OperationErrorCollector?
OperationErrorCollectorและคุณสมบัติDriverOptions.ErrorCollectorถูกแนะนำใน Aspose.GIS for .NET 26.6. เวอร์ชันก่อนหน้านี้ไม่ได้รวมไว้OperationErrorCollector สามารถซ่อมแซมพิกัดที่ไม่ถูกต้องได้หรือไม่?
ไม่ใช่. มันข้ามฟีเจอร์ที่ล้มเหลวในการแปลงและบันทึกไว้, ดังนั้นผลลัพธ์จะมีเฉพาะฟีเจอร์ที่ถูกต้องเท่านั้น. ใช้ดัชนีฟีเจอร์และพิกัดที่รายงานเพื่อแก้ไขหรือเอารายการที่ผิดพลาดออกจากข้อมูลต้นฉบับ.ฉันสามารถใช้ OperationErrorCollector กับรูปแบบผลลัพธ์ที่ไม่ใช่ KML ได้หรือไม่?
ErrorCollectorถูกกำหนดในคลาสฐานDriverOptionsดังนั้นทุกคลาสตัวเลือกไดรเวอร์จะเปิดเผยมัน ตัวอย่างที่อธิบายไว้ครอบคลุมปลายทาง KML และ MapInfo TAB; ทดสอบพฤติกรรมกับไดรเวอร์เป้าหมายของคุณเองก่อนพึ่งพาในสภาพแวดล้อมการผลิตรายละเอียดของแต่ละข้อผิดพลาดที่รวบรวมมีอะไรบ้าง?
แต่ละOperationErrorจะให้MessageและExceptionที่เป็นพื้นฐานไว้ด้วย. การล้มเหลวของการแปลงจะถูกรายงานเป็นอ็อบเจกต์TransformationErrorซึ่งจะเพิ่มFeatureIndexและค่าของX,YและZของพิกัดที่ล้มเหลว.ฉันจะรู้ได้อย่างไรว่าการแปลงเสร็จสมบูรณ์โดยไม่มีข้อผิดพลาดใดๆ? ตรวจสอบคุณสมบัติ
HasErrorsหรือCountของ collector หลังจากที่VectorLayer.Convertคืนค่า การแปลงที่เสร็จสิ้นโดยไม่เกิดข้อยกเว้นอาจยังคงข้ามฟีเจอร์บางส่วนอยู่
