I am working on geotools where I had created a FeatureCollection having the difference of the other two FeatureCollections.

I referred below link for this Comparing two shapefiles(layers) and display the differences in features in MapContent object in GeoTools

Now I am trying to create shapefile for the new FeatureCollection generated. But while doing so the .dbf file which is getting generated is empty. How can I get the new .dbf file contain the features of differenced FeatureCollection.

Mentioning my code below :

package org.geotools.tutorial.quickstart;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;

public class DifferenceDemo {

    public static void main(String[] args) throws IOException {
        String sourceFile1 = "C:/Users/neha.vashishth/Documents/GISFiles/sample1/sample1/polygon1.shp";
        File file1 = new File(sourceFile1);
        FileDataStore store1 = FileDataStoreFinder.getDataStore(file1);
        SimpleFeatureSource featureSource1 = store1.getFeatureSource();
        SimpleFeatureCollection col1 = featureSource1.getFeatures();

        String sourceFile2 = "C:/Users/neha.vashishth/Documents/GISFiles/sample2/sample2/polygon1.shp";
        File file2 = new File(sourceFile2); 
        FileDataStore store2 = FileDataStoreFinder.getDataStore(file2);
        SimpleFeatureSource featureSource2 = store2.getFeatureSource();
        SimpleFeatureCollection col2 = featureSource2.getFeatures();
        Style style = SLD.createSimpleStyle(featureSource1.getSchema(), Color.blue);
        SimpleFeatureCollection diffcol3 = difference(col1, col2);  
        SimpleFeatureCollection diffcol4 = difference(col2, col1);  
        Layer layer4 = new FeatureLayer(diffcol3, style);
        MapContent mapContent = new MapContent();
        mapContent.setTitle("Map Difference");
        createShpOfDiff(diffcol4, store1);
    private static void createShpOfDiff(SimpleFeatureCollection col3, FileDataStore store1) throws IOException {

        String pathname = "C:/Users/neha.vashishth/Documents/GISFiles/sample1/sample1/Diff/diff.shp";
        File file = new File(pathname);
        File newFile = getNewShapeFile(file);
        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
        Map<String, Serializable> params = new HashMap<String, Serializable>();
        params.put("url", newFile.toURI().toURL());
        params.put("create spatial index", Boolean.TRUE);
        final SimpleFeatureType TYPE = createFeatureType();
        ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
        Transaction transaction = new DefaultTransaction("create");
        String typeName = newDataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
        if (featureSource instanceof SimpleFeatureStore) {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;

            try {

            } catch (Exception problem) {

            } finally {
            System.exit(0); // success!
        } else {
            System.out.println(typeName + " does not support read/write access");
    private static SimpleFeatureType createFeatureType() {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system
        builder.add("the_geom", MultiPolygon.class);
        builder.length(15).add("Name", String.class); // <- 15 chars width for name field
        // build the type
        final SimpleFeatureType LOCATION = builder.buildFeatureType();
        return LOCATION;
    private static File getNewShapeFile(File file) {
        String newPath = file.getAbsolutePath();
        JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
        chooser.setDialogTitle("Save shapefile");
        chooser.setSelectedFile(new File(newPath));

        int returnVal = chooser.showSaveDialog(null);

        if (returnVal != JFileDataStoreChooser.APPROVE_OPTION) {
            // the user cancelled the dialog
        File newFile = chooser.getSelectedFile();
        if (newFile.equals(file)) {
            System.out.println("Error: cannot replace " + file);
        return newFile;

    public static SimpleFeatureCollection difference(SimpleFeatureCollection collA, SimpleFeatureCollection collB) {
        SimpleFeatureBuilder builder = new SimpleFeatureBuilder(collA.getSchema());
        List<SimpleFeature> ret = new ArrayList<>();
        try (SimpleFeatureIterator itr = collA.features()) {
          while (itr.hasNext()) {
            SimpleFeature f = itr.next();
            Geometry geom = (Geometry) f.getDefaultGeometry();
            FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
            Filter filter = ff.intersects(ff.property(collB.getSchema().getGeometryDescriptor().getLocalName()),
            SimpleFeatureCollection sub = collB.subCollection(filter);
            if (!sub.isEmpty()) {
                Geometry result = null;
              try (SimpleFeatureIterator itr2 = sub.features()) {

                while (itr2.hasNext()) {
                  SimpleFeature f2 = itr2.next();
                  Geometry geom2 = (Geometry) f2.getDefaultGeometry();
                  if (result == null) {
                    result = geom2;
                  } else {
                    result = result.union(geom2);
              if (result.isValid() && geom.isValid()) {
                // calc difference
                Geometry g = geom.difference(result);
                String geomName = collA.getSchema().getGeometryDescriptor().getLocalName();
                builder.set(geomName, g);
                SimpleFeature fout = builder.buildFeature(null);
              } else {
                if (!result.isValid()) {
                  System.out.println("Invalid result");
                if (!geom.isValid()) {
                  System.out.println("Invalid geom");
            } else {// no intersection
        return DataUtilities.collection(ret);


How can I generate the correct dbf referring to the dbf. .shp's from which I have generated the differenced .shp

Below are the columns in my other two main shapefiles :

osm_id  osm_way_id  name    type    amenity barrier boundary    building    land_area   landuse X   Y   osm_id_2    sport_2 building_u  height  start_date

But my shapefile consisting of differenced FeatureCollection is empty with just "Name".


The output shapefile only contains name because that is what you told it you wanted. Look at createFeatureType you create an output which contains a geometry and a string called name. If you want more attributes in your features then you need to include them in there.

Or if like me you are lazy you can just use the existing schema.

File c = new File("diff-out.shp");
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

Map<String, Serializable> params = new HashMap<>();
params.put("url", URLs.fileToUrl(c));
params.put("create spatial index", Boolean.TRUE);

ShapefileDataStore fdsc = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
SimpleFeatureStore store = (SimpleFeatureStore) fdsc.getFeatureSource();

Will create a new file (or overwrite the existing one) and put all the features in collc in it with all of their attributes.

  • Thanks Ian for your quick response. You make GIS implementation simple. Oct 5 '18 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.