2012-03-16 15 views
21

Tôi cần đề xuất về cách xóa BOM khỏi tệp UTF-8 và tạo bản sao của phần còn lại của tệp xml.Cách xóa BOM khỏi tệp XML trong Java

+1

các downvotes là không phải vì một bản sao, họ đang vì câu hỏi này là quá rộng trong tự nhiên - stackoverflow là để giúp đỡ với các vấn đề lập trình cụ thể, bản địa hóa. Chúng tôi có thể giúp bạn gỡ lỗi chương trình, chúng tôi sẽ không viết một chương trình cho bạn. –

+0

Tôi đang đợi điều này ở mức -5 trước khi trả lời;) – TacticalCoder

+0

@hari: mã hóa tệp của bạn là gì? UTF-8? – TacticalCoder

Trả lời

32

Có công cụ bẻ khóa do BOM trong tệp UTF-8 là rất phổ biến trong kinh nghiệm của tôi là. Tôi không biết tại sao có rất nhiều downvotes (nhưng sau đó nó cho tôi cơ hội để có đủ số phiếu để giành được một huy hiệu SO đặc biệt;)

Quan trọng hơn: một UTF-8 BOM thường không làm ý nghĩa đó là nhưng nó hoàn toàn hợp lệ (mặc dù không được khuyến khích) bởi các thông số kỹ thuật. Bây giờ vấn đề là rất nhiều người không biết rằng một BOM là hợp lệ trong UTF-8 và do đó đã viết các công cụ/API bị hỏng mà không xử lý chính xác các tệp này.

Bây giờ bạn có thể có hai vấn đề khác nhau: bạn có thể muốn xử lý tệp từ Java hoặc bạn cần sử dụng Java để tạo/sửa các tệp mà các công cụ khác (bị hỏng) cần lập trình.

Tôi đã gặp trường hợp trong một buổi biểu diễn tư vấn, nơi bộ phận trợ giúp sẽ tiếp tục nhận được tin nhắn từ người dùng gặp sự cố với một số trình soạn thảo văn bản sẽ gây rối hoàn toàn các tệp UTF-8 hợp lệ do Java tạo. Vì vậy, tôi đã phải làm việc xung quanh vấn đề đó bằng cách đảm bảo để loại bỏ các BOM từ mỗi tập tin UTF-8 duy nhất chúng tôi đã được giao dịch với.

Tôi muốn xóa BOM khỏi một tệp, bạn có thể tạo tệp mới và bỏ qua ba byte đầu tiên. Ví dụ:

... $ file /tmp/src.txt 
/tmp/src.txt: UTF-8 Unicode (with BOM) English text 

... $ ls -l /tmp/src.txt 
-rw-rw-r-- 1 tact tact 1733 2012-03-16 14:29 /tmp/src.txt 

... $ hexdump -C /tmp/src.txt | head -n 1 
00000000 ef bb bf 50 6f 6b 65 ... 

Như bạn có thể thấy, tệp bắt đầu bằng "ef bb bf", đây là (UTF-8 BOM) hoàn toàn hợp lệ.

Dưới đây là một phương pháp mà phải mất một tập tin và tạo ra một bản sao của nó bằng cách bỏ qua ba byte đầu tiên:

public static void workAroundbrokenToolsAndAPIs(File sourceFile, File destFile) throws IOException { 
    if(!destFile.exists()) { 
     destFile.createNewFile(); 
    } 

    FileChannel source = null; 
    FileChannel destination = null; 

    try { 
     source = new FileInputStream(sourceFile).getChannel(); 
     source.position(3); 
     destination = new FileOutputStream(destFile).getChannel(); 
     destination.transferFrom(source, 0, source.size() - 3); 
    } 
    finally { 
     if(source != null) { 
      source.close(); 
     } 
     if(destination != null) { 
      destination.close(); 
     } 
    } 
} 

Lưu ý rằng đó là "thô": bạn thường muốn muốn trước tiên hãy chắc chắn rằng bạn có một BOM trước khi gọi điện thoại này hoặc "Bad Thinks May Happen" [TM].

Bạn có thể nhìn vào tập tin của bạn sau đó:

... $ file /tmp/dst.txt 
/tmp/dst.txt: UTF-8 Unicode English text 

... $ ls -l /tmp/dst.txt 
-rw-rw-r-- 1 tact tact 1730 2012-03-16 14:41 /tmp/dst.txt 

... $ hexdump -C /tmp/dst.txt 
00000000 50 6f 6b 65 ... 

Và BOM đã biến mất ...

Bây giờ nếu bạn chỉ muốn minh bạch tháo BOM cho một API Java của bạn bị hỏng, sau đó bạn có thể sử dụng pushbackInputStream mô tả ở đây: why org.apache.xerces.parsers.SAXParser does not skip BOM in utf8 encoded xml?

private static InputStream checkForUtf8BOMAndDiscardIfAny(InputStream inputStream) throws IOException { 
    PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3); 
    byte[] bom = new byte[3]; 
    if (pushbackInputStream.read(bom) != -1) { 
     if (!(bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF)) { 
      pushbackInputStream.unread(bom); 
     } 
    } 
    return pushbackInputStream; } 

Lưu ý rằng công trình này, nhưng sẽ defin itely NOT khắc phục vấn đề nghiêm trọng hơn nơi bạn có thể có các công cụ khác trong chuỗi công việc không hoạt động chính xác với các tệp UTF-8 có BOM.

Và đây là một liên kết đến một câu hỏi với một câu trả lời hoàn chỉnh hơn, bao gồm mã hóa khác như:

Byte order mark screws up file reading in Java

+0

Bầu chọn không phải là một phán quyết về * chủ đề * của một câu hỏi, chúng là sự phán xét về chất lượng * của một câu hỏi. Nhìn vào các chú giải công cụ cho các nút biểu quyết. – skaffman

+1

@skaffman: OK nhưng thay vì downvoting tôi hỏi nếu OP đã sử dụng một tập tin UTF-8 (mà tôi nghi ngờ cho vấn đề đó là tất cả quá phổ biến) và sau đó thêm rằng cho câu hỏi (và chỉnh sửa các thẻ). Tôi không biết những gì khác có thể nói: * "Làm thế nào để loại bỏ một BOM từ một tập tin?" * Là khá tự giải thích. Tôi đã thêm "UTF-8". Tất nhiên nó sẽ dễ dàng hơn cho tôi để chỉ đơn giản là downvote;) – TacticalCoder

+0

@TacticalCoder cảm ơn rất nhiều cho các đề xuất ur .. Tôi chắc chắn rằng điều này sẽ giải quyết các pblm tôi đã có. – hari