<!--- We are going to be reading in a file, line by line, so first, let's create a file to read. Define the path to the file we are going to populate. ---> <cfset filePath = expandPath( "./data.txt" ) /> <!--- Delete the file if it exists so that we don't keep populating the same document. ---> <cfif fileExists( filePath )> <cfset fileDelete( filePath ) /> </cfif> <!--- Write some data to the file. ---> <cfloop index="i" from="1" to="10" step="1"> <cffile action="append" file="#filePath#" output="This is line #i# in this file." addnewline="true" /> </cfloop> <!--- ----------------------------------------------------- ---> <!--- ----------------------------------------------------- ---> <!--- If you are not on ColdFusion 8 yet, you can still read files in a line at a time by dipping down into the Java layer. Behind the scenes, ColdFusion is probably using some sort of buffered file reader, so we can do the same explicitly. To create the line number reader, we have to pass it a Reader object, which will a buffered reader for performance reasons. ---> <cfset lineReader = createObject( "java", "java.io.LineNumberReader" ).init( createObject( "java", "java.io.BufferedReader" ).init( createObject( "java", "java.io.FileReader" ).init( javaCast( "string", filePath ) ) ) ) /> <!--- Mark the beginning of the stream so we can reset the position of the reader if we need to. NOTE: You typically won't need this - I just need to do this so I can demonstrate two file reads without creating a new line number reader object. ---> <cfset lineReader.mark( javaCast( "int", 999999 ) ) /> <cfoutput> <!--- Now, let's read the file in a line at a time. As we use the readLine(), it will return a NULL when it gets to the end of the file. When that happens, the variable we are using to read the line will be deleted. ---> <cfset line = lineReader.readLine() /> <!--- Check to make sure we didn't hit the end of the file (which will return NULL, which will delete our variable). ---> <cfloop condition="structKeyExists( variables, 'line' )"> Line: #line#<br /> <!--- Read the next line. ---> <cfset line = lineReader.readLine() /> </cfloop> <br /> <!--- Reset the line number reader to the beginning of input stream for next demo. ---> <cfset lineReader.reset() /> <!--- We can also use the buffered line reader to read in chunks of the file as we did with the CFLoop tag. This is a bit more compliated as we need to read the character data into a character array. ---> <!--- Create a character array of length 50 for out read buffer (we will be reading in a max of 50 characters at any time). NOTE: It doesn't matter what the inital values are at this point since our line number reader will overwrite the data. ---> <cfset buffer = listToArray( repeatString( " ,", 50 ) ) /> <!--- Cast the ColdFusion array (collection) to a typed Java array so that we can use it with the line number reader. ---> <cfset buffer = javaCast( "char[]", buffer ) /> <!--- Read the file data into the buffer and record the number of characters that were read. ---> <cfset charCount = lineReader.read( buffer, javaCast( "int", 0 ), javaCast( "int", arrayLen( buffer ) ) ) /> <!--- Keep looping while characters were read-in. When the line reader hits the end of the file, it will return -1 for the character count. ---> <cfloop condition="(charCount neq -1)"> <!--- Output the chunk. When we do this, we want to convert the buffer to a string and then just take out what's needed. ---> <cfset chunk = mid( arrayToList( buffer, "" ), 1, charCount ) /> 50 Char Chunk: #chunk#<br /> <!--- Read the next chunk of character data from the file into the buffer and record the number of characters that were read. ---> <cfset charCount = lineReader.read( buffer, javaCast( "int", 0 ), javaCast( "int", arrayLen( buffer ) ) ) /> </cfloop> </cfoutput>