2011-09-14 39 views
49

Chương trình của tôi phải đọc tệp văn bản - từng dòng một. Tệp trong UTF-8. Tôi không chắc chắn rằng các tệp là chính xác - có thể chứa các ký tự không thể in được. Có thể kiểm tra nó mà không cần đến cấp độ byte không? Cảm ơn.Kiểm tra dòng cho các ký tự không in được trong khi đọc tệp văn bản

+0

Bạn có muốn kiểm tra một dòng hoặc toàn bộ tệp không? –

+0

Có đảm bảo rằng các nguồn cấp dữ liệu dòng là chính xác không? – Tarnschaf

+0

kiểm tra một dòng. Có, nguồn cấp dữ liệu dòng là chính xác. – user710818

Trả lời

15

Nếu bạn muốn kiểm tra một chuỗi có ký tự chưa in ra bạn có thể sử dụng một biểu thức chính quy

[^\p{Print}] 
+0

Điều này, tuy nhiên, bao gồm các khoảng trống và các ký tự tab trong tập hợp các ký tự không in của bạn trong khi chúng ảnh hưởng đến vị trí của các từ trong trang. –

49

Trong khi nó không phải là khó có thể làm điều này bằng tay sử dụng BufferedReaderInputStreamReader, tôi muốn sử dụng Guava:

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

Sau đó bạn có thể làm bất cứ điều gì bạn thích với những dòng.

EDIT: Lưu ý rằng điều này sẽ đọc toàn bộ tệp vào bộ nhớ trong một lần. Trong hầu hết các trường hợp, điều đó thực sự tốt - và chắc chắn là đơn giản hơn hơn đọc từng dòng một, xử lý từng dòng khi bạn đọc nó. Nếu đó là một tập tin khổng lồ, bạn có thể cần phải làm theo cách đó theo T.J. Câu trả lời của Crowder.

+4

Dung dịch ổi đề xuất phương pháp có gọi lại Files.readLines (Tệp tệp, bộ ký tự Charset, LineProcessor gọi lại) – Vlagorce

+0

Nếu mục đích là xử lý từng dòng, việc sử dụng BufferedRead là đơn giản. Nó cũng quá tải để thêm một phụ thuộc thư viện khác chỉ để đọc dòng trong khi thư viện Java cốt lõi đã hỗ trợ điều đó. – user172818

+5

@ user172818: Không, nó không đơn giản ... ít nhất là nếu bạn không sử dụng Java 7 với câu lệnh try-with-resources. Ngoài ra, tôi sẽ ngạc nhiên * ở bất kỳ chương trình Java không tầm thường nào mà không thể hưởng lợi từ Guava ở * nhiều * địa điểm. Đó là một thư viện tuyệt vời, và tôi sẽ không có nó. –

121

Mở tệp bằng FileInputStream, sau đó sử dụng InputStreamReader với UTF-8 Charset để đọc các ký tự từ luồng và sử dụng BufferedReader để đọc các dòng, ví dụ: qua số BufferedReader#readLine, sẽ cung cấp cho bạn một chuỗi. Khi bạn có chuỗi, bạn có thể kiểm tra các ký tự không phải là những gì bạn cho là có thể in được.

Ví dụ: (Mà không kiểm tra lỗi), sử dụng try-with-resources (đó là trong phiên bản Java mơ hồ hiện đại):

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

Hoặc, trong một bước ít hơn, mở tệp bằng FileReader và sử dụng một BufferedReader để đọc dòng. –

+1

@stviper: Và bây giờ là năm 2015, tôi đã cập nhật nó để sử dụng các tài nguyên thử nghiệm, sạch hơn nhiều. :-) –

+1

@ abhisheknaik96: Cảm ơn bạn đã chỉnh sửa nhưng chỉ có bit 'isr' là đúng; '()' được giả định ** là '()', không phải '{}' và dấu chấm phẩy cuối cùng không được yêu cầu (nhưng nó được cho phép, vì vậy tôi đã bỏ qua nó - nhiều hơn để phù hợp với dòng trên nó). –

1

Nếu mỗi char trong file được mã hóa đúng cách trong UTF-8, bạn sẽ không có bất kỳ vấn đề đọc nó sử dụng đầu đọc có mã hóa UTF-8. Tùy thuộc vào bạn để kiểm tra tất cả các char của tập tin và xem nếu bạn xem xét nó có thể in hay không.

42

Chỉ cần phát hiện ra rằng với Java NIO (java.nio.file.*), bạn có thể dễ dàng viết:

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

thay vì giao dịch với FileInputStream s và BufferedReader s ...

+0

Chỉ muốn thêm, java.nio.file. * Có sẵn từ JDK 7 –

+3

Có thể đáng nhắc đến tài liệu cho [Files.readAllLines] (http://docs.oracle.com/javase/7/docs/api /java/nio/file/Files.html): Phương pháp này là dành cho các trường hợp đơn giản, nơi thuận tiện để đọc tất cả các dòng trong một thao tác đơn lẻ. Nó không có ý định đọc trong các tệp lớn –

11

Làm thế nào về bên dưới:

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 

} 

Nguồn: http://devmain.blogspot.co.uk/2013/10/java-quick-way-to-read-or-write-to-file.html

+0

Không - xóa điều này - bạn đang sử dụng mã hóa mặc định - và bước vào một thế giới đau đớn. –

3

Câu trả lời bởi @TJCrowder là Java 6 - trong java 7 câu trả lời hợp lệ là từng người @McIntosh - mặc dù sử dụng các Charset cho tên cho UTF -8 không được khuyến khích:

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

Nhắc nhở rất nhiều cách được đăng bởi Skeet ở trên - và tất nhiên cũng áp dụng cùng một điều kiện. Tức là, đối với các tệp lớn (Java 7):

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

Tôi có thể tìm các cách sau để thực hiện.

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()); 
    } 
Các vấn đề liên quan