We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › ics to cvs - silly problem
Page Index Toggle Pages: 1
ics to cvs - silly problem (Read 521 times)
ics to cvs - silly problem
Feb 11th, 2009, 11:58am
 
Hi everyone, I'm working through an idea to make a translator to go from an ics file (Google calendar) so i can import it into excel. (don't ask, it's scary to try something new around here...)

Anyways, I'm following along in the File2 example and I thought i had everything 100% but now I'm getting an arrayoutofbounds error. Any help would be greatly appreciated.


Thanks
Jon

Quote:
/*
ical file to csv for excel import

//read the lines in, if it's not BEGIN:VEVENT, then skip, if it is, dump+1,+12 i
nto array. continue until finshed. 

  

*/

//------------------------------------------------------------------------------
-----------


Event[] events;
String[] lines;
int positionCount = 0;
String file = "file.ics";
String test = "BEGIN:VEVENT";
int zuluoffset = -8;
int temp;

//------------------------------------------------------------------------------
-----------

void setup(){
  size(200, 200);
  fill(255);
  noLoop();
  
  lines = loadStrings(file);
  events = new Event[lines.length];

  println("how many lines pulled from file.ics? " + lines.length);  
  
    for (int i = 0; i < lines.length; i++) {
            
      if (lines[i].equals(test)){
        String[] pieces = splitTokens(lines[i]);  
        trim(lines[i]);
        //println("Event   " + lines[i]);  
        println("Start   " + lines[i+1]);
        
        println("End     " + lines[i+2]);  
        //println("Pieces  " + lines[i]);  
        //println("Pieces  " + lines[i]);  
        
        
//getting an outofbounds here, not sure why. 
        events[positionCount] = new Event(pieces);
        positionCount++;
      }
    } 
  
    
}


//------------------------------------------------------------------------------
-----------


void draw(){
  background(0);
  
}

//------------------------------------------------------------------------------
-----------


class Event {
  //BEGIN_VEVENT;
  String DTSTART;         // =         "    :20090209T060000Z";
  String DTEND;           // =           "    :20090209T070000Z";
  String DTSTAMP;         //:20090211T062416Z
  String UID;             //:dl2kvglc7ofn6sukr02dec3qfo@google.com
  String CLASS;           //:PRIVATE
  String CREATED;         //:20090211T060131Z
  String DESCRIPTION;     //:
  String LAST_MODIFIED;   //:20090211T060131Z
  String LOCATION;        //:
  String SEQUENCE;        //:0
  String STATUS;          //:CONFIRMED
  String SUMMARY;         //:
  String TRANSP;          //:OPAQUE
  //END_VEVENT;
 
 public Event(String[] pieces){
    DTSTART = pieces[0];
    DTEND  = pieces[1]; 
    DTSTAMP = pieces[2];
    UID = pieces[3];
    CLASS = pieces[4];
    CREATED = pieces[5];
    DESCRIPTION = pieces[6];
    LAST_MODIFIED = pieces[7];
    LOCATION = pieces[8];
    SEQUENCE = pieces[9];
    STATUS = pieces[10];
    SUMMARY = pieces[11];
    TRANSP = pieces[12];
  }
}

//------------------------------------------------------------------------------
-----------


Re: ics to cvs - silly problem
Reply #1 - Feb 11th, 2009, 12:00pm
 
here is an example ics file

Quote:
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:5 Day Week
X-WR-TIMEZONE:Asia/Macau
X-WR-CALDESC:
BEGIN:VEVENT
DTSTART:20090209T060000Z
DTEND:20090209T070000Z
DTSTAMP:20090211T062416Z
UID:dl2kvglc7ofn6sukr02dec3qfo@google.com
CLASS:PRIVATE
CREATED:20090211T060131Z
DESCRIPTION:
LAST-MODIFIED:20090211T060131Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART:20090208T160000Z
DTEND:20090208T170000Z
DTSTAMP:20090211T062416Z
UID:loqct3tlu6jn70lqstll1e44is@google.com
CLASS:PRIVATE
CREATED:20090211T060106Z
DESCRIPTION:
LAST-MODIFIED:20090211T060106Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

