基于Java標準庫讀取CSV實現天地圖POI分類快速導入PostGIS數據庫實戰

目錄

前言

一、天地圖POI分類簡介

1、數據表格

2、分類結構

二、從CSV導入到PG數據庫

1、CSV解析流程

2、數據轉換及入庫

3、入庫成果及檢索

三、總結


前言

????????在之前的博客中,曾經對高德地圖和百度地圖的POI分類以及使用PostGIS數據庫來進行管理的模式進行了詳細的介紹。之前的博文列表:

序號博客地址
1基于ApachePOI實現百度POI分類快速導入PostgreSQL數據庫實戰
2基于ApachePOI實現高德POI分類快速導入PostgreSQL數據庫實戰

????????相信大家在平時的日常生活中,用的比較多的肯定是百度地圖和高德地圖。雖然天地圖在移動端的使用市場沒有前兩者的份額多。但是作為官方的標準,天地圖還是擁有自己得天獨厚的優勢,除了本身最具權威的地理數據,同時還有承載著官方標準的執行。因此天地圖的POI數據也是非常重要的,因此可以作為我們日常數據分析和處理的一個可靠的信息來源。不同的平臺對POI的分級分類都有所不同,相信看過上面兩篇博文的朋友一定知道,不同的廠商,對于POI分類時,它的大類和小類的定義一定是不一樣的。但是天地圖POI的分類存在非常大的差異,層次結構也是不一樣的。如下圖:

?????????天地圖的POI分類從大類來說就跟高德和百度不一樣。單從一級大類的數量來說,百度擁有?32個,而高德只區分了25個,天地圖居然有58個,在數量上天地圖是比較多的(是否可以再精簡和合并呢,需要討論),比前兩個加起來都多。另外從層級上來說,高德通常只區分了3級分類,而百度竟然有5級分類,然而天地圖在層級上非常簡單,只有2級展示,從扁平的角度來說,天地圖的扁平化做的不錯。

????????那么本文即來重點講講天地圖POI分類與高德POI分類以及百度POI分類存在什么不一樣的地方,同時結合代碼深入講解使用Java標準庫來讀取天地圖的POI 分類兵如何進行數據導入到PostGIS空間數據庫中,也為各類基于 POI 分類數據的地理信息系統開發、商業智能分析以及城市規劃應用等,鋪設一條從數據獲取到存儲利用的高效路徑,助力行業在空間數據賦能下實現精準決策與創新發展。

一、天地圖POI分類簡介

????????本節將首先重點介紹天地圖地圖的POI分類信息,在之前的博客中我們設計了用于POI管理的物理表,這里可以繼續用來存儲天地圖對應的POI分類信息。然后使用數據庫腳本的方法對POI分類信息進行錄入管理。對于天地圖而言,其POI的分類較多,但是層級簡單,因此這一節我們來詳細的解讀一下天地圖的POI分類,讓大家對分類信息有進一步的了解,為下一步對數據層級組裝和批量解析入庫打下牢固的基礎。

1、數據表格

? ? ? ? 與之前介紹的內容一樣,大家可以從天地圖的地圖開放平臺中獲取其最新的POI分類的CSV表格(是的,你沒有看錯,官方提供的確實是CSV而不是Excel,如果需要使用Excel也可以將CSV轉一下格式),這里我將從官網下載的類型截取一部分給大家參考。下載鏈接傳送門:分類編碼表。下面來看下官方在數據檢索的相關介紹:

1.1.1輸入參數說明

參數值參數說明參數類型是否必備備注(值域)
keyWord搜索的關鍵字String必填
specify指定行政區的國標碼(行政區劃編碼表)嚴格按照行政區劃編碼表中的(名稱,gb碼)String必填下載行政區劃編碼表。9位國標碼,如:北京:156110000或北京。
queryType服務查詢類型參數String必填12:行政區劃區域搜索服務。
start返回結果起始位(用于分頁和緩存)默認0String必填0-300,表示返回結果的起始位置。
count返回的結果數量(用于分頁和緩存)String必填1-300,返回結果的條數。
dataTypes數據分類(分類編碼表)String可選下載分類編碼表,參數可以分類名稱或分類編碼。多個分類用","隔開(英文逗號)。
show返回poi結果信息類別String可選取值為1,則返回基本poi信息; 取值為2,則返回詳細poi信息

????????這里不進行贅述,需要原始CSV表格的,可以去網站上下載。打開下載后的表格數據如下:

?

?

