If you have the choice, I see several advantages of using SQL*loader with a work table:
- you don't have to have access to the server, other than as an Oracle client, and no changes in init.ora are required
- you can sort the data at will and can deal with "duplicate" rows
- the data is parsed (separated into columns) for you

UTL_FILE comes into its own when the file can not be loaded (easily) as a table: reading a transaction stream where the record format is a function of the transaction code; reading free text (e.g. alrt.log).

The validation rules (written in PL/SQL) would be much the same in either case. In this case, if you use SQL*loader, you might even be able to do it with a collection of SQL statements.

I don't think I would use a trigger . . . .