Re: ics to cvs - silly problem
Reply #2 - Feb 11th, 2009, 1:47pm
 
For the record, ICS files are not specific to Google Calendar. For example, Lightening, the calendar extension of Thunderbird, uses them too.

Your code is incorrect:
- loadStrings() returns as many lines as there are in the file. OK.
- Later you init events array with this number of lines. I think that's incorrect, it should be the number of events, so probably the number of BEGIN:VEVENT lines in the file.
- Then you use splitTokens() to split the line with the VEVENT tag. Since it splits by default on whitespace, it will split nothing! And pieces won't hold the information you expect in the Event constructor.

Without making an insightful design, I would do as follow:
- An Event constructor that just set empty string on all fields.
- A method addField() getting a line: it split() on ":", and check the first part to assign to right field the second part.
- On BEGIN:VEVENT line, create a new Event.
- On next lines, if not END:VEVENT, call addField with the line.
- On END:VEVENT, add the finished Event to an ArrayList (extensible freely, since we don't know the final number of events).

An alternative to the many fields is to use a HashMap: use the tag as key, the value as... value. Put the tag names in an array, to be used to pull items from the HashMap and to be used as CSV header. When outputting the CSV line, if get(tagName) returns null, just add an empty string.
Re: ics to cvs - silly problem
Reply #3 - Feb 11th, 2009, 6:08pm
 
Thanks for the reply, i guess my coding skills need some work. I'm interested in the HASH map idea, could you give me some more info about that. I've also second thought the idea of needing to parse it then store it, could i parse then write straight to a file?

thanks
Re: ics to cvs - silly problem
Reply #4 - Feb 12th, 2009, 2:02pm
 
Lot's of cleanup, and fixing. but now i have a new problem- i'm working through an example and trying to apply it. i can't get this to work.

public static List<Employee> getEmployees() {

http://lkamal.blogspot.com/2008/07/java-sorting-comparator-vs-comparable.html


thanks
Jon
Quote:
//------------------------------------------------------------------------------
-----------

class Eventdata {
    String dateStart;
    String timeStart;
    String dateEnd;
    String timeEnd;
    String description;
    String summary;
   
 
   Eventdata(String[] pieces){
      dateStart   = pieces[0];
      timeStart   = pieces[1];
      dateEnd     = pieces[2];
      timeEnd     = pieces[3];
      description = pieces[4];
      summary     = pieces[5];
    }

  //do i need to implement anything here, to keep encapsuation?

}

//------------------------------------------------------------------------------
-----------



//this is broken, I can't get past the return datatype for the method... i'm not
 sure where the problem is. 


class Util{
  
   public List<Eventdata> getEvents(){
    
     List<Eventdata> col = new ArrayList<Eventdata>();
       
       int alength = getLength(Eventdata);
       
       for (int i = 0; i<= alength; i++){
         col.add(new Eventdata[i]);
       }
       
       return col;
     
 
  }
}

Re: ics to cvs - silly problem
Reply #5 - Feb 12th, 2009, 2:33pm
 
It should work if you put these classes in .java files: Processing doesn't support yet the <ClassName> syntax.

And yes, you probably should put the parsing code in the Eventdata class.

HashMap example: no time right now, will try and come back later, if I recall... :-P
But I am not sure it is well suited anyway, your reduced Eventdata class looks good.
Re: ics to cvs - silly problem
Reply #6 - Feb 12th, 2009, 2:36pm
 
typed lists (List<Employee>) aren't supported by processing, the ide parser doesn't handle java 1.5 syntax yet.

just get rid of the type and cast the elements when you use them.

(curses.........)
Re: ics to cvs - silly problem
Reply #7 - Feb 12th, 2009, 6:23pm
 
so no typed lists, okay no problem, thanks for the hint- I don't think I would have found that one easily. So if I'm following along- an ArrayList might be the way to go. - what are my options for sorting? Although, the dateStart field is what I'm after.

As for moving the parsing code- just pass the "String[] lines" into the class method then go from there to keep it out of setup()?  

thanks for the help, and please if I'm misusing terms, let me know- it will help me find solutions to the inevitable future problems.

Jon

Re: ics to cvs - silly problem
Reply #8 - Feb 12th, 2009, 6:57pm
 
OK, here is a quick hack. No sorting yet, there is a thread in this forum where we discuss advantages of comparable and comparator...

Code:
//==== Test.pde

Events events;
String[] lines;
int positionCount = 0;
String file = "events.ics";

void setup()
{
 size(200, 200);
 fill(255);
 noLoop();

 lines = loadStrings(file);
 events = new Events(lines);

 println("How many events pulled from " + file + "? " + events.GetEventNb());

 for (int i = 0; i < events.GetEventNb(); i++)
 {
   EventData e = events.GetEvent(i);
   println(i + " > " + e);
 }
}


//=== EventData.java

class EventData
{
  String dateStart;
  String timeStart;
  String dateEnd;
  String timeEnd;
  String description;
  String summary;

  EventData()
  {

  }

  void ParseLine(String line)
  {
     String[] parts = line.split(":");
     String tag = parts[0];
     if (tag.equals("DTSTART"))
     {
        String[] d = parts[1].split("T");
        dateStart = d[0];
        timeStart = d[1];
     }
     else if (tag.equals("DTEND"))
     {
        String[] d = parts[1].split("T");
        dateEnd = d[0];
        timeEnd = d[1];
     }
     else if (tag.equals("DESCRIPTION"))
     {
        description = parts[1];
     }
     else if (tag.equals("SUMMARY"))
     {
        summary = parts[1];
     }
  }

  @Override
  public String toString()
  {
     return dateStart + " " + timeStart + " to " + dateEnd + " " + timeEnd +
           " > " + description + " (" + summary + ")";
  }
}


//=== Events.java

import java.util.ArrayList;

class Events
{
  static final String endTag = "END:VEVENT";

  private ArrayList<EventData> events;
  private String icsLines;

  Events(String[] lines)
  {
     events = new ArrayList<EventData>();
     EventData event = new EventData();
     for (int i = 0; i < lines.length; i++)
     {
        if (lines[i].equals(endTag))
        {
           events.add(event);
           event = new EventData();
        }
        else
        {
           event.ParseLine(lines[i]);
        }
     }
  }

  int GetEventNb()
  {
     return events.size();
  }

  EventData GetEvent(int i)
  {
     return events.get(i);
  }
}
Re: ics to cvs - silly problem
Reply #9 - Feb 13th, 2009, 11:07am
 
still trucking through this... thanks for the code, i'm going line-by-line to understand it.

are you using java 1.5 syntax? - the < > is causing problems... to get around this, would i dump it into the non-typed list then when i pull it out, cast it?  

like this from the ArrayList example?
Ball ball = (Ball) balls.get(i);

what's the "static final" for when you declared the "String endTag = "END:VEVENT";"   (related to a constant, wiki wasn't much help)

and "private" in "private String icsLines; " is to limit the scope of the variable?

thanks
jon

Re: ics to cvs - silly problem
Reply #10 - Feb 13th, 2009, 12:54pm
 
jmytyk wrote on Feb 13th, 2009, 11:07am:
are you using java 1.5 syntax - the < > is causing problems...

No: look at the file names I gave (there are three files, I should have been clearer), the Java 1.5 syntax is fine in .java files, so I get advantage of it... Smiley

Quote:
what's the "static final" for when you declared the "String endTag = "END:VEVENT";"   (related to a constant, wiki wasn't much help)

static: all instances of this class will share this variable. No duplication, no waste, marginally faster I think.
final: variable content cannot be changed (nor overridden), so yes, that's a constant. I should have named it END_TAG to follow a common convention.

Quote:
and "private" in "private String icsLines; " is to limit the scope of the variable

Exactly, only this class can use/see this variable. It shows it is "internal, private stuff", for their eyes only.
Page Index Toggle Pages: 1