????????從上面這張圖可以看出天地圖的POI分類確實分的比較簡單。 同時也能看到一個比較明顯的區別,與百度的POI分類不一樣的是,天地圖有編碼的概念。同樣的,基于天地圖地圖的POI檢索可以從返回接口中看到其對應的POI分類值為:

{"eaddress": "","address": "榮濱南路東段11號附28附近","city": "","provinceCode": "156500000","cityCode": "","county": "榮昌區","typeName": "副食專賣店","source": "0","typeCode": "130207","lonlat": "105.590250,29.416870","countyCode": "156500153","ename": "","province": "重慶市","phone": "18716232760","poiType": "101","name": "李氏鹵鵝","hotPointID": "50166082CE55CFF5"
}

????????其中typeCode對應poi分類的類別編碼,而typeName則表示具體的類別名稱。

2、分類結構

????????在了解了天地圖的POI分類之后,下面我們基于之前設計的數據庫物理表和分類信息構建樹形的信息。因此需要對其分類采取細致的分類管理。在進行樹形層次構建時,我們根據分類名稱來進行統一管理:

?

?????????這個結構是天地圖POI分類管理的基礎,也是后面的數據程序解析的基礎。我們將使用編碼來進行數據的解析及入庫。 在CSV中,很大的大類和種類都是重復的,因此需要在入庫時將類別進行去重分類,最終構建一棵完整的POI分類樹。?

二、從CSV導入到PG數據庫

????????本節將詳細介紹在Java中使用標準庫實現從CSV中解析到存儲至PostgreGIS中,主要包含兩個方面,第一個是如何使用Java標準庫來進行CSV解析。第二個方面是如何基于Mybatis實現程序的批量入庫。關于數據處理流程與高德和百度POI入庫的流程一致,基本分為三個步驟:第一步是批量讀取數據源,第二步是將數據源解析出POI分類數據,最后將分類好的數據導入到PG數據庫中。

1、CSV解析流程

? ? ? ? 首先還是對天地圖下載的CSV格式的POI分類進行解析,在進行POI的分類進行構建時尤其重要,為了防止各層級在構建時出現重復的情況,這里采用LinkedHashMap集合來進行重復判斷,在存儲集合對象時,將分類編碼作為map的key,而具體分類對象作為value。在天地圖的POI分類編碼中,可以發現將編碼的前四位和后兩位可以拆開,后兩位如果是00的一般都是父類節點,通過我們的觀察可以看到在后續的對象去重判斷時,key就是重復的標記。為了實現從CSV格式的文件中讀取數據,這里首先介紹一下CSV的解析流程。在正式講解數據導入時,需要明確一個信息,就是在CSV數據的每一行中,只要遇到-這個字符就基本表示再往后讀一個單元格,當前行的數據讀取任務結束。

????????第一步:一些不要的輔助信息,比如需要定義需要處理的文件本地路徑地址。代碼如下:

@Autowired
private IPoiCategoryService poiCateGoryService;
private static final String TDT_POI_CSV_FILE = "C:/Users/Administrator/Desktop/天地圖及相關信息/天地圖Type-數據分類(分類編碼表).csv";
private static final String TRIGGER_CHAR = "-";

????????第二步:CSV解析實現

????????為了能夠正確的解析CSV數據,這里需要額外定外定義兩個參數,以此保證數據的準確解析。關于CSV的解析實現代碼如下:

