官术网_书友最值得收藏!

Exploring the GeoJSON format

GeoJSON is a format for recording geographic data structures, which includes support of geometric definitions, such as points and polygons. For example, the location of an earthquake's epicenter (point) and the area affected (polygon). Part of the GeoJSON can look as follows:

{
 "type":"Point",
 "coordinates":[122.3818333,45.0686667,12.9]
}
,
"id":"uw61022191"

Note

The previous example is a small excerpt from the feed that reports all earthquakes in the past hour (http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson). Take a moment to look at this feed and get a feel for the type of data this format contains.

To kick off this project, we will create a data-monitoring application that will record information from this feed. As this program will be running over a long period, we will want to add a logging feature to ensure it is running smoothly.

Fetching and recording the data

The main function in bin/main.dart will prompt the data to be downloaded each minute using an instance of the DataMonitor class. There are 1440 minutes in a day and the data files average at around 2k, so 3 megabytes of disk space a day is practical:

main() async {
  setupLogging();

  DataMonitor quakeMon = new DataMonitor();
  Duration updateInterval = new Duration(seconds: 60);

  new Timer.periodic(updateInterval, quakeMon.fetchData);
}

The main function is marked async, which gives you a clue that the implementation will make use of the await feature. The call to setupLogging will be covered in the next section of this chapter.

The implementation of DataMonitor is in lib/quakemonitorfs.dart, which contains the key method fetchData:

  fetchData(Timer timerFetch) async {
    try {
      var outDir = new Directory('data');
      if (!await outDir.exists()) {
        outDir.create();
      }

      log.info("Calling web service...");
      HttpClientRequest req = await geoClient.getUrl(Uri.parse(dataUrl));
      HttpClientResponse resp = await req.close();
      String latestFilePath = path.join('data', latestFilename);
      await resp.pipe(new File(latestFilePath).openWrite());
      String fileContents = await new File(latestFilePath).readAsString();

      var dataset = await JSON.decode(fileContents);

      int newId = int.parse(dataset['metadata']['generated'].toString());

      if (idPreviousFetch != newId) {
        idPreviousFetch = newId;
        var f = new File(path.join('data', '${newId}.txt'));
        await f.writeAsString(dataset.toString());
        log.fine("Saved $newId - ${dataset.toString()}");
      }
    } catch (exception, stacktrace) {
      log.severe("Exception fetching JSON.", exception, stacktrace);
    }
  }

Nearly every other line has an await! The program only has to process information every minute or so, therefore it does not require a responsive structure and a more linear approach is sufficient, though the code is still asynchronous.

The remote resource is processed first and the response closed off. The JSON string returned can be put straight into a file. Once this is completed, the fileContents variable is populated with the data from the file, which is then parsed by the JSON to return an object into the dataset.

The Id of the response is checked so that the same response is not saved twice. Note that the generated Id may be different, while the content is the same. The feed is more of a snapshot than a steady stream.

The data is saved off to the data folder using the id of the fetch as a text (.txt) file. To give some feedback, the id and JSON are written to the log file via the call to qlog.fine.

主站蜘蛛池模板: 昌邑市| 特克斯县| 江门市| 永泰县| 汽车| 中西区| 合山市| 延寿县| 黄大仙区| 新乡县| 杭锦旗| 曲周县| 西宁市| 永吉县| 乳山市| 西城区| 康平县| 曲松县| 肃北| 金坛市| 枣阳市| 金昌市| 南开区| 文安县| 台州市| 孝感市| 神农架林区| 于田县| 连南| 扬中市| 星子县| 仁化县| 灵宝市| 巴彦县| 南岸区| 北流市| 宁南县| 翁源县| 垣曲县| 安新县| 渭南市|