The while loop is much better. The for loop you've done is a bad programming habit sometimes called useless use of backticks -- a waste of memory, processes, and a weak link in your program. Every byte in that file gets read and written an extra time by a completely useless cat, then crammed all at once into one enormous shell variable before it can even start to use the data. Iif it'll fit, that is -- there are limits to the size of a shell variable, system-dependent, which can be quite small. If it doesn't fit, it might truncate it, or refuse to work at all with an error message about too many arguments.
The while loop reads once instead of twice, writes once instead of twice, doesn't need to store the entire file in memory, and will work with any size of file.
Not only UUOC, but that will not work in most shells as the read command is executed in a subshell and $i will not be available anywhere else in the script.