2012-03-24 3 views
61

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

Я был бы очень признателен за вашу помощь в этом. Благодарю.

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's 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(); 
} 

ответ

42

Вы должны использовать 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

Кроме того, этот вопрос уже ответил here.

+0

Этого недостаточно , Вам также нужен «InputStreamReader (InputStream in, CharsetDecoder dec)», так что последним аргументом является «Charset.forName (« UTF-8 »). NewDecoder()'. – tchrist

+1

Ошибки входного кодирования будут тихо опущены, если вы это сделаете. – tchrist

+0

Кодер не нужен. Конструктор принимает либо строку, либо кодировку, либо кодировщик в обоих классах ввода/вывода. Не уверен, что вы подразумеваете под своим комментарием. Можете ли вы уточнить, пожалуйста? –

41

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

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

и

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

+9

Если вы не используете очень подробный аргумент 'Charset.forName (« UTF-8 »). NewDecoder()' или какой-либо конструктор fancier вместо просто '' UTF-8'', вы не будете правильно уведомлены об ошибках кодирования (читайте: исключения будут подавлены, и они загадочно скроют ошибки кодирования). – tchrist

+2

'new OutputStreamWriter (новый FileOutputStream (файл), StandardCharsets.UTF_8)' – Abdull

64

Safe Кодирование Конструкторы

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

Для файла I/O, всегда убедитесь, что всегда использовать в качестве второго аргумента, как OutputStreamWriter и InputStreamReader фантазии аргумент кодировщик:

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 s есть исключения.

+1

Отличный ответ, но я думаю, что в нем есть небольшая ошибка. 'InputStreamReader char_input = new InputStreamWriter' должен читать:' InputStreamReader char_input = new InputStreamReader' и конструктор 'InputStreamReader' принимает' CharsetDecoder', а не 'CharsetEncoder'. –

+0

Но это настоящая проблема, что не представляется возможным для представления UTF-8, я думал, что он может кодировать что угодно. –

+0

Если вы хотите пожаловаться на исключения потоков Streams, попробуйте 'CipherInputStream', который удаляет' BadPaddingException', даже если они созданы аутентифицированным потоком шифрования :( –

4

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

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

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

На мой взгляд

Если вы хотите написать следовать вид UTF-8 .Вы должны создать байт array.Then, вы можете сделать такие, как: 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(); 
+0

Не могли бы вы добавить некоторые пояснения к этому коду? –

+0

Добро пожаловать в переполнение стека! Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. Также попробуйте не толковать код с пояснительными комментариями, что уменьшает читаемость кода и объяснений! –

0

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

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

Вы можете узнать больше об этом в JavaDoc:

 Смежные вопросы

  • Нет связанных вопросов^_^