Search code examples
csvtwitterprocessingtwitter4j

How to append results in Processing?


I have implemented the Table() function in order to save the results generated by the application. However, it seems that the Timer function in the application causes the application to write over the existing CSV file each time it runs. Rather than write over the existing CSV file, I would like to append the newest search results to the existing CSV file. Is there a way to do this? Is it easier to append the results if the results are stored in a different format such as JSON?

Timer timer;
import java.util.List;
Table table;
long lastID = Long.MAX_VALUE;

void setup() {

  timer = new Timer(30000);
  timer.start();
  goTwitter();

  table = new Table();
  table.addColumn("id");
  table.addColumn("latitude");
  table.addColumn("longitude");

} 

void draw(){
   if (timer.isFinished()){
     goTwitter();
     timer.start();
   }
}

void goTwitter(){

  ConfigurationBuilder cb = new ConfigurationBuilder();
  cb.setOAuthConsumerKey("");
  cb.setOAuthConsumerSecret("");
  cb.setOAuthAccessToken("");
  cb.setOAuthAccessTokenSecret("");


Twitter twitter = new TwitterFactory(cb.build()).getInstance();
  Query query = new Query("#love"); 
  int numberOfTweets = 300; 
  ArrayList<Status> tweets = new ArrayList<Status>();
  while (tweets.size () < numberOfTweets) {
    if (numberOfTweets - tweets.size() > 100)
      query.setCount(100);
    else 
      query.setCount(numberOfTweets - tweets.size());
      //long lastID = Long.MAX_VALUE;
    try {
      QueryResult result = twitter.search(query);
      tweets.addAll(result.getTweets());
      println("Gathered " + tweets.size() + " tweets");
      for (Status t: tweets) 
        if(t.getId() < lastID) lastID = t.getId();
    }
    catch (TwitterException te) {
      println("Couldn't connect: " + te);
    }; 
    query.setSinceId(lastID);

  }
  for (int i = 0; i < tweets.size(); i++) {
    Status t = (Status) tweets.get(i);

    GeoLocation loc = t.getGeoLocation();

    String user = t.getUser().getScreenName();
    String msg = t.getText();
    String time = "";
    if (loc!=null) {
      Double lat = t.getGeoLocation().getLatitude();
      Double lon = t.getGeoLocation().getLongitude();
      println(i + " USER: " + user + " wrote: " + msg + " located at " + lat + ", " + lon);

    TableRow newRow = table.addRow();
    newRow.setString("id", user);
    newRow.setDouble("latitude", lat);
    newRow.setDouble("longitude", lon);

    saveTable(table, "data2/syria_16500_5.csv");      
    } 
  }
  println("lastID= " + lastID);
}

class Timer {
  int savedTime;
  int totalTime;

  Timer (int tempTotalTime) {
    totalTime = tempTotalTime;
  }

  void start(){
    savedTime = millis();
  }

 boolean isFinished() {
    int passedTime = millis() - savedTime;
    if (passedTime > totalTime){
      return true;
    } else {
      return false;
    }
  }
}

Solution

  • Well, there does not seem to be a direct implementation to append to a table, so you'll have to resort to a hack: load the table in processing, write to it and resave it, sort of like this:

    processing.data.Table table;
    void setup() {
      File f = new File(sketchPath("") + "data2/syria_16500_5.csv");
        println(f.getAbsolutePath());
      if (!f.exists()) {
        table = new processing.data.Table();
        table.addColumn("id");
        table.addColumn("latitude");
        table.addColumn("longitude");
      } 
      else 
        table = loadTable("data2/syria_16500_5.csv", "header, csv");
      TableRow newRow = table.addRow();
      newRow.setString("id", "asad");
      newRow.setDouble("latitude", 234);
      newRow.setDouble("longitude", 2523);
    
      saveTable(table, "data2/syria_16500_5.csv");
    }
    

    The sketch first checks if the file exists. If it does not, it creates a new table, otherwise it loads the old table in with its header. Be warned, this is not particularly safe... If you change your columns (say, in a text editor) and try to run the sketch again you will get an exception.