Tworzę prosty program do liczenia słów w Javie, który czyta pliki tekstowe katalogu.
Jednak ciągle otrzymuję błąd:
java.nio.charset.MalformedInputException: Input length = 1
z tego wiersza kodu:
BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));
Wiem, że prawdopodobnie to rozumiem, ponieważ użyłem Charset
znaku, który nie zawierał niektórych znaków w plikach tekstowych, z których niektóre zawierały znaki innych języków. Ale chcę uwzględnić te postacie.
Później dowiedziałem się w JavaDocs, że Charset
jest opcjonalny i używany tylko do bardziej wydajnego odczytu plików, więc zmieniłem kod na:
BufferedReader reader = Files.newBufferedReader(file);
Ale niektóre pliki nadal wyrzucają MalformedInputException
. Nie wiem dlaczego.
Zastanawiałem się, czy istnieje all-inclusive Charset
, który pozwoli mi czytać pliki tekstowe z wieloma różnymi typami znaków ?
Dzięki.
źródło
ISO-8859-1
i działa dobrze. Myślę, że to dla europejskich postaci, co jest w porządku. Nadal nie wiem, dlaczegoUTF-16
nie działa.ISO-8859-1
, to nie jestUTF-16
. Te kodowania są zupełnie inne. Plik nie może być jednym i drugim.Tworzenie BufferedReader z Files.newBufferedReader
Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);
podczas uruchamiania aplikacji może zgłosić następujący wyjątek:
java.nio.charset.MalformedInputException: Input length = 1
Ale
new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"),"utf-8"));
działa dobrze.
Różnica polega na tym, że ta pierwsza używa domyślnej akcji CharsetDecoder.
podczas gdy ta ostatnia używa akcji REPLACE.
źródło
ISO-8859-1 to kompletny zestaw znaków, w tym sensie, że gwarantuje, że nie zgłosi wyjątku MalformedInputException. Jest więc dobry do debugowania, nawet jeśli twoje dane wejściowe nie są w tym zestawie znaków. Więc:-
req.setCharacterEncoding("ISO-8859-1");
Miałem kilka znaków podwójnego cudzysłowu z prawej strony / podwójnego cudzysłowu z lewej strony w danych wejściowych i zarówno US-ASCII, jak i UTF-8 rzuciły na nie MalformedInputException, ale ISO-8859-1 działało.
źródło
Napotkałem również ten wyjątek z komunikatem o błędzie,
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)
i odkryłem, że podczas próby użycia pojawia się jakiś dziwny błąd
napisać rzutowanie typu String "orazg 54" z typu ogólnego w klasie.
//key is of generic type <Key extends Comparable<Key>> writer.write(item.getKey() + "\t" + item.getValue() + "\n");
Ten łańcuch ma długość 9 i zawiera znaki z następującymi punktami kodowymi:
111 114 97 122 103 9 53 52 10
Jeśli jednak BufferedWriter w klasie zostanie zastąpiony przez:
FileOutputStream outputStream = new FileOutputStream(filePath); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
może z powodzeniem napisać ten ciąg bez wyjątków. Ponadto, jeśli napiszę ten sam ciąg utworzony ze znaków, nadal działa OK.
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();
Wcześniej nigdy nie napotkałem żadnego wyjątku podczas używania pierwszego BufferedWriter do pisania jakichkolwiek ciągów. To dziwny błąd, który występuje w BufferedWriter utworzonym z java.nio.file.Files.newBufferedWriter (ścieżka, opcje)
źródło
ISO_8859_1 Pracowało dla mnie! Czytałem plik tekstowy z wartościami oddzielonymi przecinkami
źródło
spróbuj tego .. miałem ten sam problem, poniżej implementacja działała dla mnie
następnie używaj programu Reader, gdziekolwiek chcesz.
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(); }
źródło
Napisałem poniżej, aby wydrukować listę wyników do standaryzacji w oparciu o dostępne zestawy znaków. Zwróć uwagę, że informuje również o tym, która linia nie działa z numeru linii opartego na 0, w przypadku rozwiązywania problemów ze znakiem powodującym problemy.
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); } }
źródło
Cóż, problem polega na tym, że
Files.newBufferedReader(Path path)
jest to realizowane w następujący sposób:public static BufferedReader newBufferedReader(Path path) throws IOException { return newBufferedReader(path, StandardCharsets.UTF_8); }
więc w zasadzie nie ma sensu określać,
UTF-8
chyba że chcesz, aby kod był opisowy. Jeśli chcesz wypróbować „szerszy” zestaw znaków, możesz spróbowaćStandardCharsets.UTF_16
, ale i tak nie możesz być w 100% pewien, że otrzymasz wszystkie możliwe znaki.źródło
możesz spróbować czegoś takiego lub po prostu skopiować i wkleić poniższy fragment.
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 ++; } }
źródło
while(exception)
pętlę wieczną, jeśli nigdy nie znajdzie działającego zestawu znaków w tablicy. Program obsługi wyjątków powinien ponownie zgłosić, jeśli osiągnięty zostanie koniec tablicy i nie zostanie znaleziony działający zestaw znaków. Ponadto w chwili pisania tej odpowiedzi liczba głosów wynosiła „-2”. Głosowałem za „-1”. Myślę, że powodem, dla którego otrzymała głosy negatywne, jest niewystarczające wyjaśnienie. Chociaż rozumiem, co robi kod, inni mogą nie. Dlatego komentarz typu „możesz spróbować czegoś takiego” może nie zostać doceniony przez niektórych ludzi.UTF-8 działa dla mnie z polskimi znakami
źródło