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

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.

主站蜘蛛池模板: 开封市| 桦南县| 成安县| 澄城县| 竹北市| 通化市| 南漳县| 蓝山县| 沙坪坝区| 奉贤区| 陆河县| 建始县| 远安县| 淮安市| 黑龙江省| 临湘市| 固镇县| 南城县| 江永县| 孙吴县| 香河县| 湟源县| 巴中市| 成都市| 文成县| 满洲里市| 牡丹江市| 互助| 甘泉县| 舞阳县| 迁西县| 焦作市| 唐山市| 郓城县| 新密市| 新巴尔虎右旗| 松桃| 灵宝市| 神木县| 化隆| 广饶县|