반응형

이번 글에서는 geotools를 활용해서 shpaefile을 Postgis로 변환하는 것에 대해 알아볼려고 한다.

 

dbf 파일에 직접 접근해서 데이터를 가져올 수 도 있지만 공간쿼리를가 필요한 경우 아무래도 postgis와 연동하면 수월하게 원하는 데이터를 가져올 수 있기 때문에 이 작업이 필요한거 같았다.

 

geotools에서 .dbf 파일에 접근하여 읽어서 데이터를 가져오는 방법도 있지만 오늘은 postgis 테이블로 컨버팅하는 방법에 대해 알아보자

 

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureStore;
import org.geotools.data.postgis.PostgisNGDataStoreFactory;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.CRS;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureVisitor;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

public class ShpaeToPostGIS {

	public static void main(String[] args)throws FactoryException, MalformedURLException, IOException, ClassNotFoundException, SQLException {
    		
            	String shapeFileLoc="파일경로/파일명.shp";
		    String postGISTblName = "테이블명";//생성할 테이블 이름 postgis에서 테이블 생성시 소문자로 생성됨 
		    String shapeEPSG = "좌표계";//ex)EPSG:4326 epsg.io 참조
		    
		    try {

	            //shapefileLoader 
	            Map<String, Object> shapeParams = new HashMap<>();
	            shapeParams.put("url", new File(shapeFileLoc).toURI().toURL());
	            shapeParams.put("charset", "EUC-KR"); // shape파일의 인코딩 ,설정하지 않으면 한글 깨짐
	            
	            DataStore shapeDataStore = DataStoreFinder.getDataStore(shapeParams);       

	            // feature type
	            String typeName = shapeDataStore.getTypeNames()[0];
	            FeatureSource<SimpleFeatureType,SimpleFeature> featSource = shapeDataStore.getFeatureSource(typeName);
	            FeatureCollection<SimpleFeatureType,SimpleFeature> featSrcCollection = featSource.getFeatures();
	            SimpleFeatureType ft = shapeDataStore.getSchema(typeName);

	            // feature type copy to set the new name
	            SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
	            builder.setName(postGISTblName);
	            builder.setAttributes(ft.getAttributeDescriptors());
	            builder.setCRS(ft.getCoordinateReferenceSystem());

	            SimpleFeatureType newSchema = builder.buildFeatureType();

	            // management of the projection system
	            CoordinateReferenceSystem crs = ft.getCoordinateReferenceSystem();

	            // test of the CRS based on the .prj file
	            Integer crsCode = CRS.lookupEpsgCode(crs, true);
	            
	            if (crsCode == null) {
                	//shp파일의 좌표계를 postgis 테이블을 생성할 스키마를 설정을해준다.
	                CoordinateReferenceSystem crsEpsg = CRS.decode(shapeEPSG);
	                newSchema = SimpleFeatureTypeBuilder.retype(newSchema,crsEpsg);
	            }

	            Map<String, Object> params = new HashMap<>();
	            params.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
	            params.put(PostgisNGDataStoreFactory.HOST.key, "host ip");
	            params.put(PostgisNGDataStoreFactory.PORT.key, 포트번호(Integer));
	            params.put(PostgisNGDataStoreFactory.SCHEMA.key, "스키마이름");
	            params.put(PostgisNGDataStoreFactory.DATABASE.key, "데이터베이스");
	            params.put(PostgisNGDataStoreFactory.USER.key, "유저이름");
	            params.put(PostgisNGDataStoreFactory.PASSWD.key, "패스워드");
			   
	            DataStore dataStore = DataStoreFinder.getDataStore(params);
	            dataStore.createSchema(newSchema);
	            
	           	 //shp 파일의 featurecollection을 새로 생성할 테이블에 추가해주면 된다.
               	 FeatureStore<SimpleFeatureType,SimpleFeature> featStore = (FeatureStore<SimpleFeatureType,SimpleFeature>)dataStore.getFeatureSource(postGISTblName);
	            
               	 featStore.addFeatures(featSrcCollection);
	        
	        } catch (Exception e) {
	            System.out.println("ERROR:"+e);
	        }
    }

}

 

당연한 이야기지만 먼저 디비 접속이 잘 되는지 확인해봐야 한다. 잘 된다 생각하고 확인안하고 했다가 한시간 헛수고했다.ㅜ

 

예전에 배웠던 방식은 gdal을 설치해서 gdal 명령어에 dbtype, projection, 파일경로, db 연결 정보 등 옵션을 추가해서 컨버트한 것만 알고 있었지만 이번에 geotools을 공부하면서 알게 되었다.

 

성능은 gdal이나 geotools나 비슷했던거 같다.

 

db에 임포트 할 때 어떻게 테이블에 insert 하는지는 아직 자세히 알아보지 않았지만 하나씩 insert 하는지 속성 갯수가 많으면 상당히 오래 걸렸다.

 

아직 이부분에 대해서는 데이터를 어떻게 하면 더 빠르게 처리할 수 있을지 공부하고 있다.

 

혹시 더 좋은 방안이 있다면 알려주시면 감사합니다.ㅎ

 

 

반응형

+ Recent posts