- Opening/Closing files:
Files are opened for reading by the command OPENR. Its structure is
OPENR,unit,'filename.dat'. This will open any ASCII file for input. unit
is simply any number from 1 to 99. It does not mean anything except that
IDL needs a unit number to assign to that I/O channel so it knows which file
to read from. Files can be closed by the command CLOSE,unit. Here is an
example of opening two different files for input at the same time, then
closing both of them:
OPENR,1,'file1.dat'
OPENR,2,'file2.dat'
CLOSE,1
CLOSE,2
- Reading from files:
READF,unit,variables will read formatted data from an open file. unit is
whatever number you chose as the unit when you used the OPENR command. In
this way, you can have up to 99 files open at once, and easily specify to IDL
which one you want to read from. Say you have a file that looks like this:
5 9.2
3 4.7
2 6.2and you want to read the data into IDL variables and
print out the product of the two columns. You would write:
openr,1,'file.dat'
for j=0,2 do begin
readf,1,x,y
print,x*y
endfor
close,1
Notice that to read different columns of numbers, you only have
to enter multiple variables separated by commas. If you just put readf,1,x
instead, it would read the first column and ignore the second column every
time through the loop.
- Reading strings:
Just like with READ, you must define a variable to be a string before reading
a string from a file: s=''. When you then read a string: READF,1,s it reads
the rest of the entire line from the file into the string. Using the above
example, if you typed READF,1,s after opening the file, s would have the
value " 5 9.2". If you typed READF,1,x,s next, x would be an integer
with the value 3 and s would have the value " 4.7". Because strings
read the entire line, it is usually recommended that if you are producing a
file with several columns of numbers and one column that contains a string,
the column containing strings should be the last column. For example:
8 5.99 Basketball
12 2.99 Baseball
7 12.99 FootballThis example shows a data file containing
the quantity in stock, price, and name of three items a sporting goods store
would carry. To read this:
openr,1,'goods.dat'
name=''
for j=0,2 do begin
readf,1,quan,price,name
print,name,"quantity: ",quan,"price: $",price
endfor
close,1
- Manually tokenizing strings:
Sometimes though, you'll encounter files that have multiple columns with
strings or the first column is a string. In these cases, you will have to
look at the file in a text editor and decide how to manually tokenize the
string. You may also encounter files that have headings at the top of the
columns that you will want to skip. Example:
Sequence file ident reds luminosity
-------- ----------------- ---------------- ----- ------------------------
1 Q095533p690355rb NGC3031-H270-sp +.000 3.8420107999999999e+01
2 Q120309p444153rb NGC4051-AGNwatc +.002 3.8491015996893545e+01
3 Q115756p552713rb hst_ngc3998 +.004 3.9021241276783940e+01
4 Q042000m545617rb NGC1566-H130-sp +.005 3.9428945651481349e+01
Say you want to pull out the quasar name, redshift, and luminosity:
openr,1,'quasars.dat'
s=''
readf,1,s ;read and throw away top line
readf,1,s ;read and throw away 2nd line
for j=0,3 do begin
readf,1,s
name=strcompress(strmid(s,28,15))
red=strmid(s,45,5)+0.
l=strmid(s,53,22)+0.
print,red,l,name
endfor
close,1
You could alternatively write your own tokenizing routine and
use WHERE, STRPOS, and STRMID to automatically find the columns by looking
at where the whitespace starts and stops, but it is easier for many purposes
to just manually enter the column numbers and use STRMID like in the example.
READS can also be used sometimes, but only when a string contains columns of
only numbers (see READS under ? for more info).
- Using strparse:
This is a situation ideal for strparse. After throwing away the top 2 lines,
read in the third line:
readf,1,s
file=strparse(s,2)
redshift=strparse(s,4)+0.
After the line is read into s, strparse is used to extract the second column,
containing the filename into another string. The fourth column, containing
the redshift, is extracted and converted into a floating point number.
Alternatively you could read the entire file into an array:
s=strarr(4)
readf,1,s
file=strparse(s,2)
redshift=strparse(s,4)+0.
and use strparse on the array to extract arrays containing the filenames and
redshifts.
- Detecting end-of-file and number of lines in a file
The boolean EOF(unit) will let you know when you reach the end of a file. So
if you do not know how many lines are in the file, you can use a routine such
as:
openr,1,'file.dat'
while NOT EOF(1) do begin
readf,1,x,y
print,x,y
endwhile
close,1
This routine will read two columns and print the contents for
every row in the file. There is no command to find out how many lines are
in a file so if you need to detect this in your program, the simplest way
is to read in all the data in the form of strings and count how many lines
there are, then reopen the file an read the data:
openr,1,'file.dat'
s=''
b=0
while NOT EOF(1) do begin
readf,1,s
b=b+1
endwhile
close,1
n=fltarr(b)
openr,1,'file.dat'
for j=0,b-1 do begin
readf,1,x,y
n[j]=y
endfor
close,1
In this example, the 2nd column of the file is now stored in the
array n.
- Reading arrays:
You have to be careful when reading arrays. There are two proper ways to do
it. The first is seen above. READF,1,X,Y then n[j]=Y. You can NOT type
readf,1,x,n[j]. The data must first be read into a scalar then copied to
an array element. The second way is to read an entire file into a single
array. For example, the file
3 9.5
4 7.2
... ... ;23 more lines
can be read by:
n=fltarr(2,25)
f=''
read,'Enter filename: ',f
openr,1,f
readf,1,n
close,1
This will read the entire file with 2 columns and 25 rows of numbers into
the 2 dimensional array n. Note that filenames can be stored in string
variables. Say you have a file with 3 columns of numbers.
The first 5 lines are either headings or junk you want to get rid of. You
then want lines 6-105 in an array and lines 156-255 in a second array:
s=strarr(5)
x=fltarr(3,100)
y=flatrr(3,100)
skip=fltarr(3,50)
openr,1,'file.dat'
readf,1,s ;reads first 5 lines into s
readf,1,x ;reads lines 6-105 into x
readf,1,skip ;reads lines 106-155 into skip
readf,1,y ;reads lines 156-255 into y
close,1