Java FileReader 인코딩 문제


130

java.io.FileReader를 사용하여 일부 텍스트 파일을 읽고 문자열로 변환하려고 시도했지만 결과가 잘못 인코딩되어 읽을 수 없다는 것을 알았습니다.

내 환경은 다음과 같습니다.

  • Windows 2003, OS 인코딩 : CP1252

  • 자바 5.0

내 파일은 UTF-8로 인코딩되거나 CP1252로 인코딩되며 일부 (UTF-8로 인코딩 된 파일)에는 중국어 (라틴 문자가 아닌) 문자가 포함될 수 있습니다.

다음 코드를 사용하여 작업을 수행합니다.

   private static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        FileReader reader = new FileReader(filePath);
        //System.out.println(reader.getEncoding());
        BufferedReader reader = new BufferedReader(reader);
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }

위의 코드는 작동하지 않습니다. 텍스트가 UTF-8로 인코딩 된 경우에도 FileReader의 인코딩이 CP1252라는 것을 알았습니다. 그러나 java.io.FileReader의 JavaDoc은 다음과 같이 말합니다.

이 클래스의 생성자는 기본 문자 인코딩과 기본 바이트 버퍼 크기가 적절하다고 가정합니다.

FileReader를 사용하는 경우 직접 문자 인코딩을 설정할 필요가 없다는 의미입니까? 그러나 현재 잘못 인코딩 된 데이터를 얻었습니다. situtaion을 처리하는 올바른 방법은 무엇입니까? 감사.


또한 루프 내에서 String.valueOf ()를 풀고 StringBuffer.append (char [], int, int)를 직접 사용해야합니다. 이것은 char []의 많은 복사를 저장합니다. 또한 StringBuffer를 StringBuilder로 교체하십시오. '아무것도 당신의 질문에 관한 것이 아닙니다.
Joachim Sauer 2016 년

1
나는 그것을 말하기 싫어하지만 붙여 넣은 부분 직후에 JavaDoc을 읽었습니까? "이 값을 직접 지정하려면 FileInputStream에 InputStreamReader를 구성하십시오."라는 부분이 있습니까?
Powerlord

귀하의 의견에 감사드립니다. 실제로 JavaDoc을 읽었지만 확실하지 않은 것은 이러한 값을 직접 지정해야하는지 여부와 "FileInputStream에서 InputStreamReader 구성"으로 전환하는 것입니다.
nybon

예, 파일이 플랫폼 기본 인코딩 이외의 파일임을 알고 있으면 사용할 파일을 InputStreamReader에 알려야합니다.
Alan Moore

답변:


248

예, 읽으려는 파일 의 인코딩을 지정해야합니다 .

예, 읽으려는 파일의 인코딩 을 알고 있어야 합니다.

아니요, 주어진 "일반 텍스트"파일의 인코딩 을 추측 하는 일반적인 방법은 없습니다 .

하나의 인수 생성자는FileReader 항상 플랫폼 기본 인코딩을 사용하는데 이는 일반적 으로 나쁜 생각 입니다.

Java 11 FileReader은 인코딩을 허용하는 생성자를 얻었으므로 : new FileReader(file, charset)new FileReader(fileName, charset).

이전 버전의 Java에서는을 사용해야 합니다.new InputStreamReader(new FileInputStream(pathToFile), <encoding>)


1
InputStream은 = new FileInputStream (파일 이름)입니다. 여기에 내가 러시아어 파일 이름으로 오류 파일을 찾을 수 없습니다 오류가 발생했습니다
Bhanu 샤르마에게

3
InputStreamReader 사용을 제안하는 경우 +1이지만 코드 블록에 링크를 사용하면 코드를 복사하여 붙여 넣기가 어려워집니다 (변경 될 수있는 경우). thx
Ferrybig

1
인코딩에서 "UTF-8"또는 "UTF8"입니까? 에 따르면 인코딩에서 Java SE 참조 하기 때문에, InputStreamReaderA는 java.io클래스, 그것은 "UTF8"것입니까?
NobleUplift

9
@NobleUplift : 가장 안전한 방법은 엉망이 StandardCharsets.UTF_8될 가능성이 없다는 것입니다 ;-) 그러나 네, 문자열 "UTF8"을 사용하면 정확합니다 (두 가지 방법을 모두 수용한다는 것을 기억하지만).
Joachim Sauer

