Создать файл в UTF-8 с помощью FileWriter (Java)?

У меня есть следующий код, однако я хочу, чтобы он писал как файл UTF-8 для обработки иностранных символов. Есть ли способ сделать это, есть ли необходимость иметь параметр?

Я бы очень признателен за вашу помощь в этом. Спасибо.

try {
  BufferedReader reader = new BufferedReader(new FileReader("C:/Users/Jess/My Documents/actresses.list"));
  writer = new BufferedWriter(new FileWriter("C:/Users/Jess/My Documents/actressesFormatted.csv"));
  while( (line = reader.readLine()) != null) {
    //If the line starts with a tab then we just want to add a movie
    //using the current actor name.
    if(line.length() == 0)
      continue;
    else if(line.charAt(0) == '\t') {
      readMovieLine2(0, line, surname.toString(), forename.toString());
    } //Else we've reached a new actor
    else {
      readActorName(line);
    }
  }
} catch (IOException e) {
  e.printStackTrace();
}

Ответ 1

Конструкторы безопасного кодирования

Получение Java для правильного уведомления об ошибках кодирования является сложным. Вы должны использовать самый многословный и, увы, наименее используемый из четырех альтернативных конструкторов для каждого из InputStreamReader и OutputStreamWriter, чтобы получить правильное исключение при кодировании глюк.

Для ввода/вывода файлов всегда всегда используйте как второй аргумент как OutputStreamWriter, так и InputStreamReader аргумент fancy encoder:

  Charset.forName("UTF-8").newEncoder()

Существуют и другие, даже более благоприятные возможности, но ни одна из трех более простых возможностей не работает для обработки исключений. Они делают:

 OutputStreamWriter char_output = new OutputStreamWriter(
     new FileOutputStream("some_output.utf8"),
     Charset.forName("UTF-8").newEncoder() 
 );

 InputStreamReader char_input = new InputStreamReader(
     new FileInputStream("some_input.utf8"),
     Charset.forName("UTF-8").newDecoder() 
 );

Что касается работы с

 $ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere

Проблема заключается в том, что она не будет использовать форму аргумента полного кодирования для потоков символов, и поэтому вы снова пропустите проблемы с кодировкой.

Более длинный пример

Вот более длинный пример, который управляет процессом вместо файла, где мы продвигаем два разных потока входных байтов и один выходной поток байтов для всех потоков символов UTF-8 с полной обработкой исключений:

 // this runs a perl script with UTF-8 STD{IN,OUT,ERR} streams
 Process
 slave_process = Runtime.getRuntime().exec("perl -CS script args");

 // fetch his stdin byte stream...
 OutputStream
 __bytes_into_his_stdin  = slave_process.getOutputStream();

 // and make a character stream with exceptions on encoding errors
 OutputStreamWriter
   chars_into_his_stdin  = new OutputStreamWriter(
                             __bytes_into_his_stdin,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newEncoder()
                         );

 // fetch his stdout byte stream...
 InputStream
 __bytes_from_his_stdout = slave_process.getInputStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stdout = new InputStreamReader(
                             __bytes_from_his_stdout,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

// fetch his stderr byte stream...
 InputStream
 __bytes_from_his_stderr = slave_process.getErrorStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stderr = new InputStreamReader(
                             __bytes_from_his_stderr,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

Теперь у вас есть три символьных потока, которые все увеличивают исключение при ошибках кодирования, соответственно называемых chars_into_his_stdin, chars_from_his_stdout и chars_from_his_stderr.

Это немного сложнее, чем то, что вам нужно для вашей проблемы, решение которой я дал в первой половине этого ответа. Ключевым моментом является то, что это единственный способ обнаружить ошибки кодирования.

Просто не заставляйте меня начинать с PrintStream исключений еды.

Ответ 2

Ditch FileWriter и FileReader, которые бесполезны именно потому, что они не позволяют вам указывать кодировку. Вместо этого используйте

new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)

и

new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);

Ответ 3

Вам необходимо использовать класс OutputStreamWriter в качестве параметра записи для вашего BufferedWriter. Он принимает кодировку. Ознакомьтесь с javadocs.

Примерно так:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream("jedis.txt"), "UTF-8"
));

Или вы можете установить текущую системную кодировку с системным свойством file.encoding в UTF-8.

java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...

Вы также можете установить его как системное свойство во время выполнения с System.setProperty(...), если он нужен только для этого конкретного файла, но в таком случае, как я думаю, я бы предпочел OutputStreamWriter.

Установив системное свойство, вы можете использовать FileWriter и ожидать, что оно будет использовать UTF-8 в качестве кодировки по умолчанию для ваших файлов. В этом случае для всех файлов, которые вы читаете и пишете.

EDIT

  • Начиная с API 19, вы можете заменить строку "UTF-8" на StandardCharsets.UTF_8

  • Как указано в комментариях ниже tchrist, если вы намерены обнаруживать ошибки кодирования в своем файле, вам придется использовать подход OutputStreamWriter и использовать конструктор, который получает кодировщик кодировки.

    Что-то вроде

    CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    encoder.onMalformedInput(CodingErrorAction.REPORT);
    encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("jedis.txt"),encoder));
    

    Вы можете выбирать между действиями IGNORE | REPLACE | REPORT

Также на этот вопрос уже был дан ответ здесь.

Ответ 4

С китайским текстом я попытался использовать Charset UTF-16 и, к счастью, он работает.

Надеюсь, это поможет!

PrintWriter out = new PrintWriter( file, "UTF-16" );

Ответ 5

Так как Java 7 есть простой способ обработки кодировки символов BufferedWriter и BufferedReaders. Вы можете создать BufferedWriter напрямую, используя класс Files вместо создания различных экземпляров Writer. Вы можете просто создать BufferedWriter, который рассматривает кодировку символов, вызывая:

Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8);

Об этом можно узнать в JavaDoc:

Ответ 6

Начиная с Java 11 вы можете сделать:

FileWriter fw = new FileWriter("filename.txt", Charset.forName("utf-8"));

Ответ 7

ОК, теперь 2019, и из Java 11 у вас есть конструктор с Charset:

FileWriter​(String fileName, Charset charset)

К сожалению, мы все еще не можем изменить размер байтового буфера, и это установлен на 8192. (https://www.baeldung.com/java-filewriter)

Ответ 8

используйте OutputStream вместо FileWriter для установки типа кодировки

OutputStream outputStream = new FileOutputStream(file); // file is your File object where you want to write you data OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); outputStreamWriter.write(json); // json is your data outputStreamWriter.flush(); outputStreamWriter.close();

Ответ 9

По-моему

Если вы хотите написать follow kind UTF-8. Вам следует создать массив байтов. Затем вы можете сделать следующее: byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();

Затем вы можете записать каждый байт в созданный файл. Пример:

OutputStream f=new FileOutputStream(xmlfile);
    byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();
    for (int i=0;i<by.length;i++){
    byte b=by[i];
    f.write(b);

    }
    f.close();