I prefer UTL_FILE. It is much better to use than spooling using SQLPLUS.

Hope this code helps:

DECLARE
*** utl_file declarations
p_file_name VARCHAR2(20);
p_file_dir VARCHAR2(30);
v_file_handle UTL_FILE.file_type;


BEGIN

p_file_name := 'file_name.dat';
p_file_dir := '/xxx/xxx/utl_file_dir';
v_file_handle := UTL_FILE.fopen (p_file_dir, p_file_name, 'w');

**** Inside the cursor loop you can dump a record to the file by UTL_FILE.put_line (
v_file_handle,variable || ',' || variable);

***** After so many records, you can flush the records to clear memory

UTL_FILE.fflush (v_file_handle_log);

***** After the cursor loops, close the file and you are done.
UTL_FILE.fclose (v_file_handle);

END