Опора на кодировку по умолчанию, что я должен использовать и почему?
FindBugs сообщает об ошибке:
Опора на кодировку по умолчанию Нашел вызов метода, который будет выполнять преобразование байта в String (или String to byte) и будет предполагать, что кодировка платформы по умолчанию подходит. Это приведет к изменению поведения приложения между платформами. Используйте альтернативный API и явно укажите имя кодировки или Charset.
Я использовал FileReader как это (всего лишь фрагмент кода):
public ArrayList<String> getValuesFromFile(File file){
String line;
StringTokenizer token;
ArrayList<String> list = null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
list = new ArrayList<String>();
while ((line = br.readLine())!=null){
token = new StringTokenizer(line);
token.nextToken();
list.add(token.nextToken());
...
Чтобы исправить ошибку, мне нужно изменить
br = new BufferedReader(new FileReader(file));
to
br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()));
И когда я использую PrintWriter, произошла ошибка. Так что теперь у меня есть вопрос. Когда я могу (должен) использовать FileReader и PrintWriter, если это не хорошая практика, полагаться на кодировку по умолчанию?
И второй вопрос - правильно использовать Charset.defaultCharset()? Я решил использовать этот метод для автоматического определения кодировки пользовательской ОС.
Ответы
Ответ 1
Если файл находится под управлением вашего приложения, и если вы хотите, чтобы файл был закодирован в кодировке по умолчанию платформы, вы можете использовать кодировку платформы по умолчанию. Указание этого явно упрощает, для вас и будущих сопровождающих, что это ваше намерение. Это было бы разумным по умолчанию для текстового редактора, например, который затем записывал бы файлы, которые мог бы читать любой другой редактор на этой платформе.
Если, с другой стороны, вы хотите убедиться, что любой возможный символ может быть записан в ваш файл, вы должны использовать универсальную кодировку, такую как UTF8.
И если файл поступает из внешнего приложения или должен быть совместим с внешним приложением, тогда вы должны использовать кодировку, которую ожидает это внешнее приложение.
Что вы должны понимать, так это то, что если вы пишете файл, как вы делаете на машине, и читаете его, как вы делаете на другом компьютере, который не имеет одинаковой кодировки по умолчанию, вы не будете обязательно быть в состоянии прочитать то, что вы написали. Используя определенную кодировку, чтобы писать и читать, например UTF8, убедитесь, что файл всегда будет одинаковым, независимо от того, какая платформа используется при записи файла.
Ответ 2
В идеале это должно быть:
try (InputStream in = new FileInputStream(file);
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader)) {
... или:
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
... если файл закодирован как UTF-8.
Практически каждая кодировка, не являющаяся форматом преобразования Unicode, устарела для данных естественного языка. Есть языки, которые вы не можете поддерживать без Юникода.
Ответ 3
Вы должны использовать кодировку по умолчанию всякий раз, когда вы читаете файл, который находится вне вашего приложения, и его можно считать локальным кодированием пользователя, например текстовыми файлами пользователя. Возможно, вы захотите использовать кодировку по умолчанию при записи таких файлов, в зависимости от того, что пользователь будет делать с этим файлом позже.
Вы не должны использовать кодировку по умолчанию для любого другого файла, особенно для файлов приложений.
Если приложение, например, записывает файлы конфигурации в текстовый формат, вы всегда должны указывать кодировку. В общем UTF-8 всегда является хорошим выбором, так как он совместим практически со всеми. Это не может привести к неожиданным сбоям пользователей в других странах.
Это не ограничивается кодировкой символов, но также и форматами даты/времени, цифр или других языков. Если вы, например, используете стандартную кодировку и строки даты и времени по умолчанию на американской машине, попробуйте прочитать этот файл на немецком сервере, вы можете быть удивлены, почему одна половина - тарабарщина, а другая половина месяца смущена или выключена на один час из-за летнего времени.