while read drops the last line
Processing text:
while read -r line; do echo "$line"; done < file.txt
If the last line has no trailing newline it is skipped: read returns non-zero at EOF without a newline, so while stops.
while read -r line || [ -n "$line" ]; do ... done < file.txt
Or ensure the file ends with a newline. Many generators omit it, which is exactly when this bites.
Do not drop -r either, or backslashes are interpreted and paths containing \ lose characters.
The piped form has a subshell trap: variables set inside cat file | while read ... are invisible afterwards. Use process substitution or plain redirection.