A diferença efetiva entre seus exemplos é insignificante, desde que nenhuma exceção seja lançada.
Se, no entanto, uma exceção for lançada enquanto estiver na cláusula 'try', o primeiro exemplo a engolirá completamente. O segundo exemplo aumentará a exceção para a próxima etapa da pilha de chamadas, portanto a diferença nos exemplos declarados é que um oculta completamente todas as exceções (primeiro exemplo) e o outro (segundo exemplo) retém as informações de exceção para possível tratamento posterior enquanto ainda executando o conteúdo na cláusula 'finally'.
Se, por exemplo, você colocasse o código na cláusula 'catch' do primeiro exemplo que gerou uma exceção (aquela que foi inicialmente levantada ou uma nova), o código de limpeza do leitor nunca seria executado. Finalmente, executa independentemente do que acontece na cláusula 'catch'.
Portanto, a principal diferença entre 'catch' e 'finalmente' é que o conteúdo do bloco 'finally' (com algumas raras exceções) pode ser considerado com garantia de execução, mesmo diante de uma exceção inesperada, enquanto qualquer código a seguir uma cláusula de 'captura' (mas fora de uma cláusula 'finalmente') não teria essa garantia.
Aliás, Stream e StreamReader implementam IDisposable e podem ser agrupados em um bloco 'using'. Blocos 'Using' são o equivalente semântico de try / finalmente (sem 'catch'); portanto, seu exemplo pode ser expresso de forma mais concisa como:
using (StreamReader reader = new StreamReader("myfile.txt"))
{
int i = 5 / 0;
}
... que fechará e descartará a instância StreamReader quando ela estiver fora do escopo. Espero que isto ajude.