1
@JoachimSauer 사실, 이것은 Byte Order Mark바이트 순서 설정과 함께 .. 의 목적 중 하나입니다 ! :) 따라서 Java의 FileReader가 그러한 BOM이있는 UTF-16을 자동으로 감지 할 수 없다는 것이 이상합니다. 실제로 나는 한 번 UnicodeFileReader정확히 그 일을했습니다. 불행히도 비공개 소스이지만 Google에는 매우 유사한 UnicodeReader 가 있습니다.
Stijn de Witt

79

FileReader Java의 플랫폼 기본 인코딩을 사용합니다.이 인코딩은 실행중인 컴퓨터의 시스템 설정에 따라 다르며 일반적으로 해당 로캘의 사용자에게 가장 인기있는 인코딩입니다.

이 "최상의 추측"이 올바르지 않으면 인코딩을 명시 적으로 지정해야합니다. 불행히도 FileReader이것을 허용하지 않습니다 (API의 주요 감독). 대신 new InputStreamReader(new FileInputStream(filePath), encoding)파일에 대한 메타 데이터에서 인코딩 을 사용 하고 이상적으로 가져와야합니다.


24
"API에 대한 주요 감독"-이 설명에 감사드립니다-왜 내가 만든 생성자를 찾을 수 없는지 궁금했습니다! 건배 John
monojohnny

@Bhanu Sharma : 그것은 다른 수준의 인코딩 문제이며, 파일 이름을 어디에서 가져 왔는지 확인하고, 컴파일러가 사용하는 인코딩을 하드 코딩했는지 확인하십시오.
Michael Borgwardt

1
@BhanuSharma : 파일 이름 인코딩 문제는이 질문과 관련이 없습니다. 기존의 많은“유니 코드 파일 이름이 Java에서 작동하지 않는 이유”질문 중 하나를 참조하십시오. 스포일러 : FileReader와 같은 java.io API는 Windows에서 유니 코드를 지원할 수없는 C 표준 라이브러리 파일 시스템 호출을 사용합니다. 대신 java.nio 사용을 고려하십시오.
bobince

1
" FileReaderJava 플랫폼 기본 인코딩을 사용합니다.이 인코딩은 실행중인 컴퓨터의 시스템 설정에 따라 다르며 일반적으로 해당 로캘의 사용자들 사이에서 가장 인기있는 인코딩입니다." 나는 그렇게 말하지 않을 것입니다. 최소한 Windows. 기묘한 기술적 / 역사적 이유로 인해 JVM은 유니 코드가 Windows에서 '모든 새 애플리케이션'에 권장되는 인코딩 이라는 사실을 무시하고 레거시 앱의 폴백으로 구성된 레거시 인코딩 이 '플랫폼 기본값'인 것처럼 항상 작동 합니다.
Stijn de Witt

6
심지어 Java 앱이 파일 / 스트림 / 리소스를 읽거나 쓸 때마다 인코딩을 명시 적으로 지정 하지 않으면 안정적 으로 작동 할 수 없기 때문에 깨진 것 입니다.
Stijn de Witt


6

Java 7+ doc의 경우 다음을 사용할 수 있습니다.

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

여기에 모든 Charsets doc가 있습니다

예를 들어 파일이 CP1252에있는 경우이 방법을 사용하십시오.

Charset.forName("windows-1252");

IO 및 NIO doc 모두에 대한 Java 인코딩의 다른 표준 이름은 다음과 같습니다.

파일에 정확히 인코딩되어 있는지 모르는 경우 Google 의이 도구와 같은 타사 라이브러리를 사용하면 상당히 깔끔합니다.


1

InputStreamReader를 사용하는 FileInputStream은 FileReader를 직접 사용하는 것보다 낫습니다. 후자는 인코딩 문자 세트를 지정할 수 없기 때문입니다.

다음은 BufferedReader, FileInputStream 및 InputStreamReader를 함께 사용하여 파일에서 행을 읽을 수있는 예제입니다.

List<String> words = new ArrayList<>();
List<String> meanings = new ArrayList<>();
public void readAll( ) throws IOException{
    String fileName = "College_Grade4.txt";
    String charset = "UTF-8";
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream(fileName), charset)); 

    String line; 
    while ((line = reader.readLine()) != null) { 
        line = line.trim();
        if( line.length() == 0 ) continue;
        int idx = line.indexOf("\t");
        words.add( line.substring(0, idx ));
        meanings.add( line.substring(idx+1));
    } 
    reader.close();
}

0

키릴 자모와 같은 라틴 언어의 다른 경우 다음과 같이 사용할 수 있습니다.

FileReader fr = new FileReader("src/text.txt", StandardCharsets.UTF_8);

.txt파일이 UTF-8(기본이 아닌 ANSI) 형식 으로 저장되어 있는지 확인하십시오 . 건배!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.