Using a java.io.BufferedReader in ColdFusion

So I'm parsing through some response text I get from a CFHTTP I'm firing off, and I figure – the easiest way to parse through this thing, is actually going through it line by line.

There are a variety of ways I could have done this particular endevour, but I figured I build myself up a java.io.BufferedReader that I would pass my String into (via a java.io.StringReader), and I could loop around the thing till my heart was content.

Only issue is this – the only way to tell if the BufferedReader is done, is that it returns null from it's readLine() method.

Doh. CF doesn't handle null values all that well.

So I figure – maybe it will return an empty string? Who knows. I'll set it up like I would in Java and see what will happen.

1st round starts like this:

stringReader = createObject("java", "java.io.StringReader").init(response);
bufferedReader = createObject("java", "java.io.BufferedReader").init(stringReader);
while(Len(line = bufferedReader().getLine()))
{
  //do stuff
}

Which unfortunatley doesn't work too well – as CF won't handle the evaluation inside parenthesis, and thinks the = is my mistake for 'eq'. So we switch over to a do … while loop instead, and get:

do
{
   line = bufferedReader.readLine();
} while(Len(line));

Which works – except it returns back an error: 'line is not defined'.

Which I realise (but fail to understand) is that when Java returned the null value out of the method, it actually removes the line variable from the scope of the method! Woah!

So in the end, this is what I end up with, and it works a treat:

stringReader = createObject("java", "java.io.StringReader").init(response);
bufferedReader = createObject("java", "java.io.BufferedReader").init(stringReader);

do
{
   line = bufferedReader.readLine();
   lineCheck = isDefined("line");
   if(lineCheck)
   {
      //do stuff
   }
} while(lineCheck);

This works perfectly, and now I can use by StringBuffer Happily!

Leave a Comment

Comments

  • PaulH | March 26, 2005

    i think cf is actually dropping that var reference. if you have any java class returning a NULL, that cf var goes south. even if you use javacast this happens:

    z=javacast("null","");
    writeoutput("#z#");

    should throw a variable z is undefined error.

  • jim collins | March 27, 2005

    This is what I did:
    bufferedReader = createObject("java", "java.io.BufferedReader");
    bufferedReader.init(fileReader);
    try {
    do {
    fileAsString = bufferedReader.readLine();
    processLine(fileAsString);
    } while (true);
    } catch (coldfusion.runtime.UndefinedVariableException e) {
    // this indicates end of file, ok to ignore error
    }

  • Mark | March 27, 2005

    Paul – I am using this code inside a CFC, so these variables are var’d. So looks like you have a point there.

    Jim – Using a exception to break a loop for me tends against most best practices I’ve read about. But it does work.

  • Dan Plesse | August 16, 2006

    I better way is not to use do

    Here is another example using while and cfscript.

    <cfscript>

    reader = createObject("java", "java.io.BufferedReader").init(createObject("java", "java.io.FileReader ").init("C:destroyChildAt.txt"));
    line = "";

    while(isDefined("line")){

    writeOutput(line & "<br />");

    line = reader.readLine();

    }
    reader.close();
    </cfscript>

  • Dan Plesse | November 13, 2006

    While doing the readLine() inside any loop solves the EOF and thus null problem you can also use java.io.LineNumberReader which is the lowest Reader on java.io branch.

    <pre>
    <cfloop condition="#IsDefined("variable.line")#">
    #java_io_BufferedReader.getLineNumber()#
    <cfoutput> #len(variable.line)#
    #HTMLEditFormat(variable.line)#</cfoutput><br>
    <cfset variable.line = java_io_BufferedReader.readline()>
    </cfloop>
    </pre>

    make sure you use the close() methods or you causing more problems then solving! Jrun will run crazy and null all objects afterwards.

  • Dan plesse | November 13, 2006

    I had to do that over

    <cfset variable.line = ""> // start with crap

    <cfset variable.line = java_io_LineNumberReader.readline()>
    or read in some good stuff

    <cfloop condition="#IsDefined("variable.line")#"> //look for null

    #java_io_LineNumberReader.getLineNumber()# // for fun

    Look for null here at the last before the next loop
    <cfset variable.line = java_io_LineNumberReader.readline()>

    </cfloop>

    // close close close

    <cfset java_io_LineNumberReader.close()> //for Jrun

    // null null null
    <cfset java_io_LineNumberReader = null> //null out for Jrun