Listing 1
<cfparam name="attributes.str_Filename" default="">
<cfparam name="attributes.str_LineDelimiter"
default="#chr(13)##chr(10)#">
<cfparam name="attributes.str_TokenDelimiter"
default=",">
<cffunction name="TokenizeLine" returntype="array">
<cfargument name="str_Content" type="string"
required="true">
<cfargument name="str_Delimiter" type="string"
required="true">
<cfset var ar_Tokens = arrayNew(1)>
<cfset var int_CurrPos = 1>
<cfset var int_NextPos = 1>
<cfset var str_Token = "">
<cfscript>
int_NextPos =
REFind("#arguments.str_Delimiter#|$",
arguments.str_Content, int_CurrPos);
while (int_NextPos gt 0)
{
str_Token = mid(arguments.str_Content,
int_CurrPos, int_NextPos - int_CurrPos);
arrayAppend(ar_Tokens, str_Token);
int_CurrPos = int_NextPos +
len(arguments.str_Delimiter);
int_NextPos =
REFind("#arguments.str_Delimiter#|$",
arguments.str_Content, int_CurrPos);
}
// If the line ends with a token, add
// an extra empty element to the array
if (len(arguments.str_Content) gt 0
and mid(arguments.str_Content,
len(arguments.str_Content), 1)
is arguments.str_Delimiter)
{
arrayAppend(ar_Tokens, "");
}
</cfscript>
<cfreturn ar_Tokens>
</cffunction>
<cfif ThisTag.ExecutionMode IS "Start">
<!--- Read the file and inititialize position
and caller variables --->
<cffile action="read"
file="#attributes.str_Filename#"
variable="str_Content">
<cfset int_CurrPos = 1>
<cfset caller.TextParse.str_Line = "">
<cfset caller.TextParse.ar_Tokens = arrayNew(1)>
</cfif>
<!--- Find the next delimiter. The regular
expression "#attributes.str_LineDelimiter#|$"
finds the next line delimiter OR the end of
the string. --->
<cfset int_NextPos =
REFind("#attributes.str_LineDelimiter#|$",
str_Content, int_CurrPos)>
<cfif int_NextPos gt 0>
<!--- Get and return the line and tokens --->
<cfset str_Line = mid(str_Content,
int_CurrPos, int_NextPos - int_CurrPos)>
<cfset caller.TextParse.str_Line = str_Line>
<cfset caller.TextParse.ar_Tokens =
TokenizeLine(str_Line,
attributes.str_TokenDelimiter)>
<!--- reset the current position --->
<cfset int_CurrPos = int_NextPos +
len(attributes.str_LineDelimiter)>
</cfif>
<cfif ThisTag.ExecutionMode IS "End">
<!--- Keep looping as long as we have
content to process --->
<cfif int_NextPos gt 0>
<cfexit method="Loop">
</cfif>
</cfif>