Skip to content

Instantly share code, notes, and snippets.

@stevewillard
Created December 28, 2017 15:16
Show Gist options
  • Save stevewillard/fda58884b7a9131bca189dad13551372 to your computer and use it in GitHub Desktop.
Save stevewillard/fda58884b7a9131bca189dad13551372 to your computer and use it in GitHub Desktop.
shapefile to geojson
const stream = require('stream');
const fs = require('fs');
const unzip = require('unzip-stream');
const Zip2GeoJsonStream = require('./zip2geojson');
const file = process.argv[2];
const readStream = fs
.createReadStream(file)
.pipe(unzip.Parse())
.pipe(new Zip2GeoJsonStream())
.pipe(fs.createWriteStream(file.replace(/\.[^\.]+$/, '.geojson')));
{
"devDependencies": {},
"dependencies": {
"event-stream": "^3.3.4",
"project-geojson": "^1.0.2",
"shapefile": "^0.6.6",
"unzip-stream": "^0.2.1"
}
}
const fs = require('fs');
const path = require('path');
const stream = require('stream');
const es = require('event-stream');
const project = require('project-geojson');
const shapefile = require('shapefile');
const EXTENSIONS = ['.prj', '.shp', '.dbf'];
class Shp2GeoJSONStream extends stream.Readable {
constructor(shp, dbf) {
super({ objectMode: true });
this.source = shapefile.open(shp, dbf);
}
_read() {
this.source.then(source => {
source.read().then(result => {
this.push(result.done ? null : result.value);
});
});
}
}
class Zip2GeoJsonStream extends stream.Transform {
constructor() {
super({ objectMode: true });
this.buffers = {};
}
_transform(entry, e, cb) {
const filename = entry.path;
const extname = path.extname(filename);
if (EXTENSIONS.indexOf(extname) > -1) {
entry.pipe(
es.wait((err, buff) => {
this.buffers[extname] = buff;
cb();
})
);
return;
}
entry.autodrain();
cb();
}
_flush(cb) {
let dataStream = null;
let projStream = es.through();
// handle shp/dbf files
if ('.shp' in this.buffers) {
const shpBuff = this.buffers['.shp'];
const dbfBuff = this.buffers['.dbf'];
dataStream = new Shp2GeoJSONStream(shpBuff, dbfBuff);
}
// handle projection files
if ('.prj' in this.buffers) {
const prjBuff = this.buffers['.prj'];
projStream = project.obj(prjBuff.toString(), 'EPSG:4326');
}
if (!dataStream) {
throw new Error(
'provided zip file does not contain valid shape or vector files'
);
}
// pipe the data to the projection stream and then push each record to the
// next part of the stream using a pass-through stream
dataStream.pipe(projStream);
// .pipe(es.through(record => this.push(record), () => cb()));
cb();
}
}
module.exports = Zip2GeoJsonStream;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment