Inform me () when using this script or encorporating it in a library.
Source code of readfile.pro:
;+
; NAME:
; READFILE
; PURPOSE:
; An easier way of reading in columned ascii files where the
; contents of the ascii file can be mixed, i.e. strings, floats,
; doubles, integers, etc. The results are returned as a struct.
; CALLING SEQUENCE:
; READFILE, filename, format=format[, del=del][, skip=skip]
; EXAMPLES:
; result = READFILE('data.txt', FORMAT='D, A, 3D, I'
; KEYWORDS:
; filename = name of the file
; format = format string where each element can be
; (either lower- or uppercase) of A (string), S (string), B
; (byte), I (integer), L (long), F (float), D (double), C
; (complex), DC (complex double), UI (unsigned integer), UL
; (unsigned long) or ULL (unsigned 64 bit long) separated by
; commas. A quantifier in front of it might indicate the number
; of columns resulting in an array in the struct.
; del = delimiter of the columns. Standard a space (32B). For
; tab use 09B
; skip = the same skip as READ_ASCII
; MODIFICATION HISTORY:
; Before 05/06/2007 Written by Eduard Westra
;-
PRO parseFormat, format, fieldcount, fieldtypes, fieldgroups
fmtList = STRTRIM(STRSPLIT(format, ',', /EXTRACT), 2)
nList = N_ELEMENTS(fmtList)
fieldgroups = 0UL
fieldtypes = 0L
fieldcount = 0UL
FOR i = 0, nList-1 DO BEGIN
res = stregex(fmtList[i], '([0-9]*)([ABILFDCSU]*)', /EXTRACT, /SUBEXPR, /FOLD_CASE)
IF res[1] EQ '' THEN no = 1 ELSE no = LONG(res[1])
type = res[2]
fieldcount += no
fieldgroups = [fieldgroups, REPLICATE(i, no)]
CASE type OF
'a': ntype = 7
'A': ntype = 7
's': ntype = 7
'S': ntype = 7
'b': ntype = 1
'B': ntype = 1
'i': ntype = 2
'I': ntype = 2
'l': ntype = 3
'L': ntype = 3
'f': ntype = 4
'F': ntype = 4
'd': ntype = 5
'D': ntype = 5
'c': ntype = 6
'C': ntype = 6
'dc': ntype = 9
'DC': ntype = 9
'ui': ntype = 12
'UI': ntype = 12
'ul': ntype = 13
'UL': ntype = 13
'ull': ntype = 14
'ULL': ntype = 14
ELSE: MESSAGE, "Wrong column type... "+type
ENDCASE
fieldtypes = [fieldtypes, REPLICATE(ntype, no)]
ENDFOR
fieldgroups = fieldgroups[1:*]
fieldtypes = fieldtypes[1:*]
END
;This function only needs one external procedure: strreplace.pro
;If one wants the tab as separator, then del=09B should be sufficient
FUNCTION readfile, input, format=format, del=del, skip=skip
IF N_ELEMENTS(format) EQ 0 THEN MESSAGE, 'You need to specify the format...'
parseFormat, format, fieldcount, fieldtypes, fieldgroups
version = 1.
datastart = 0
IF N_ELEMENTS(del) EQ 0 THEN delimiter = 32B ELSE BEGIN
IF N_ELEMENTS(del) EQ 1 THEN delimiter = BYTE(del) ELSE MESSAGE, 'One needs to provide one delimiter...'
ENDELSE
IF N_ELEMENTS(delimiter) GT 1 THEN MESSAGE, "Invalid delimiter '"+del+"'..."
missingvalue = !VALUES.D_NAN
commentsymbol = '#'
tmp = STRING(INDGEN(fieldcount, /LONG), FORMAT='(I'+STRTRIM(STRING(CEIL(ALOG10(fieldcount))), 2)+')')
STRREPLACE, tmp, ' ', '0'
fieldnames = 'FIELD'+tmp
fieldlocations = INTARR(fieldcount)
template = {$
VERSION:version, $
DATASTART:datastart, $
DELIMITER:delimiter, $
MISSINGVALUE:missingvalue, $
COMMENTSYMBOL:commentsymbol, $
FIELDCOUNT:fieldcount, $
FIELDTYPES:fieldtypes, $
FIELDNAMES:fieldnames, $
FIELDLOCATIONS:fieldlocations, $
FIELDGROUPS:fieldgroups}
RETURN, READ_ASCII(input, template=template, data_start=skip)
END