2011-07-02 95 views
6

在我的程序中,用戶可以加載帶有鏈接的文件(這是一個webcrawler),但我需要驗證用戶選擇的文件是純文本還是其他文件(只允許純文本)。如何檢查文件是純文本?

可以這樣做嗎?如果有用,我使用JFileChooser來打開文件。

編輯:

什麼是從用戶預期:包含URL的文本文件。

我想要避免的事情:用戶從MS Word(示例)中加載MP3文件或文檔。

回答

5

一個文件只是一系列的字節,沒有更多的信息,你不能分辨這些字節是否應該是某些字符串編碼(比如ASCII或UTF-8或ANSI-something)中的代碼點或其他東西。您將不得不採取啓發式方法,例如:

  • 嘗試解析許多已知編碼中的文件,並查看解析是否成功。如果確實如此,那麼你可能有一個文本文件。
  • 如果您希望僅使用西方語言的文本文件,則可以假設大多數字符位於ASCII範圍(0..127),更具體地說是(33..127)加上空格(製表符,換行符,運輸回報,空間)。對每個不同字節值的出現次數進行計數,如果文檔的壓倒性部分處於「典型西文字符」集合中,則通常認爲它是文本文件是安全的。
  • 擴展以前的方法;以期望的語言對足夠多的文本進行採樣,並建立一個字符頻率曲線。要檢查您的文件,請將文件的字符頻率配置文件與您的測試數據進行比較,並查看它是否足夠接近。

但是,這裏有另一種解決方案:將所有您收到的文本視爲文本,在需要時應用必要的轉換(例如發送到Web瀏覽器時進行HTML編碼)。只要你防止文件被解釋爲二進制數據(例如用戶雙擊該文件),最糟糕的是你會產生亂碼數據。

2

文本也是二進制數據的一種形式。

我想你要檢查的是你的輸入中是否有任何字符是< 32.如果你可以安全地假定你的文本是多字節編碼的,那麼你可以掃描整個文件並中止如果你在[0,32]範圍內選擇一個字節(不包括9,10,13,除了「文本」中的任何其他內容),或者最壞的情況檢查空字節[謝謝,tdammers!] )。如果您可以合理地期望接收UTF-16或UTF-32編碼文本,則必須更加努力。

+0

Tab,換行符和回車符<32 – tdammers

+0

@tdammers:哎呀,好抓。好的,排除那些比賽!那麼換行呢? :-) –

+0

我可能會檢查文件是否爲UTF-8,假設它是文本,如果它是有效的UTF-8(可能不包括與製表符,換行符和回車符以及127之外的代碼點<32)。 – MRAB

0

您應該創建一個查看文件描述的過濾器,並檢查文本。

1

如果您不想通過file extension來猜測,您可以閱讀文件的第一部分。但接下來的問題將是字符編碼。使用BufferedInputStream(之前的mark()和之後的reset()),用編碼爲"ISO-8859-1"InputStreamReader進行包裝,並使用Character.isLetterOrDigit()Character.isWhitespace()對已讀取的字符進行計數,以獲得典型文本內容的比率。我認爲文本文件的比例應該超過80%。

您也可以嘗試使用其他編碼,如UTF-8,但當您的編碼不是UTF-8時,您可能會遇到無效的字符問題。

+0

我可以輕鬆地將圖像的擴展名重命名爲「.TXT」,並嘗試將其加載到試圖打開「文本」文件並導致其崩潰的應用程序中。 – Si8

+0

@ SiKni8:這不是問題,一個好的應用程序在打開二進制文件時不會崩潰! –

1

您還可以查看是否初始字節是物料清單,這應該表明UTF文件:

- UTF-8  => 0xEF, 0xBB, 0xBF 
- UTF-16 BE => 0xFE, 0xFF 
- UTF-16 LE => 0xFF, 0xFE 

Rossum的

0

可以從Java調用shell命令file -i ${filename},並檢查輸出看它是否包含像charset=binary這樣的東西。如果是這樣,那麼它是二進制文件。否則,它是基於文本的文件。

你可以在shell中使用file在各種文件中玩並熟悉它。 Groovy中我會寫類似

'file -i ${path/to/myfile}'.execute().getText().contains('charset=binary')

在Java中,你也可以撥打shell命令。請參閱this

相關問題