Если вы знаете, что файл закодирован в Windows 1252, вы можете открыть файл с помощью StreamReader и передать правильную кодировку. То есть:
StreamReader reader = new StreamReader("filename", Encoding.GetEncoding("Windows-1252"), true);
Значение «true» указывает ему установить кодировку на основе меток порядка байтов в начале файла, если они есть. В противном случае он открывается как Windows-1252.
Затем вы можете прочитать файл и, если вы хотите преобразовать в UTF-8, записать в файл, который вы открыли с этой конечной кодировкой.
Краткий ответ на ваш первый вопрос заключается в том, что не существует 100% удовлетворительного способа определения кодировки файла. Если есть метки порядка байтов, вы можете определить, какой это вариант Unicode, но без спецификации вы застряли с помощью эвристики для определения кодировки.
У меня нет хорошего справочника по эвристике. Вы можете искать "как Блокнот определяет набор символов". Я помню, что видел что-то об этом некоторое время назад.
На практике я нашел следующее, чтобы работать для большей части того, что я делаю:
StreamReader reader = new StreamReader("filename", Encoding.Default, true);
Большинство файлов, которые я читаю, - это те, которые я создаю с помощью StreamWriter .NET, и они находятся в UTF-8 с BOM. Другие файлы, которые я получаю, обычно пишутся с помощью какого-либо инструмента, который не понимает Unicode или кодовые страницы, и я просто воспринимаю его как поток байтов, что хорошо работает с Encoding.Default.