[This answer has been significantly revised: the original was unsafe. Thanks to IanH for pointing this out.]
I usually try to avoid formatting the input, which is not a list, when I can afford it. There is already an answer with parsing strings for great generality, but I will offer some suggestions for easier setup.
When you are relaxed, trusting input, for example, when it's just formatting that is a bit complicated (or you are happy to leave it to check the boundaries of your compilers), you can come close to your example with
read(unitfile, *) ii, jj, aa(ii, jj, :)
Alternatively, if the section of the array is more complex than specified directly by the first two columns, it can be an expression or even functions
read(unitfile, *) ii, jj, aa(fi(ii,jj), fj(ii,jj), :fn(ii,jj))
with pure integer function fi(ii,jj) etc. There is even some possibility of having a range check in these functions (for example, returning a partition of size 0).
In a more general case, but remaining in the list, you can use a buffer for real variables
read(unitfile, *) ii, jj, buffer(:) ! Or ... buffer(:fn(ii,jj)) ! Validate ii and jj before attempting to access aa with them aa(.., .., :) = buffer
where the buffer is a suitable size.
Your first approach considered assumes that you have some reasonable idea of ββthe structure of the strings, including length, but when the number of reals is unknown from ii and jj , or when the type (and reading polymorphism isn 't allowed) is unknown, then everything really becomes complicated. In addition, if you are very sensitive to data entry verification or even provide meaningful detailed user feedback with an error, this is not optimal.
Finally, iostat helps.