ColdFusion, AJAX and web...
<cfscript>
variables.iNrTimesToLoop = url.nr;
variables.sStringToConcat = "The quick brown fox jumped over the fence: ";
variables.sFileName = "#getcurrenttemplatepath()#_test_#gettickcount()#.txt";
start = gettickcount();
</cfscript>
<cfset variables.sstring = "">
<cfoutput>
<cfsavecontent variable="variables.sString">
<cfloop from="1" to="#variables.iNrTimesToLoop#" index="variables.x">
#variables.sStringToConcat##variables.x##chr(13)##chr(10)#
</cfloop>
</cfsavecontent>
</cfoutput>
<cffile action="append" file="#variables.sFileName#" output="#variables.sString#">
<cfscript>
end = gettickcount();
total = end-start;
</cfscript>
<cfoutput>
Total time: #total#ms
</cfoutput>
Java StringBuffer class
oStringBuffer = CreateObject("java",
"java.lang.StringBuffer").init(JavaCast("int",initSize));
// Append a string
oStringBuffer.append("A string");
// Get string back from buffer
sString = oStringBuffer.toString();
Java BufferedWriter class
oFileWriter = CreateObject("java",
"java.io.FileWriter").init("filename",JavaCast("boolean","true"));
oBufferedWriter = CreateObject("java",
"java.io.BufferedWriter").init(oFileWriter);
// Write a string to buffer
oBufferedWriter.write("A string");
Can you post the CFML code? Or email it to me directly (mnimer@macromedia.com). Thanks!
I ran into this problem a few years back and it has to do with the way Cold Fusion writes variables. Specifically, it looks to me like it doesn't concatenate so much as it rewrites the old variable plus the new portion to the new variable. So the longer the string gets, the longer it takes to concatenate it.
This can be confirmed by using cfflush in conjuntction with writing out a "." between every loop interation. You will see that the process slows down over time. The way I found around this is to concatenate a temp variable in each interation, and concatenate to the master variable at the end of each loop. That is if you don't want to bother using Java. It sounds like your solution works for you.
I have written a udf called QueryToCSV2 to show the same concept. You can get this udf from cflib.org
http://cflib.org/udf.cfm?ID=1197
has anyone tested this against concantenation in the DB using good old SQL?
By Darryl Lyons, at 7/06/2005 10:31:00 pm
Qasim, Nice UDF. I initialised our CSV generation component with a writer component -- which could either be a StringBuffer or a BufferedWriter class.
By Darryl Lyons, at 7/06/2005 10:32:00 pm
Mike, I'll try to get the full code examples online soon.
By Darryl Lyons, at 7/07/2005 08:09:00 pm
I've added a CFML code example -- its the test I used originally for the CFSAVECONTENT method.
This is a problem that I have struggled with for a long time. I have found that using cffile with action="append" is the best method. After implementing your method by using the BufferedReader class, it seems to me that the two methods are doing roughly the same thing--appending small strings to the end of a file, instead of appending small strings into one large string and writing it to a file. However, even with these two methods I find that the process is using an excessive amount of memory (300mb for a query of 50,000 records). Am I doing something wrong? Is there a way to reuse one chunk of memory to process all of the small strings individually? Right now a new string object is created for every string that is appended to the file. I have heard that you can rewrite the toString() method on the StringBuffer class so that it won't create a new string object, but I don't know how to do it and I imagine it would make my CF code much less portable. I would love any help on this one!!!
By Darryl Lyons, at 7/14/2005 06:37:00 pm
Using the BufferedWriter class is not the same as CFFILE action=APPEND. ColdFusion is essentially opening the file every time (to my knowledge), whereas BufferedWriter writes to a stream.
The best way to achieve what you want is to use the Java.io.BufferedWriter class directly instead of your string concatenation. This way the string is written to the Buffer up until 8094 characters, and then is written to the file. I've found this method uses far less memory than regular string concatenation.
You can email me at darryllyons at fastmail.com.au if you want me to send you a code sample (or I can put up a more detailed post?)
With the move to CFMX, string concatenation seemed to get a bit slower--very much slower on large strings. I have found an easy workaround that performs well. Instead of concatenating a string, perform an ArrayAppend(someArray,"someString" ) function inside your loop. Then when you are ready to output the data or write to a file, use the ArrayToList(someArray,"#chr(13)##chr(10)#" ) function. In a test I performed, the new ArrayAppend approach took 93 milliseconds and the old took 86657 milliseconds. Can Java do better than that? The test loop was 10000 iterations and the total size of the string was 1211Kb. ColdFusion seems to work with arrays much more efficiently than strings.
By Darryl Lyons, at 8/25/2005 06:22:00 pm
Greg,
I'll have to look into that one -- good find.
Darryl,
I have a need to process large files as well, and I am trying to adapt your java bufferedWriter methodology, but I am not proficient in java at all. Could you post or send me the complete source that utilizes the java classes? I see and understand the CF example fine, but don't quite know how to incorporate the java into your CF example. Thanks a Lot!
bjk@glengrp.com
By 123, at 8/30/2010 01:30:00 pm
http://www.submitwww.com/user/view/voted/login/hardysed123
http://www.submitwww.com/user/view/voted/login/hermes123
http://www.surfurls.com/user.php?login=freeboots&view=history
http://www.taagz.com/user.php?login=123mbt&view=history
http://www.taagz.com/user.php?login=bootpoint&view=history
http://www.taagz.com/user.php?login=breilting321&view=history
http://www.taagz.com/user.php?login=Chanel123&view=history
http://www.taagz.com/user.php?login=Chanel321&view=history
http://www.taagz.com/user.php?login=coach123&view=history
http://www.taagz.com/user.php?login=coach321&view=history