All-inclusive tekenset om “java.nio.charset.MalformedInputException: Input length = 1” te vermijden?

Ik ben een eenvoudig programma voor het tellen van woorden in Java aan het maken dat de op tekst gebaseerde bestanden van een directory leest.

Ik krijg echter steeds de foutmelding:

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

van deze regel code:

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

Ik weet dat ik dit waarschijnlijk begrijp omdat ik een Charsetheb gebruikt die sommige tekens in de tekstbestanden niet bevatte, waarvan sommige tekens van andere talen bevatten. Maar ik wil die karakters opnemen.

Ik leerde later op de JavaDocsdat de Charsetoptioneel is en alleen wordt gebruikt voor een efficiëntere lezing van de bestanden, dus ik heb de code gewijzigd in:

BufferedReader reader = Files.newBufferedReader(file);

Maar sommige bestanden geven nog steeds de MalformedInputException. Ik weet niet waarom.

Ik vroeg me af of er een allesomvattende Charsetis waarmee ik tekstbestanden met veel verschillende soorten tekens kan lezen?

Bedankt.


Antwoord 1, autoriteit 100%

U wilt waarschijnlijk een lijst met ondersteunde coderingen hebben. Probeer voor elk bestand om de beurt elke codering, misschien beginnend met UTF-8. Elke keer dat u de MalformedInputExceptionopmerkt, probeert u de volgende codering.


Antwoord 2, autoriteit 56%

BufferedReader maken van Files.newBufferedReader

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

wanneer de toepassing wordt uitgevoerd, kan de volgende uitzondering optreden:

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

Maar

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

werkt goed.

Het verschil is dat de eerste de standaardactie van CharsetDecoder gebruikt.

De standaardactie voor fouten met onjuiste invoer en niet-toewijsbare tekens is om ze te rapporteren.

terwijl de laatste de REPLACE-actie gebruikt.

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)

Antwoord 3, autoriteit 36%

ISO-8859-1 is een all-inclusive tekenset, in die zin dat het gegarandeerd geen MalformedInputException genereert. Het is dus goed voor het debuggen, zelfs als uw invoer niet in deze tekenset staat. Dus:-

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

Ik had enkele dubbele-rechts-aanhalingstekens/dubbel-links-aanhalingstekens in mijn invoer, en zowel US-ASCII als UTF-8 gooiden MalformedInputException erop, maar ISO-8859-1 werkte.


Antwoord 4, autoriteit 8%

Ik ben deze uitzondering ook tegengekomen met een foutmelding,

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)

en ontdekte dat er een vreemde bug optreedt bij het proberen te gebruiken

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

om een ​​String “orazg 54” cast van een generiek type in een klasse te schrijven.

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

Deze string heeft een lengte van 9 en bevat tekens met de volgende codepunten:

111
114
97
122
103
9
53
52
10

Als de BufferedWriter in de klas echter wordt vervangen door:

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

het kan deze string zonder uitzonderingen schrijven. Bovendien, als ik dezelfde String maak van de karakters, werkt het nog steeds goed.

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();

Voorheen ben ik nog nooit een Exception tegengekomen bij het gebruik van de eerste BufferedWriter om Strings te schrijven. Het is een vreemde bug die optreedt bij BufferedWriter gemaakt op basis van java.nio.file.Files.newBufferedWriter(pad, opties)


Antwoord 5, autoriteit 6%

probeer dit.. ik had hetzelfde probleem, onderstaande implementatie werkte voor mij

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

gebruik vervolgens Reader waar u maar wilt.

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

Antwoord 6, autoriteit 6%

ISO_8859_1 Werkte voor mij! Ik was een tekstbestand aan het lezen met door komma’s gescheiden waarden


Antwoord 7, autoriteit 4%

Ik heb het volgende geschreven om een ​​lijst met resultaten af ​​te drukken om te standaardiseren op basis van beschikbare tekensets. Merk op dat het u ook vertelt welke regel faalt vanaf een regelnummer op basis van 0 voor het geval u probeert op te lossen welk teken problemen veroorzaakt.

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);
    }
}

Antwoord 8

Nou, het probleem is dat Files.newBufferedReader(Path path)als volgt is geïmplementeerd:

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

dus eigenlijk heeft het geen zin om UTF-8op te geven, tenzij je beschrijvend wilt zijn in je code.
Als je een “bredere” tekenset wilt proberen, kun je het proberen met StandardCharsets.UTF_16, maar je kunt er toch niet 100% zeker van zijn dat je elk mogelijk teken krijgt.


Antwoord 9

UTF-8 werkt voor mij met Poolse karakters


Antwoord 10

je kunt zoiets proberen, of gewoon het onderstaande stuk kopiëren en plakken.

boolean exception = true;
Charset charset = Charset.defaultCharset(); //Try the default one first.        
int index = 0;
while(exception) {
    try {
        lines = Files.readAllLines(f.toPath(),charset);
          for (String line: lines) {
              line= line.trim();
              if(line.contains(keyword))
                  values.add(line);
              }           
        //No exception, just returns
        exception = false; 
    } catch (IOException e) {
        exception = true;
        //Try the next charset
        if(index<Charset.availableCharsets().values().size())
            charset = (Charset) Charset.availableCharsets().values().toArray()[index];
        index ++;
    }
}

Other episodes