FileWriter (Java)를 사용하여 UTF-8로 파일을 작성 하시겠습니까?


82

그러나 다음 코드가 있지만 외국 문자를 처리하기 위해 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'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();
}

답변:


77

안전한 인코딩 생성자

Java가 인코딩 오류를 올바르게 알리도록하는 것은 까다 롭습니다. 당신은 사용해야 가장 자세한 그리고, 슬프게도, 적어도 사용되는 각각의 네 개의 다른 contructors의를 InputStreamReader하고 OutputStreamWriter인코딩 결함에 적절한 예외를받을 수 있습니다.

파일 I / O의 경우 항상 두 번째 인수 OutputStreamWriterInputStreamReader멋진 인코더 인수에 대해 항상 사용하십시오 .

  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식사 예외 에 대해 시작하지 마십시오 .


1
멋진 대답,하지만 난 그것으로 사소한 버그가 있다고 생각 - InputStreamReader char_input = new InputStreamWriter읽어야가 : InputStreamReader char_input = new InputStreamReader InputStreamReader생성자가 소요 CharsetDecoder하는 없습니다 CharsetEncoder.
Mark Rhodes

그러나 이것이 진짜 문제입니까, UTF-8이 표현할 수없는 것은 무엇이든 인코딩 할 수 있다고 생각했습니다.
Paul Taylor

Streams 먹는 예외에 대해 불평하고 싶다면 인증 된 암호 스트림에 의해 생성 된 경우에도 CipherInputStream제거하는을 시도하십시오 BadPaddingException:(
Maarten Bodewes

코드에서 약간의 오류를 발견했습니다. "InputStreamReader"에 대한 "Charset.forName ("UTF-8 "). newEncoder ()"는 "Charset.forName ("UTF-8 "). newDecoder ()"이어야합니다. 그래서 "인코더"대신 "디코더". 어쨌든이 좋은 답변과 +1에 감사드립니다. :)
codepleb

2
(전체 Java IO 시스템은 항상 엉망이었습니다. Joda Time이 재 작업 한 날짜처럼 완전히 재 작업해야합니다.)
Tuntable

56

도랑 FileWriter그리고 FileReader그들은 당신이 인코딩을 지정하는 것을 허용하지 않습니다 정확히 때문에 쓸모. 대신

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

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


12
Charset.forName("UTF-8").newDecoder()대신에 매우 장황한 인수 (또는 더 멋진 구조)를 사용 "UTF-8"하지 않으면 인코딩 오류에 대한 알림을 제대로받지 못합니다 (읽기 : 예외가 억제되고 신비하게 인코딩 오류가 숨겨집니다).
tchrist 15:53에

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

46

OutputStreamWriter.NET Framework에 대한 작성기 매개 변수로 클래스 를 사용해야 합니다 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 .

시스템 속성을 설정하면 FileWriterUTF-8을 파일의 기본 인코딩으로 사용할 수 있으며 예상 할 수 있습니다 . 이 경우 읽고 쓰는 모든 파일에 적용됩니다.

편집하다

  • 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

또한이 질문은 이미 여기에서 답변 되었습니다 .


그것은 충분하지 않아. 또한 InputStreamReader(InputStream in, CharsetDecoder dec)마지막 인수가입니다 Charset.forName("UTF-8").newDecoder().
tchrist

1
그렇게하면 입력 인코딩 오류가 자동으로 삭제됩니다.
tchrist

인코더가 필요하지 않습니다. 생성자는 입력 / 출력 클래스 모두에서 String, Charset 또는 Encoder를받습니다. 귀하의 의견이 무엇을 의미하는지 잘 모르겠습니다. 자세히 설명해 주시겠습니까?
Edwin Dalorzo 2012 년

3
@edalorzo {In,Out}putStream{Reader,Writer}잘못된 데이터에 대해 네 가지 생성자 를 테스트 해보면 그중 세 개가 인코딩 오류로 인해 발생 해야하는 모든 예외마스킹 하고 네 번째 형식 만이 올바르게 전달한다는 것을 알게 될 것입니다. 그것은 . 나는 내 대답에서 이것을 약간 설명합니다. Charset.forName("UTF-8").newDecoder()
tchrist

1
예, 훨씬 좋습니다. 그것은의 많은 이 출력 온다보다이 나오면 입력 인코딩 오류가 더 자주 (그것은 UTF 양식의 경우 적어도 : 8 비트 출력 인코딩이 항상 잃게 - 잃게 . 유니 코드) 그러나, 당신은 이론적으로 여전히 발생할 수 있습니다 Java는 짝을 이루지 않은 서로 게이트가 메모리의 문자열에 존재할 수 있도록 허용하지만 (그럴 필요 가 있습니다 . 이것은 버그가 아닙니다!), 이에 부합하는 UTF- {8,16,32} 출력 인코더는 출력시이를 생성 할 수 없습니다.
tchrist

9

Java 11부터 다음을 수행 할 수 있습니다.

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

7

Java 7부터는 BufferedWriter 및 BufferedReaders의 문자 인코딩을 쉽게 처리 할 수 ​​있습니다. Writer의 다양한 인스턴스를 만드는 대신 Files 클래스를 사용하여 BufferedWriter를 직접 만들 수 있습니다. 다음을 호출하여 문자 인코딩을 고려하는 BufferedWriter를 간단히 만들 수 있습니다.

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

JavaDoc에서 자세한 내용을 찾을 수 있습니다.


5

중국어 텍스트로 Charset UTF-16을 사용하려고 시도했지만 운이 좋게 작동합니다.

이것이 도움이되기를 바랍니다!

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

UTF-32으로 시도 할 수 있습니다
베어

1

이제 2019 년이되었습니다. Java 11에서는 Charset이 포함 된 생성자가 있습니다.

FileWriter​(String fileName, Charset charset)

안타깝게도 여전히 바이트 버퍼 크기를 수정할 수 없으며 8192로 설정되어 있습니다. ( https://www.baeldung.com/java-filewriter )


0

FileWriter 대신 OutputStream을 사용하여 인코딩 유형 설정

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

-3

내 의견으로는

다음과 같은 종류의 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();

Stack Overflow에 오신 것을 환영합니다! 이 코드 스 니펫은 질문을 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 큰 도움이됩니다. 미래에 독자를 위해 질문에 답하고 있으며 해당 사용자는 코드 제안 이유를 모를 수 있습니다. 또한 설명 주석으로 코드를 복잡하게 만들지 마십시오. 이렇게하면 코드와 설명의 가독성이 감소합니다!
Isiah Meadows
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.