MATLAB Answers

Can one read one line of string title followed by multiple lines of numeric data like FORTRAN?

30 views (last 30 days)
Kenneth Lamury
Kenneth Lamury on 3 Jul 2016
Edited: dpb on 17 Jul 2016
My test.txt file consist of one line of 80 characters followed by multiple FORTRAN lines that use both integer & floating-point numbers of format I7 or F7.0. Am I restricted to ' ' or ',' delimiters (which would require much rework), or is there a way to read a FORTRAN file?
C2345678901234567890123456789012345678901234567890123456789012345678901234567890
10 3.0 4.0 5.0 7.0 9.0 10.0 15.0 20.0 25.0 xxxxxxxxxx
I plan to write MATLAB R2016a Student programming code using a FORTRAN txt/doc file.

  3 Comments

Kenneth Lamury
Kenneth Lamury on 6 Jul 2016
There are a number of FORTRAN formats I deal with, eg 1) 20A4 for headers, 2) 10F7.0, 3) 10F7.0,I2, 4) 6F7.0,3I3,I2,6A4, 5) 3I7,7F7.0, 6) 10I7, and 7) continuation of values should certain variables exceed 10 field format. ('F' is floating point; 'I' is an integer; and 'A' is an alpha-numeric field.) Should I try to exceed the number of cards read, an 'EOF ' or 'END ' would terminate program. I plan to rewrite a FORTRAN program, with some difficult due to 'GO TO' statements, as a MATLAB program that calls a '.dat' or '.txt' or '.for' file as input. Here is a sample input:
*PROJECT TITLE *----____
10 2.433 241.88 786.65 312.82 312.82 0 7 0 0 0****----****----****----
605.24 747.31839.3325618.8 122.79 34.142 .7688 .49444 0. 0. 1
550.15 668.65339.3325565.5 144.37 34.142 .7688 .49444 0. 0. 2
495.070589.98839.3325512.1 165.96034.142 .7688 .49444 550.761412.839ON GEOM
439.99 511.32339.3325461.8 187.54 31.58 .7688 .49444 0. 0. 4
384.91 432.65839.3325413.5 209.13 31.58 .7688 .49444 0. 0. 5
330.280353.99339.3325365.10 232.50 31.58 .7688 .47083 320.769240.82 IN GEOM
275.64 275.32839.3325316.7 255.94 31.58 .7688 .47083 0. 0. 7
221.04 196.66339.3325275.0 279.38 28.5 .7688 .47083 0. 0. 8
166.43 117.99839.3325240.1 302.82 22.17 .7688 .47083 130.1 312.82 MG GEOM
111.81 39.332539.3325214.1 326.26 10.73 0. .0001 0. 0. 10
.40 .175439.096154.044444.024938.014749.008726.005051.002857.002439EI405 R
.50 .250 .121951.057143.035587.021692.013333.008 .004484.004515GJ405 R
3 4 16.0 3.9961 1 0 9 0 0 0 0KENG
.5 0 0 THRPIT°
1.3240 0.000 0 0 0 0 0 MP THR
0000000000000000000000000000000000000000000000000000000000000000000000VZ THR IAP
-.24360-.23560-.22750-.47400-.42390-.32570-.14540MEA THR IAP
.38200 .38200 .38200 .77420 .79860 .84200 .88720TEA THR IAP
0 0 0 -.99966-.99966-.99966-1.9994-1.9994-1.9994-1.9994VX THR IAP
0000000000000000000000000000000000000000000000000000000000000000000000VY THR IAP
0 0 0 -.04063-.11809-.19555-.32029-.47554-.63111-.78712MZ THR IAP
201.0 * TMI
-9.0 -8.0 -7.0 -6.0 -5.0 -4.0 -2.0 0.0 4.0 6.0 * TAL
8.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 * TAL
.245 .164 .106 .072 .049 .032 .014 .01 .009 .009 M=1.0 TCD
.01 .014 .021 .032 .049 .072 .106 .163 .244 .341 M=1.0 TCD
-126.67-40.141-.24780 206.06 62.339 .38190 .85191 .0 0.0.523689O-NAC.JUMP IAP
*____OUTB'D NAC_____*
-126.67-57.292-.25450 206.06 88.291 .39220 .85191 0 0.0.523689I-NAC.JUMP IAP
*_____INB'D NAC_____*
-97.783 -4.613.000000221.234 10.438.914640.000000 0 0.0.404269* MAINGEAR
*-MAIN GEAR UP LOAD-*
1.0 -8073 .53526-.84557552.590 -8271 .69555-1.0828323.360 1183.9FLT-UP KCR IAP
.03261-.10898136.270
2.0 -8073 .53526-.84557552.590 -8271 .69555-1.0828323.360-3579.0FLT-DN KCR IAP
-.15468 .35382136.270
3.0 -8230 .54673-.87494552.590 -8281 .69639-1.0841323.360-3579.0GRD-DN KCR IAP
-.15468 .35382136.270
0000000
0000000
1 4 4 -1 .910 .810 .730 .702 0 0KC-R ONAC
-17.154-22.425-26.642-28.453 XHEA
4 7 6 -1 .640 .600 .545 .480 .460 .411KC-R INAC
-34.327-38.117-43.329-49.487-51.387-56.025 XHEA
7 9 5 -1 .330 .300 .270 .200 .173 0-135 GEAR
-63.699-64.877-64.510-62.982-61.132 XHEA
9 11 2 1 .120 .090 0 0 0 0-135 SOB
-59.216-56.298 XHEA
3 10 .4 1 1 3 6 MCR,NACLDS
5.01 6.02 6.47 6.56 7.00 6.3 6.7 7.4 7.05 7.45 M0
.0170 .017 .0284 .0120 .0064 .0244 .0072 .0060 .0154 .019 ALPHA
-.0248 -.026 -.0272 -.0269 -.0242 -.0217 -.0203 -.0197 -.0207 -.0223 CM0
.03 .007 .003 -.003 .001 -.005 -.013 -.031 -.075 -.112 DCMDCL
.4 M=.4
5.4362 6.5438 7.0163 7.4000 7.4100 6.8 7.17 7.9505 7.6549 8.1114 M0
.017 .0167 .0281 .0122 .0060 .0235 .0138 .0034 .0148 .018 ALPHA
-.0274 -.0281 -.0293 -.0291 -.0261 -.0235 -.0216 -.0211 -.0224 -.0242 CM0
.0284 .0073 .0039 .0039 .0014 -.0025 -.01 -.0301 -.0768 -.1126 DCMDCL
.55 M=.55
5.65 6.9713 7.4656 7.615 8.6684 7.6 8.45 8.7944 8.1911 8.6294 M0
.0184 .0159 .0275 .0126 .0183 .0245 .0207 .015 .0144 .0190 ALPHA
-.0283 -.0297 -.0306 -.0302 -.0275 -.026 -.0244 -.0223 -.0237 -.0256 CM0
.0314 .0073 .0054 .0091 .0049 -.001 -.0107 -.0276 -.0764 -.1126 DCMDCL
.7 M=.7
6.512 7.421 8.2154 9.2263 8.6588 7.3 7.8 8.4646 8.6729 9.3123 M0
.0288 .0212 .0305 .0092 .0236 .035 .0195 .0187 .0209 .0219 ALPHA
-.0308 -.0328 -.0354 -.0363 -.0321 -.0286 -.0234 -.0228 -.026 -.0277 CM0
.0366 .0176 .0163 .022 .0135 -.001 -.0095 -.025 -.0741 -.1131 DCMDCL
.8 M=.8
7.0820 8.3683 8.6008 8.8377 8.2319 7.5 8.6 9.635 10.050010.6633 M0
.0151 .017 .0336 .0227 .0258 .0355 .0275 .0176 .0174 .0173 ALPHA
-.0374 -.0378 -.0377 -.0375 -.0347 -.0325 -.0272 -.0263 -.0292 -.0311 CM0
.03 .011 .0027 -.0034 .0032 -.002 -.0095 -.0191 -.0741 -.1153 DCMDCL
.85 M=.85
7.8582 9.3157 9.5266 9.3 8.7588 7.95 7.9 8.5366 9.962 11.0504 M0
.0085 .0144 .0311 .0246 .0209 .027 .017 .0093 .0169 .0194 ALPHA
-.0379 -.0338 -.0437 -.0496 -.0431 -.0374 -.029 -.0250 -.03 -.0361 CM0
.0652 .0020 .0324 .0591 .0344 -.0075 -.047 -.0819 -.1574 -.2066 DCMDCL
.9 M=.9
7.540811.042210.1302 7.0963 8.6429 7.632 8.0 8.7013 9.545910.4801 M0
.0 .013 .031 .035 .0176 .0292 .0221 .0127 .0107 .0135 ALPHA
-.0476 -.0410 -.0453 -.0544 -.0398 -.043 -.0305 -.0233 -.0227 -.0274 CM0
.125 -.0126 .0215 .0693 -.0225 -.06 -.092 -.142 -.2049 -.2508 DCMDCL
.95 M=.95
8.5713 7.0532 6.9459 6.6719 6.915 6.9 6.9 7.4086 9.703310.7462 M0
.0193 .0248 .0414 .003 .0073 .0198 .031 .0249 .0097 .0081 ALPHA
-.06 -.0490 -.0526 -.0564 -.0294 -.0384 -.0315 -.0218 -.0138 -.0115 CM0
.0913 .0843 .0814 .0608 -.0858 -.1498 -.1954 -.2034 -.2603 -.3058 DCMDCL
BLANK
-.0014 -.0008 -.0153 -.0187 -.0063 -.0207 -.012 -.0064 -.0052 -.0046 SPOILER
-.0009 .00123 .0014 -.00085-.00438 .0058 .00295 .00297 .0063 .00838 INPUTS
0000000 2ND CONTRO
0000000 SURFACE
.10 -.00200 .0665-.00100 .0292-.00340 .0716-.00140 .0292 0LAOA 1
0 0 0
.40 -.00160 .0647-.00074 .0289-.00362 .0603-.00147 .0395 0LAOA 2
0 0 0
.55 -.00145 .0653-.00070 .0301-.00377 .0669-.00144 .0375 0LAOA 3
0 0 0
.70 -.00150 .0676-.00074 .0305-.00430 .0693-.00149 .0378 0LAOA 4
0 0 0
.75 -.00157 .0682-.00078 .0298-.00460 .0790-.00160 .0358 0LAOA 5
0 0 0
.80 -.00180 .0676-.00086 .0292-.00510 .1040-.00166 .0339 0LAOA 6
0 0 0
.825 -.00195 .0670-.00092 .0290-.00535 .0960-.00171 .0322 0LAOA 7
0 0 0
.85 -.00220 .0665-.00100 .0289-.00565 .0954-.00177 .0299 0LAOA 8
0 0 0
.875 -.00255 .0653-.00106 .0287-.00600 .0877-.00183 .0306 0L0AO 9
0 0 0
.90 -.00300 .0650-.00120 .0285-.00640 .0888-.00189 .0302 0LAOA 10
0 0 0
.925 -.00370 .0642-.00120 .0284-.00670 .0802-.00195 .0292 0LAOA 11
0 0 0
.95 -.00500 .0630-.00135 .0281-.00710 .0698-.00200 .0265 0LAOA 12
0 0 0
BLANK
BLANK
.10 .0096 .00214-.04800 .00480 CFM-BIV6 1
.30 .0096 .00214-.04800 .00480 CFM-BIV6 2
.40 .0068 .00214-.04800 .00480 CFM-BIV6 3
.55 .0007 .00209-.04691 .00383 CFM-BIV6 4
.70 -.0092 .00190-.04590 .00258 CFM-BIV6 5
.80 -.0198 .00230-.04701 .00100 CFM-BIV6 6
.85 -.0145 .00294-.05611 .00437 CFM-BIV6 7
.90 -.0176 .00340-.05900 .00739 CFM-BIV6 8
.95 -.0244 .00270-.03344 .00307 CFM-BIV6 9
BLANK
1 1 2 1
.00144 .00733 .02125-.80198-.78749-.76392-1.8507-1.6503-.933901.14687TSTRRE UP IAP
-.00258-.04264-.12665-.15142-1.1779-2.3085-3.4050-5.6952-8.1845-10.639MSTRRE UP IAP
-.1570 -.5960-1.2910-10.400-11.626-13.203-23.331-25.474-27.490-31.124VSTRRE UP IAP
5642 25468 27628 4219 6.5 62.957FLT RE IAP
7500 250 .4343 1.0000 1.0000 0.0 0.0 735.798395 0
260.0 .267 1.0 0 .3571 0 0 0 0 62.957
28.30 0 1 1 0 0
1 1 0 0 0 0 0 0 0
260.0 .267 1.5 0 .3571 0 0 0 0 62.957
28.35 0 1 1 0 0
1 1 0 0 0 0 0 0 0
-1 GW<0
30000 280 .7760 1.0000 1.0000 0.0 0.0 735.374730 0
260.0 .267 1.0 0 .3626 0 0 0 0 62.957
58.30 0 1 1 0 0
1 1 0 0 0 0 0 0 0
260.0 .267 1.5 0 .3626 0 0 0 0 62.957
58.35 0 1 1 0 0
1 1 0 0 0 0 0 0 0
-1 GW<0
-1 0 VE=0
-1 EI(1)<0
-1 -1
END
NOTE: this write-up may not print an 80 character line!
I do not want to rewrite the input data with a first ' ' on each line, nor rewrite using ' ' or ',' to separate fields. I want to an existing FORTRAN input file without changes.
A MATLAB file like
>> fmt=[repmat('%7f',1,10) '%*s'];
>> fid=fopen('ZLS918_919_KCR_Test_Up_0.dat','r');
>> data=cell2mat(textscan(fid,fmt,'headerlines',1,'collectoutput',1));
>> fmt=[repmat('%4c',1,20) '%*s'];
treats the complete input file as 10F7.0 or 20A4 format.
Now, how does one read a FORTRAN input file into MATLAB? I'm currently using R2016a Student.
Stephen Cobeldick
Stephen Cobeldick on 6 Jul 2016
@Kenneth Lamury: it is a lot better for us if you upload the files rather than printing them as text here. Simply click the paperclip button to upload them.
dpb
dpb on 6 Jul 2016
"how does one read a FORTRAN input file into MATLAB?(*)"
I'd suggest two things--first Matlab is NOT Fortran so don't try to turn a Fortran program literally into Matlab.
In Matlab there isn't strong typing as there is in Fortran so the distinction between integer and real is immaterial; everything numeric is DOUBLE unless you specifically cast it to something else which is also fraught with some "issues". It's not likely there's much if anything in the code that will matter whether integers are specifically stored as integers or not.
Second, it may be far simpler to MEX the Fortran and so while you're calling the function transparently from Matlab, it's still Fortran underneath and doing the job in that fashion the Fortran i/o will still function just as it did.
As far as the comment regarding the example I gave, it works just fine for the description of the input file as given at the time--you've just now added the other information.
If you're adamant about forcing Fortran into Matlab, I think the only way to read the file as it currently is constructed will be to read it on a line-by-line basis as text and then parse the fields; it's too irregular it appears (altho some of that may be the formatting?) to make much use of the expedient of simply separating columns because it isn't all numeric--although looking again (after I reformatted your posting to CODE) perhaps the numeric values are all in 7-column fields; just not all records have same number of elements? If that were to be so, then theoretically you could use the information from the way the Fortran READs are constructed to split up the file into the proper subsections of records that match and either use the File Exchange submission or "roll your own" to parse records. Note that you can call textscan multiple times on the same file handle with a number of repetitions of the format string to read to limit the scope of a given format string to the desired size of the data wanted at any given call, just like READ uses an array size.
But, it'd still be simpler to just mex it imo...or, if it's a standalone program, make an interface routine from Matlab and dispatch it to background execution and retrieve the results.
(*) I'll note that at one time I had built a mex file that took a Fortran FORMAT statement and the associated READ information and used Fortran to do the actual read operation. Unfortunately, when left previous employer, I didn't realize the only copy of it and the source to it resided on a machine there and so it was lost...I had some ambition to rewrite it but unfortunately haven't gotten the round tuit required to have done so. I do agree it's a sorely-missed facility in Matlab; I began making request for the enhancement clear back at Ver 4 20 yr ago. At this point I have little hope it'll ever happen but I still think it's a reasonable enhancement request.
C i/o is simply broken for fixed-width text files w/o delimiters other than blanks/spaces as Walter's example illustrates. Trying to beat that into submission inside Matlab which uses the C RTL is basically pounding one's head into a wall for anything but the most well-behaved (in the C sense) case; it can only be done by brute force in the general case.

