Я разрабатываю новую функцию для своего приложения для Android, чтобы включить резервное копирование и восстановление данных. Я использую файлы XML для резервного копирования данных. Это фрагмент кода, который устанавливает кодировку для выходного файла:
XmlSerializer serializer = Xml.newSerializer();
FileWriter fileWriter = new FileWriter(file, false);
serializer.setOutput(fileWriter);
serializer.startDocument("UTF-8", true);
[... Write data to the file....]
Вот как я пытаюсь импортировать данные из файла XML. Сначала я проверяю правильность кодировки:
XmlPullParser parser = Xml.newPullParser();
FileReader reader = new FileReader(file);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(reader);
if(!"UTF-8".equals(parser.getInputEncoding())) {
throw new IOException("Incorrect file encoding");
}
[... Read data from the file....]
И тут я столкнулся с проблемой. Этот код отлично работает на Android 2.3.3 (как на устройстве, так и на эмуляторе), кодировка правильно определяется как «UTF-8». Но в версиях API11+ (Honeycomb, ICS, JB) выдается исключение. Когда я запускаю это в режиме отладки, я вижу, что parser.getInputEncoding() возвращает null
. Я проверил фактические файлы XML, созданные в версии 2.3.3 и более поздних, и они имеют точно такие же заголовки: <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
. Почему getInputEncoding() возвращает null в API11+?
Дополнительные выводы:
Я обнаружил, что есть способ правильно определить кодировку файлов на устройствах API11+, используя FileInputStream
вместо FileReader
следующим образом:
XmlPullParser parser = Xml.newPullParser();
FileInputStream stream = new FileInputStream(file);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(stream, null);
if(!"UTF-8".equals(parser.getInputEncoding())) {
throw new IOException("Incorrect file encoding");
}
[... Read data from the file....]
В этом случае getInputEncoding() правильно определяет кодировку UTF-8 на эмуляторах и устройствах API11+, но возвращает null на 2.3.3. Итак, на данный момент я могу вставить ответвление в код, чтобы использовать FileReader в API11+ и FileInputStream в pre-API11:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
parser.setInput(stream, null);
} else {
parser.setInput(reader);
}
Но как правильно проверить кодировку с помощью XmlPullParser.getInputEncoding()? Почему разные версии Android ведут себя по-разному в зависимости от того, какую из них я использую: FileInputStream или FileReader?