// 自定義CSV行解析(處理帶逗號的字段)
private static String[] parseCsvLine(String line) {java.util.List<String> fields = new java.util.ArrayList<>();StringBuilder field = new StringBuilder();boolean inQuotes = false;for (char c : line.toCharArray()) {if (c == '"') {inQuotes = !inQuotes; // 切換引號狀態} else if (c == ',' && !inQuotes) {fields.add(field.toString());field.setLength(0); // 重置} else {field.append(c);}}fields.add(field.toString()); // 添加最后一個字段return fields.toArray(new String[0]);
}// 清理單元格值
private static String cleanCellValue(String value) {// 去除首尾空格和引號value = value.trim();if (value.startsWith("\"") && value.endsWith("\"")) {value = value.substring(1, value.length() - 1);}// 處理轉義的雙引號return value.replace("\"\"", "\"");
}

????????第三步:CSV數據解析,實現最基本的數據解析讀取和基礎配置之后,下面就可以來實現對CSV數據的具體讀取,這里采取的是直接的Java標準庫解析的方法。實例代碼如下:

private static LinkedHashMap<String,PoiCategory> csv2Map(){// UTF-8, GBK, GB2312, ISO-8859-1, Windows-1252Charset charset = Charset.forName("GBK"); // 根據實際文件編碼設置LinkedHashMap<String,PoiCategory> amapPoiTypeMap = new LinkedHashMap<String, PoiCategory>(); try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(TDT_POI_CSV_FILE), charset))) {String line = "";int rowNum = 0;while ((line = br.readLine()) != null) {rowNum++;String[] cells = parseCsvLine(line); // 使用自定義解析方法處理帶逗號的字段boolean foundTrigger = false;List<String> poiCategories = new ArrayList<String>();String poiCategoryCode = "";//獲取每一行的的每個格子的數據for (int i = 0; i < cells.length; i++) {String cellValue = cleanCellValue(cells[i]);//System.out.println(cellValue);if (cellValue.contains(TRIGGER_CHAR)) {foundTrigger = true;//System.out.println("[行 " + rowNum + "] 觸發單元格: " + cellValue);if (i + 1 < cells.length) {String nextValue = cleanCellValue(cells[i + 1]);poiCategoryCode = nextValue;//System.out.println("→ 終止單元格: " + nextValue);} else {System.out.println("→ 終止單元格: (空)");}break;}else {poiCategories.add(cellValue);}}if (!foundTrigger) {System.out.println("行 " + rowNum + ": 未找到觸發字符");}//執行分類預處理if(foundTrigger) {String prefix_head = poiCategoryCode.substring(0,4);String prefix_tail = poiCategoryCode.substring(4);if(prefix_tail.equalsIgnoreCase("00")) {//00表示大類String levelFirst = poiCategoryCode;//處理一級,添加到集合中if(!amapPoiTypeMap.containsKey(levelFirst)) {PoiCategory category = new PoiCategory(IdWorker.getId(),1944421516292726785L,"0,100,1944421516292726785",String.join("/", poiCategories),StringUtils.EMPTY,levelFirst);amapPoiTypeMap.put(levelFirst, category);}}else {//剩下表示小類if(!amapPoiTypeMap.containsKey(poiCategoryCode)) {String _parentKey = prefix_head + "00";PoiCategory parentCategory = amapPoiTypeMap.get(_parentKey);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,String.join("/", poiCategories),StringUtils.EMPTY,poiCategoryCode);amapPoiTypeMap.put(poiCategoryCode, category);}}}}} catch (IOException e) {e.printStackTrace();}return amapPoiTypeMap;
}

2、數據轉換及入庫

????????將CSV數據成功的解析轉換成LinkedHashMap之后,事情還遠遠沒結束,接下來需要將獲取的LinkedHashMap轉換成ArrayList。為了在查詢數據的時候方便,在正式入庫之前還需要增加一家額外的輔助信息,信息如下:

/**
* - 將map集合轉換成list集合
* @param amapPoiTypeMap
* @return
*/
private static List<PoiCategory> convertMap2DataList(LinkedHashMap<String,PoiCategory> amapPoiTypeMap) {List<PoiCategory> categoryData = new ArrayList<PoiCategory>();Date now = DateUtils.getNowDate();for (PoiCategory value : amapPoiTypeMap.values()) {value.setPlatform("tianditu");value.setDelFlag(0);value.setStatus(0);value.setOrderNum(1);value.setCreateTime(now);categoryData.add(value);}return categoryData;
}

????????到這里,我們就已經實現了如何使用Java標準庫來解析CSV文件,并且將數據都讀到了LinkedHashMap對象中,接下來就調用上述的方法來組裝成一個完整的數據導入實例,核心代碼如下:

@Test
public void writer2DB() {//step1、讀取CSV到Map集合中LinkedHashMap<String,PoiCategory> map = csv2Map();//step2、將map轉成list集合List<PoiCategory> categoryData = convertMap2DataList(map);//step3、插入到數據庫中for (PoiCategory poiCategory : categoryData) {System.out.println(poiCategory);}//step4、數據入庫 poiCateGoryService.batchInsertPoiCategory(categoryData);System.out.println("finished...");
}

3、入庫成果及檢索

????????完成以上的程序編寫,并運行操作后就完成了天地圖POI分類數據的PostGIS數據庫導入操作,程序執行完成后,可以在控制臺看到以下輸出:

????????為了驗證是否在數據庫中是否也保存了這些數據,可以使用以下SQL語句進行查詢:?

select * from biz_poi_category t where platform = 'tianditu';

??????????在客戶端軟件中執行以上SQL后可以看到以下結果:

三、總結

????????以上就是本文的主要內容,支持對天地圖的POI分類的CSV入庫及檢索就基本完成,后續我們將深入使用POI信息以及如何進行相應數據的采集。那么本文即來重點講講天地圖POI分類與高德和百度POI分類存在什么不一樣的地方,需要注意的是,本文讀取的文件不是Excel而是CSV格式,因此也深入講解了如何使用Java標準庫來解析天地圖的POI分類文件,同時深入講解天地圖?POI 分類如何進行數據導入,如何將CSV數據轉為LinkedHashMap,再到ArrayList,最后批量入庫。也為各類基于 POI 分類數據的地理信息系統開發、商業智能分析以及城市規劃應用等,鋪設一條從數據獲取到存儲利用的高效路徑,助力行業在空間數據賦能下實現精準決策與創新發展。行文倉促,難免有許多不足之處,如有不足,在此懇請各位專家博主在評論區不吝留言指出,不勝感激。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91845.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91845.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91845.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

人-AI交互中的信息論不同于傳統的信息論,其信息的增量≠不確定性的減量

在人機交互&#xff08;Human-AI Interaction, HAI&#xff09;領域&#xff0c;信息論的應用確實與傳統的信息論有所不同。這種差異主要源于人機交互HAI中信息的復雜性、動態性以及人類認知的特點。1. 傳統信息論的核心概念傳統信息論由克勞德香農&#xff08;Claude Shannon&…

K8s 通過 Scheduler Extender 實現自定義調度邏輯

1. 為什么需要自定義調度邏輯 什么是所謂的調度? 所謂調度就是指給 Pod 對象的 spec.nodeName 賦值 待調度對象則是所有 spec.nodeName 為空的 Pod 調度過程則是從集群現有的 Node 中為當前 Pod 選擇一個最合適的 實際上 Pod 上還有一個平時比較少關注的屬性&#xff1a;…

7.19 換根dp | vpp |滑窗

lcr147.最小棧通過兩個棧 維護實現class MinStack { public:stack<int> A, B;MinStack() {}void push(int x) {A.push(x);if(B.empty() || B.top() > x)B.push(x);}void pop() {if(A.top() B.top())B.pop();A.pop();}int top() {return A.top();}int getMin() {retur…

以太坊的心臟與大腦:詳解執行客戶端(EL)與共識客戶端(CL)

好的&#xff0c;各位技術同道&#xff0c;歡迎再次光臨我的博客。在上一篇文章中&#xff0c;我們聊了如何搭建一個以太坊測試節點&#xff0c;并提到了節點需要同時運行“執行客戶端”和“共識客戶端”。很多朋友對此表示了濃厚興趣&#xff0c;想深入了解這兩者究竟是什么&a…

Debian-10,用glibc二進制預編譯包,安裝Mysql-5.7.44 筆記250716

Debian-10,用glibc二進制預編譯包,安裝Mysql-5.7.44 筆記250716 &#x1f4e6; 一步腳本 #!/bin/bash### 安裝依賴 apt install -y libaio1 libnuma1 libncurses5### 下載MySQL-5.7.44 的 glib二進制包: mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz ,(如果不存在) mkdir…

用邏輯回歸(Logistic Regression)處理鳶尾花(iris)數據集

# 導入必要的庫 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from…

華大北斗TAU1201-1216A00高精度雙頻GNSS定位模塊 自動駕駛專用

在萬物互聯的時代&#xff0c;您還在為定位不準、信號丟失而煩惱嗎&#xff1f;TAU1201-1216A00華大北斗高精度定位模塊TAU1201是一款高性能的雙頻GNSS定位模塊&#xff0c;搭載了華大北斗的CYNOSURE III GNSS SoC 芯片&#xff0c;該模塊支持新一代北斗三號信號體制&#xff0…

堅持繼續布局32位MCU,進一步完善產品陣容,96Mhz主頻CW32L012新品發布!

在全球MCU市場競爭加劇、國產替代加速的背景下&#xff0c;嵌入式設備對核心控制芯片的性能、功耗、可靠性及性價比提出了前所未有的嚴苛需求。為適應市場競爭&#xff0c;2025年7月16日&#xff0c;武漢芯源半導體正式推出基于CW32L01x系列低功耗微控制器家族的全新成員&#…

用線性代數推導碼分多址(CDMA)

什么是碼分多址 碼分多址&#xff1a;CDMA允許多個用戶同時、在同一頻率上傳輸數據。它通過給每個用戶分配唯一的、相互正交的二進制序列來實現區分。用戶的數據比特被這個碼片序列擴展成一個高速率的信號&#xff0c;然后在接收端通過相同的碼片序列進行相關運算來回復原數據 …

mac 配置svn

1.查看brew的版本&#xff1a;brew install subversion2.安裝brew命令&#xff1a;bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"3.把路徑添加到path環境變量&#xff1a;echo export PATH"/opt/homebrew/b…

使用 .NET Core 的原始 WebSocket

在 Web 開發中&#xff0c;后端存在一些值得注意的通信協議&#xff0c;用于將更改通知給已連接的客戶端。所有這些協議都用于處理同一件事。但鮮為人知的協議很少&#xff0c;鮮為人知的協議也很少。今天&#xff0c;將討論 WebSocket&#xff0c;它在開發中使用最少&#xff…

編程實現Word自動排版:從理論到實踐的全面指南

在現代辦公環境中&#xff0c;文檔排版是一項常見但耗時的工作。特別是對于需要處理大量文檔的專業人士來說&#xff0c;手動排版不僅費時費力&#xff0c;還容易出現不一致的問題。本文將深入探討如何通過編程方式實現Word文檔的自動排版&#xff0c;從理論基礎到實際應用&…

力扣經典算法篇-25-刪除鏈表的倒數第 N 個結點(計算鏈表的長度,利用棧先進后出特性,雙指針法)

1、題干 給你一個鏈表&#xff0c;刪除鏈表的倒數第 n 個結點&#xff0c;并且返回鏈表的頭結點。 示例 1&#xff1a;輸入&#xff1a;head [1,2,3,4,5], n 2 輸出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 輸入&#xff1a;head [1], n 1 輸出&#xff1a;[] 示例 3&…

VIT速覽

當我們取到一張圖片&#xff0c;我們會把它劃分為一個個patch&#xff0c;如上圖把一張圖片劃分為了9個patch&#xff0c;然后通過一個embedding把他們轉換成一個個token&#xff0c;每個patch對應一個token&#xff0c;然后在輸入到transformer encoder之前還要經過一個class …

【服務器與部署 14】消息隊列部署:RabbitMQ、Kafka生產環境搭建指南

【服務器與部署 14】消息隊列部署&#xff1a;RabbitMQ、Kafka生產環境搭建指南 關鍵詞&#xff1a;消息隊列、RabbitMQ集群、Kafka集群、消息中間件、異步通信、微服務架構、高可用部署、消息持久化、生產環境配置、分布式系統 摘要&#xff1a;本文從實際業務場景出發&#x…

LeetCode中等題--167.兩數之和II-輸入有序數組

1. 題目 給你一個下標從 1 開始的整數數組 numbers &#xff0c;該數組已按 非遞減順序排列 &#xff0c;請你從數組中找出滿足相加之和等于目標數 target 的兩個數。如果設這兩個數分別是 numbers[index1] 和 numbers[index2] &#xff0c;則 1 < index1 < index2 <…

【C# in .NET】19. 探秘抽象類:具體實現與抽象契約的橋梁

探秘抽象類:具體實現與抽象契約的橋梁 在.NET類型系統中,抽象類是連接具體實現與抽象契約的關鍵橋梁,它既具備普通類的狀態承載能力,又擁有類似接口的行為約束特性。本文將從 IL 代碼結構、CLR 類型加載機制、方法調度邏輯三個維度,全面揭示抽象類的底層工作原理,通過與…

Apache RocketMQ + “太乙” = 開源貢獻新體驗

Apache RocketMQ 是 Apache 基金會托管的頂級項目&#xff0c;自 2012 年誕生于阿里巴巴&#xff0c;服務于淘寶等核心交易系統&#xff0c;歷經多次雙十一萬億級數據洪峰穩定性驗證&#xff0c;至今已有十余年發展歷程。RocketMQ 致力于構建低延遲、高并發、高可用、高可靠的分…

永磁同步電機控制算法--弱磁控制(變交軸CCR-VQV)

一、原理介紹CCR-FQV弱磁控制不能較好的利用逆變器的直流側電壓&#xff0c;造成電機的調速范圍窄、效率低和帶載能力差。為了解決CCR-FQV弱磁控制存在的缺陷&#xff0c;可以在電機運行過程中根據工況的不同實時的改變交軸電壓給定uq?的值&#xff0c;實施 CCR-VQV弱磁控制。…

達夢數據守護集群搭建(1主1實時備庫1同步備庫1異步備庫)

目錄 1 環境信息 1.1 目錄信息 1.2 其他環境信息 2 環境準備 2.1 新建dmdba用戶 2.2 關閉防火墻 2.3 關閉Selinux 2.4 關閉numa和透明大頁 2.5 修改文件打開最大數 2.6 修改磁盤調度 2.7 修改cpufreq模式 2.8 信號量修改 2.9 修改sysctl.conf 2.10 修改 /etc/sy…