Sign in to comment.

Accepted Answer

dpb
dpb on 3 Jul 2016
As long as you don't have fixed-width fields with missing data, no problems with space-delimited files--
>> type ken.dat
C2345678901234567890123456789012345678901234567890123456789012345678901234567890
10 3.0 4.0 5.0 7.0 9.0 10.0 15.0 20.0 25.0 xxxxxxxxxx
>> fmt=[repmat('%f',1,10) '%*s'];
>> fid=fopen('ken.dat','r');
>> data=cell2mat(textscan(fid,fmt,'headerlines',1,'collectoutput',1))
data =
10 3 4 5 7 9 10 15 20 25
>> fid=fclose(fid);
>> whos data
Name Size Bytes Class Attributes
data 1x10 80 double
>>

  3 Comments

Kenneth Lamury
Kenneth Lamury on 16 Jul 2016
Where does MATLAB state the "flags(?)' like "headerlines,1" and "collectoutput,1". I can see the "'%f',1,10" but fail to see the extension beyond "%*s". It seems like they are hidden most of the time, n'est pas? I see that I can merge textscan into cell2mat to speed up (?) the code.
After awhile I understood that MATLAB types the reading based upon the first read field, n'est pas? It accepts "%10f %24s" format but not "%21c %7f", so split the readings, and my input deck, to accommodate MATLAB. (See my recent attachments on my success.)
dpb
dpb on 16 Jul 2016
It's all under the links starting with
doc textscan
You have to read the full content of the documentation; there's a set of links to subsections on the LHS of the page, but when you're trying to learn something it's better to just start reading linearly; there may be something in there you really, really, really need to know and didn't even know to ask! :)
"...I understood that MATLAB types the reading based upon the first read field"
No, that is not so.
textscan returns a numeric vector as a cell array element, of length number of times that field type is matched. Note the type of the returned numeric value matches that of the conversion field. This is easily-enough demonstrated--
>> s='0.032 3 1234567890 1234567890 stuff stuff morestuff';
>> c=textscan(s,'%f %d %n %u %s %c %9c')
c =
[0.0320] [3] [1.2346e+09] [1234567890] {1x1 cell} 's' 'tuff more'
>> cellfun(@class,c,'uni',0)
ans =
'double' 'int32' 'double' 'uint32' 'cell' 'char' 'char'
>> cellfun(@disp,c,'uni',0)
0.0320
3
1.2346e+09
1234567890
'stuff'
s
tuff more
>>
A string specifier '%s' function returns a similar cell vector of strings. OTOH, for each character conversion that includes a field width operator, the return is a K-by-M character array, where M is the field width. The above, too, is in the documentation if you read the details under the section on Output Arguments
There's just funky stuff that happens with C formatted input scanning that's all there is to be said; particularly if you come from a Fortran background where "a character means a character". I don't even pretend to know all the C rules regarding the differences in interpretation between %c and %s and while Matlab documentation covers the high points, it's not the C Standard that defines the underlying behavior, it's a quick 'n fairly dirty users' guide that covers the ordinary cases. Without reading it all again (for the (several millionth time it seems :) ), I know there are some given caveats regarding the difference between the two but I don't recall what they are otomh. One I know of that probably is a "gotcha'!" for your case is that when the field width is given for %c, delimiters, white-space, and end-of-line characters are also counted whereas they're not with %s (although quoted strings are a special case as well).
NB: in the latter regard the return of the '%c' alternates above regarding what actually was read/returned.
"...merge textscan into cell2mat to speed up (?) the code"
On input, no; the conversion from cell array to the double array will actually take a little longer at that point but you'll gain that back going forward for strictly numeric data in array in both ease of addressing (straight paren's indexing vis a vis the curly braces to address cell content) as well as the reduced overhead of not having the indirection of the cell storage needing that dereferencing on each address fetch. In your case, the data you were looking for, while having character data at the ends of the records was all numeric, going ahead and converting to the double array from the git-go was the more efficient route overall, skipping the unwanted comment fields.
In the end, where there were multiple arrays of various sizes as revealed by the later postings, it would have been more simple in getting to the desired end result to use the same form but piecemeal for the individual arrays in the target program since the full file isn't regular in its entirety as the first posting implied. However, while somewhat of a pit(proverbial)a(ppendage), it's certainly possible to manage to read the input from Matlab although from a totally reliable implementation as Walter has pointed out multiple times parsing the actual fixed-width fields is the only sure-fire way to ensure you read every possible valid input file correctly; your way still relies on there being a delimiter between fields to prevent C-style formatted i/o from skipping blanks when counting field widths relying on its definition of what the number of characters in a field width specification means. While I and most others with Fortran background think it's an extremely wrongheaded definition, it is the way C is specified to work.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 3 Jul 2016
You can use field widths in fscanf() or textscan() formats. For example,
sscanf('123456789', '%3f%2d%f')
ans =
123
45
6789

  2 Comments

Walter Roberson
Walter Roberson on 4 Jul 2016
Testing again, I am reminded that the problem with this is that the field counts do not start until the first non-blank character. So for example,
sscanf('123 56789', '%3f%2d%f')
then it will not be " 5" (two characters) parsed as %d when you use the %2d there: instead the blank will be skipped and it will be the "56" that is parsed as %d .
The work-around for this is to split into strings of fixed width and then parse each string with the appropriate non-fixed-width format.
I seem to recall that about 5 or so months ago I gave code that could take care of that, but I do not find that code at the moment. I do, though, find http://www.mathworks.com/matlabcentral/fileexchange/10866-fixed-width-import
Kenneth Lamury
Kenneth Lamury on 16 Jul 2016
The author of the function 'fixed_width_import' still lives in Jordan and no longer supports it as he no longer has a copy of MATLAB. I found it restrictive and not useful, so I too stopped using it.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by