2011-09-14 20 views
49

Mój program musi czytać pliki tekstowe - linia po linii. Pliki w UTF-8. Nie jestem pewien, czy pliki są poprawne - mogą zawierać niedrukowalne znaki. Czy możliwe jest sprawdzenie bez przejścia do poziomu bajtów? Dzięki.Sprawdź linię dla niedrukowalnych znaków podczas odczytu pliku tekstowego

+0

Czy chcesz sprawdzić pojedynczą linię, czy cały plik? –

+0

Czy jest zagwarantowane, że posuwy wierszy są poprawne? – Tarnschaf

+0

zaznacz jedną linię. Tak, wiersze wierszy są poprawne. – user710818

Odpowiedz

15

Jeśli chcesz sprawdzić ciąg zawiera znaki niedrukowalne można użyć wyrażenia regularnego

[^\p{Print}] 
+0

Obejmuje to jednak białe znaki i tabulatory w zestawie znaków niedrukowalnych, które mają wpływ na miejsce słów na stronie. –

49

Chociaż nie trudno to zrobić ręcznie przy użyciu BufferedReader i InputStreamReader, użyję Guava:

List<String> lines = Files.readLines(file, Charsets.UTF_8); 

Następnie można zrobić cokolwiek chcesz z tych linii.

EDYCJA: Zauważ, że za jednym razem odczyta cały plik do pamięci. W większości przypadków jest to naprawdę w porządku - i na pewno jest to łatwiejsze niż czytanie linii po linii, przetwarzanie każdej linii podczas jej czytania. Jeśli jest to olbrzymi plik, być może trzeba to zrobić w taki sposób, jak w przypadku T.J. Odpowiedź Crowdera.

+4

Guava alse zaproponować metodę z oddzwonieniem Files.readLines (plik pliku, zestaw znaków charset, wywołanie LineProcessor oddzwonienie) – Vlagorce

+0

Jeśli celem jest przetwarzanie linii po linii, użycie BufferedRead jest tak proste. Jest również przesadą, aby dodać kolejną zależność od biblioteki tylko do odczytu linii, podczas gdy podstawowa biblioteka Java już to obsługuje. – user172818

+5

@ user172818: Nie, to nie jest takie proste ... Przynajmniej nie, jeśli nie używasz Java 7 z instrukcją try-with-resources. Dodatkowo, byłbym * zdumiony * przy każdym nietrywialnym programie Java, który nie mógłby korzystać z Guava w * wielu * miejscach. To wspaniała biblioteka i nie byłbym bez niej. –

121

Otwórz plik z FileInputStream, a następnie użyć InputStreamReader z UTF-8 Charset odczytać znaki ze strumienia i użyć BufferedReader czytać wiersze, na przykład przez BufferedReader#readLine, co da ci ciąg znaków. Gdy masz ciąg, możesz sprawdzić, czy postacie nie są tym, co uważasz za możliwe do wydrukowania.

E.g. (Bez sprawdzania błędów), używając try-with-resources (który jest w niejasno nowoczesnej wersji Java):

String line; 
try (
    InputStream fis = new FileInputStream("the_file_name"); 
    InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8")); 
    BufferedReader br = new BufferedReader(isr); 
) { 
    while ((line = br.readLine()) != null) { 
     // Deal with the line 
    } 
} 
+1

Albo, dla mniejszej liczby kroków, otwórz plik za pomocą FileReadera i użyj BufferedReader do czytania linii. –

+1

@stviper: A teraz jest 2015, zaktualizowałem go, by używać try-for-resources, znacznie czystszego. :-) –

+1

@ abhisheknaik96: Dziękuję za twoją edycję, ale tylko bit 'isr' był poprawny; '()' są ** przypuszczalnie ** to '()', a nie '{}', a ostatni średnik nie jest wymagany (ale jest dozwolony, więc go zostawiłem - bardziej zgodny z linie powyżej). –

1

Jeśli każdy znak w pliku jest poprawnie zakodowany w UTF-8, nie będzie miał żadnego problemu lektury przy użyciu czytnika z kodowaniem UTF-8. Aż do ciebie, aby sprawdzić każdy znak pliku i sprawdzić, czy uważasz, że można go wydrukować, czy nie.

42

Właśnie okazało się, że z Java NIO (java.nio.file.*) można łatwo napisać:

List<String> lines=Files.readAllLines(Paths.get("/tmp/test.csv"), Charset.forName("UTF-8")); 
for(String line:lines){ 
    System.out.println(line); 
} 

zamiast zajmować się FileInputStream s i BufferedReader s ...

+0

Po prostu chcę dodać plik java.nio.file. * Jest dostępny od JDK 7 –

+3

Warto wspomnieć o dokumencie dla [Files.readAllLines] (http://docs.oracle.com/javase/7/docs/api /java/nio/file/Files.html): ta metoda jest przeznaczona dla prostych przypadków, w których wygodne jest odczytanie wszystkich linii w pojedynczej operacji. Nie jest przeznaczony do czytania w dużych plikach. –

11

Co na ten temat poniżej:

FileReader fileReader = new FileReader(new File("test.txt")); 

BufferedReader br = new BufferedReader(fileReader); 

String line = null; 
// if no more lines the readLine() returns null 
while ((line = br.readLine()) != null) { 
     // reading lines until the end of the file 

} 

Źródło: http://devmain.blogspot.co.uk/2013/10/java-quick-way-to-read-or-write-to-file.html

+0

Nie - usuń to - korzystasz z domyślnego kodowania - i wkraczasz w świat bólu. –

3

Odpowiedź przez @TJCrowder jest Java 6 - w Javie 7 Poprawna odpowiedź jest jedna przez @McIntosh - choć jego stosowanie charset dla nazwy dla UTF -8 jest odradzane:

List<String> lines = Files.readAllLines(Paths.get("/tmp/test.csv"), 
    StandardCharsets.UTF_8); 
for(String line: lines){ /* DO */ } 

Przypomina dużo o sposobie Guava napisanym przez Skeeta powyżej - i oczywiście te same zastrzeżenia dotyczą. Oznacza to, że w przypadku dużych plików (Java 7):

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8); 
for (String line = reader.readLine(); line != null; line = reader.readLine()) {} 
5

Mogę znaleźć następujące sposoby.

private static final String fileName = "C:/Input.txt"; 

public static void main(String[] args) throws IOException { 
    Stream<String> lines = Files.lines(Paths.get(fileName)); 
    lines.toArray(String[]::new); 

    List<String> readAllLines = Files.readAllLines(Paths.get(fileName)); 
    readAllLines.forEach(s -> System.out.println(s)); 

    File file = new File(fileName); 
    Scanner scanner = new Scanner(file); 
    while (scanner.hasNext()) { 
     System.out.println(scanner.next()); 
    } 
Powiązane problemy