【问题标题】:Reading an ESRI shapefile from a zip-file during Runtime in Java - DataStoreFinder.getDataStore(connectParameters) returns null在 Java 运行时从 zip 文件中读取 ESRI shapefile - DataStoreFinder.getDataStore(connectParameters) 返回 null
【发布时间】:2012-12-23 21:46:14
【问题描述】:

我们正在构建一个用于上传包含 ESRI 形状文件的 zip 文件的服务。该服务应该能够读取 shapefile 并对其内容进行处理。所以我构建了一个类,将 zip 文件解压缩到临时文件夹(System.getProperty("java.io.tmpdir") 的子文件夹)。

另一个类从 Unzip 类调用 unzip 方法,然后尝试使用 Geotools 读取解压后的 shapefile。它使用 Geotools DataStoreFinder.getDataStore(Map params) 方法从解压缩的 shapefile 创建数据存储。这里出现了问题:getDataStore 方法返回 null。我测试了网址,它看起来没问题。派生 URL 的文件存在,是一个文件,可以由应用程序读取(使用 shapefile.exists()、shapefile.isFile()、shapefile.canRead() 进行测试)。那么,有什么问题呢?为什么会返回 null?

这是(相关的)代码:

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.geodan.equus.entity.dataset.BasicFeature;
import com.geodan.equus.exception.EquusException;
import com.geodan.equus.processor.EquusProcessor;
import com.geodan.util.io.UnzipUtils;
import com.vividsolutions.jts.geom.Geometry;

public class ShapefileProcessor implements EquusProcessor
{

    private static final File TEMP_UNZIP_DIR = new File(
        System.getProperty("java.io.tmpdir") + File.separator
                + "atlas_temp_unzip_dir");

    public static Set<BasicFeature> importFeatures(final File zipFile)
        throws EquusException
    {
        // Check if the input file has the zipfile extension 
        if (!zipFile.getName().endsWith(".zip"))
        {
            throw new EquusException(
                    "The file is not a zipfile. It cannot be processed.");
        }

        // Unzip the file
        try
        {
            UnzipUtils.unzip(zipFile, TEMP_UNZIP_DIR);
        }
        catch (IOException error)
        {
            throw new EquusException("The zipfile cannot be unzipped.", error);
        }

        // Validate whether the unzipped folder contains a shapefile and return it
        File shapefile = new File("");
        try
        {
            shapefile = findShapefile(TEMP_UNZIP_DIR);
        }
        catch (IOException error)
        {
            throw new EquusException(
                    "The zipfile does not contain a shapefile. Cannot process its contents.",
                error);
        }

        // Collect the features from the shapefile and put them into an iterator 
        FeatureIterator<SimpleFeature> featureIterator;
        try
        {
            featureIterator = readShapefile(shapefile);
        }
        catch (EquusException e)
        {
            throw new EquusException(e.getMessage(), e);
        }

        // Create a Set filled with the features in the FeatureIterator
        Set<BasicFeature> features = createFeatureSet(featureIterator);

        return features;

    }

    private static File findShapefile(File unzipPath) throws IOException
    {
        File shapefile = new File("");
        // Find first .shp file in the unzip folder
        File[] unzippedFiles = unzipPath.listFiles();
        for (int i = 0; i < unzippedFiles.length; i++)
        {
            if (unzippedFiles[i].getName().endsWith(".shp"))
            {
                shapefile = new File(unzipPath + File.separator
                        + unzippedFiles[i].getName());
                break;
            }
        }
        if (shapefile.toString() == "")
        {
            throw new IOException("No shapefile present in '" + unzipPath
                + "'.");
        }
        return shapefile;
    }

    private static FeatureIterator<SimpleFeature> readShapefile(File shapefile)
        throws EquusException
    {
        // Collects the features from a shapefile and puts them into an iterator
        FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection;
        try
        {
            Map<String, URL> connectParameters = new HashMap<String, URL>();
            connectParameters.put("url", shapefile.toURI().toURL());
            DataStore dataStore = DataStoreFinder.getDataStore(connectParameters);
            String typeName = dataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = dataStore.getFeatureSource(typeName);
                featureCollection = featureSource.getFeatures();
        }
        catch (Exception e)
        {
            throw new EquusException(
                    "Features cannot be retrieved from the shapefile.", e);
        }
        return featureCollection.features();
    }

    private static Set<BasicFeature> createFeatureSet(
            FeatureIterator<SimpleFeature> featureIterator)
    {
        SimpleFeature simpleFeature = null;
        Set<BasicFeature> features = new HashSet<BasicFeature>();
        while (featureIterator.hasNext())
        {
            simpleFeature = featureIterator.next();
            BasicFeature feature = new BasicFeature();
            feature.setGeometry((Geometry) simpleFeature.getDefaultGeometry());
            features.add(feature);
        }
        return features;
    }
}

【问题讨论】:

    标签: java null unzip geotools


    【解决方案1】:

    只需像这样使用ShapefileDataStore的构造函数:

    // URL url = file.toURI().toURL();
    DataStore shapefileStore = new ShapefileDataStore(url)
    

    【讨论】:

      【解决方案2】:

      虽然您的代码看起来正确,但我发现我们代码库中关键行的实现略有不同:

      Map<String, Object> map = new HashMap<>();
      map.put(ShapefileDataStoreFactory.URLP.key, url);
      map.put(ShapefileDataStoreFactory.CREATE_SPATIAL_INDEX.key, Boolean.TRUE);
      DataStore shapefileStore = DataStoreFinder.getDataStore(map);
      

      【讨论】:

        【解决方案3】:

        您的代码是正确的,但您的类路径缺少 ShapeFileDataStore。 通过添加例如:gt2-shapefile-2.3.2.jar

        来修复您的类路径

        或者直接使用

        DataStore shapefileStore = new ShapefileDataStore(url)
        

        这具有您立即会看到的优点,即您的代码由于缺少 shapefile 库而无法编译。

        Iterator availableStores =  DataStoreFinder.getAvailableDataStores();
        

        您可以输出所有可用数据存储的列表。如果为空或没有列出 ShapefileDataStoreFactory,您将知道原因是类路径。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-07
          • 1970-01-01
          • 2012-08-18
          • 1970-01-01
          • 2015-05-13
          • 2017-12-03
          • 2017-03-03
          相关资源
          最近更新 更多