web-dev-qa-db-fra.com

Jeu de caractères tout compris pour éviter "Java.nio.charset.MalformedInputException: Longueur d'entrée = 1"?

Je crée un programme wordcount simple en Java qui lit les fichiers texte d'un répertoire.

Cependant, je continue à avoir l'erreur:

Java.nio.charset.MalformedInputException: Input length = 1

à partir de cette ligne de code:

BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));

Je sais que j’ai probablement compris cela parce que j’utilisais une Charset qui n'incluait pas certains des caractères dans les fichiers texte, dont certains contenaient des caractères d’autres langues. Mais je veux inclure ces personnages.

J'ai appris par la suite dans JavaDocs que la Charset est facultative et utilisée uniquement pour une lecture plus efficace des fichiers. J'ai donc modifié le code en:

BufferedReader reader = Files.newBufferedReader(file);

Mais certains fichiers jettent toujours la MalformedInputException. Je ne sais pas pourquoi.

Je me demandais s'il existait une Charset tout compris qui me permettrait de lire des fichiers texte contenant de nombreux types de caractères?

Merci.

53
Jonathan Lam

Vous voudrez probablement avoir une liste des encodages supportés. Pour chaque fichier, essayez chaque encodage à tour de rôle, en commençant peut-être par UTF-8. Chaque fois que vous attrapez la MalformedInputException, essayez le codage suivant.

51

Création de BufferedReader à partir de Files.newBufferedReader 

Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);

lors de l'exécution de l'application, elle peut générer l'exception suivante:

Java.nio.charset.MalformedInputException: Input length = 1

Mais

new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"),"utf-8"));

fonctionne bien.

La différence est que, le premier utilise l'action par défaut CharsetDecoder.

L'action par défaut pour les erreurs malformed-input et unmappable-character est de signaler les.

tandis que ce dernier utilise l'action REPLACE.

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)
17
Xin Wang

ISO-8859-1 est un jeu de caractères tout compris, dans le sens où il est garanti de ne pas lancer MalformedInputException. C'est donc bon pour le débogage, même si votre entrée n'est pas dans ce jeu de caractères. Alors:-

req.setCharacterEncoding("ISO-8859-1");

J'avais quelques caractères citation double-droite/citation double-gauche dans mon entrée, et US-ASCII et UTF-8 ont jeté MalformedInputException dessus, mais ISO-8859-1 a fonctionné.

11
Tim Cooper

J'ai aussi rencontré cette exception avec un message d'erreur, 

Java.nio.charset.MalformedInputException: Input length = 1
at Java.nio.charset.CoderResult.throwException(Unknown Source)
at Sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at Sun.nio.cs.StreamEncoder.write(Unknown Source)
at Java.io.OutputStreamWriter.write(Unknown Source)
at Java.io.BufferedWriter.flushBuffer(Unknown Source)
at Java.io.BufferedWriter.write(Unknown Source)
at Java.io.Writer.write(Unknown Source)

et a constaté que certains étrange bug se produit lorsque vous essayez d'utiliser

BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath));

écrire un transtypage String "orazg 54" à partir d'un type générique dans une classe. 

//key is of generic type <Key extends Comparable<Key>>
writer.write(item.getKey() + "\t" + item.getValue() + "\n");

Cette chaîne a une longueur de 9 et contient des caractères avec les points de code suivants:

111 114 97 122 103 9 53 52 10.

Cependant, si BufferedWriter dans la classe est remplacé par: 

FileOutputStream outputStream = new FileOutputStream(filePath);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));

il peut écrire avec succès cette chaîne sans exception. De plus, si j’écris la même chaîne, créer à partir des caractères, cela fonctionne toujours.

String string = new String(new char[] {111, 114, 97, 122, 103, 9, 53, 52, 10});
BufferedWriter writer = Files.newBufferedWriter(Paths.get("a.txt"));
writer.write(string);
writer.close();

Auparavant, je n'avais jamais rencontré d'exception lors de l'utilisation du premier BufferedWriter pour écrire des chaînes. BufferedWriter est créé à partir de Java.nio.file.Files.newBufferedWriter (chemin d'accès, options).

3
Tom

ISO_8859_1 a travaillé pour moi! Je lisais un fichier texte avec des valeurs séparées par des virgules

2

J'ai écrit ce qui suit pour imprimer une liste de résultats standard en fonction des jeux de caractères disponibles. Notez qu'il vous indique également quelle ligne échoue à partir d'un numéro de ligne basé sur 0 au cas où vous résolvez le problème.

public static void testCharset(String fileName) {
    SortedMap<String, Charset> charsets = Charset.availableCharsets();
    for (String k : charsets.keySet()) {
        int line = 0;
        boolean success = true;
        try (BufferedReader b = Files.newBufferedReader(Paths.get(fileName),charsets.get(k))) {
            while (b.ready()) {
                b.readLine();
                line++;
            }
        } catch (IOException e) {
            success = false;
            System.out.println(k+" failed on line "+line);
        }
        if (success) 
            System.out.println("*************************  Successs "+k);
    }
}
1

essayez ceci .. j'ai eu le même problème, ci-dessous mise en œuvre a fonctionné pour moi

Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), StandardCharsets.ISO_8859_1);

utilisez ensuite Reader où vous le souhaitez.

foreg:

CsvToBean<anyPojo> csvToBean = null;
    try {
        Reader reader = Files.newBufferedReader(Paths.get(csvFilePath), 
                        StandardCharsets.ISO_8859_1);
        csvToBean = new CsvToBeanBuilder(reader)
                .withType(anyPojo.class)
                .withIgnoreLeadingWhiteSpace(true)
                .withSkipLines(1)
                .build();

    } catch (IOException e) {
        e.printStackTrace();
    }
0
Vin

UTF-8 fonctionne pour moi avec des caractères polonais

0
Adriano

Eh bien, le problème est que Files.newBufferedReader(Path path) est implémenté comme ceci:

public static BufferedReader newBufferedReader(Path path) throws IOException {
    return newBufferedReader(path, StandardCharsets.UTF_8);
}

donc en gros, il est inutile de spécifier UTF-8 à moins que vous ne souhaitiez être descriptif dans votre code. Si vous voulez essayer un jeu de caractères "plus large", vous pouvez essayer avec StandardCharsets.UTF_16, mais vous ne pouvez pas être sûr à 100% d'obtenir tous les caractères possibles de toute façon.

0
francesco foresti