158 lines
5.4 KiB
C#
158 lines
5.4 KiB
C#
|
|
using System.IO.Compression;
|
|||
|
|
using System.Resources;
|
|||
|
|
using System.Text;
|
|||
|
|
using Flurl.Http;
|
|||
|
|
using NetTopologySuite.Geometries;
|
|||
|
|
using NetTopologySuite.IO;
|
|||
|
|
|
|||
|
|
namespace OpenAuth.App.ServiceApp.ShpGeo.Utils;
|
|||
|
|
|
|||
|
|
public class ShapeUtil
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="shpPath"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
/// <exception cref="NotImplementedException"></exception>
|
|||
|
|
public static List<Dictionary<string, object>> getRows(string shpPath)
|
|||
|
|
{
|
|||
|
|
throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 支持
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="shpPath"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static List<Dictionary<string, object>> ReadAllGeometry(string shpPath)
|
|||
|
|
{
|
|||
|
|
// 取得后缀,如果是zip,则解压
|
|||
|
|
var fileExtension = Path.GetExtension(shpPath);
|
|||
|
|
if (!fileExtension.Equals(".shp") && !fileExtension.Equals(".zip"))
|
|||
|
|
{
|
|||
|
|
throw new Exception("不支持的文件格式");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置字符编码
|
|||
|
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|||
|
|
var gbk = Encoding.GetEncoding("gbk");
|
|||
|
|
if (fileExtension == ".zip")
|
|||
|
|
{
|
|||
|
|
var extractPath = Path.GetDirectoryName(shpPath) + "\\temp";
|
|||
|
|
Directory.CreateDirectory(extractPath);
|
|||
|
|
|
|||
|
|
using (var archive = ZipFile.OpenRead(shpPath))
|
|||
|
|
{
|
|||
|
|
// 列举ZIP文件中的条目
|
|||
|
|
foreach (var entry in archive.Entries)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine("zip 包含文件:");
|
|||
|
|
var fileName = gbk.GetString(Encoding.Default.GetBytes(entry.FullName));
|
|||
|
|
Console.WriteLine(fileName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取ZIP文件中的所有文件到指定目录
|
|||
|
|
|
|||
|
|
foreach (var entry in archive.Entries)
|
|||
|
|
{
|
|||
|
|
if (entry.Name != string.Empty)
|
|||
|
|
{
|
|||
|
|
// 确保完整路径存在 entry.FullName 是否可以编码
|
|||
|
|
var fixedEntryName = entry.FullName.Replace("/", "");
|
|||
|
|
var destinationPath = Path.GetFullPath(Path.Combine(extractPath, fixedEntryName));
|
|||
|
|
Console.WriteLine("解压文件路径:" + destinationPath);
|
|||
|
|
if (!destinationPath.StartsWith(Path.GetFullPath(extractPath) + Path.DirectorySeparatorChar))
|
|||
|
|
{
|
|||
|
|
throw new UnauthorizedAccessException("试图提取的文件超出了目标文件夹的路径边界。");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取条目到目标路径
|
|||
|
|
entry.ExtractToFile(destinationPath, overwrite: true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 遍历解压目录,是否有shp后缀的文件
|
|||
|
|
if (!Directory.Exists(extractPath))
|
|||
|
|
{
|
|||
|
|
throw new Exception("文件解压失败");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查找
|
|||
|
|
var dirInfo = new DirectoryInfo(extractPath);
|
|||
|
|
// zip 压缩包中只有一个shp文件
|
|||
|
|
shpPath = dirInfo.GetFiles("*.shp", SearchOption.AllDirectories)[0].FullName;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var data = ParseShape(shpPath, null);
|
|||
|
|
var tifPath = data.First()["Image"].ToString();
|
|||
|
|
if (CheckForGarbledText(tifPath))
|
|||
|
|
{
|
|||
|
|
// 乱码,需要解码
|
|||
|
|
data = ParseShape(shpPath, gbk);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return data;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static List<Dictionary<string, object>> ParseShape(string shpPath, Encoding code)
|
|||
|
|
{
|
|||
|
|
using var dataReader = code == null
|
|||
|
|
? new ShapefileDataReader(shpPath, GeometryFactory.Default)
|
|||
|
|
: new ShapefileDataReader(shpPath, GeometryFactory.Default, code);
|
|||
|
|
Console.WriteLine("记录数" + dataReader.RecordCount);
|
|||
|
|
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
|
|||
|
|
while (dataReader.Read())
|
|||
|
|
{
|
|||
|
|
Dictionary<string, object> row = new Dictionary<string, object>();
|
|||
|
|
// 读取列
|
|||
|
|
for (int i = 0, j = 0; i < dataReader.FieldCount; i++)
|
|||
|
|
{
|
|||
|
|
var colName = dataReader.GetName(i);
|
|||
|
|
var value = dataReader.GetValue(i);
|
|||
|
|
row.Add(colName, value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rows.Add(row);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return rows;
|
|||
|
|
// return NetTopologySuite.IO.Esri.Shapefile.ReadAllGeometries(shpPath);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool CheckForGarbledText(string content)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 检查是否有不可打印的字符
|
|||
|
|
foreach (char c in content)
|
|||
|
|
{
|
|||
|
|
if (char.IsControl(c) && !char.IsWhiteSpace(c))
|
|||
|
|
{
|
|||
|
|
return true; // 发现不可打印的控制字符
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否有不常见的字符
|
|||
|
|
foreach (char c in content)
|
|||
|
|
{
|
|||
|
|
if (c > 0x7F && !char.IsLetterOrDigit(c) && !char.IsPunctuation(c) && !char.IsSymbol(c) &&
|
|||
|
|
!char.IsWhiteSpace(c))
|
|||
|
|
{
|
|||
|
|
return true; // 发现不常见的字符
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false; // 没有发现乱码
|
|||
|
|
}
|
|||
|
|
catch (DecoderFallbackException)
|
|||
|
|
{
|
|||
|
|
return true; // 解码失败,存在乱码
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
return true; // 其他异常,可能表示存在乱码
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|