如何知道運行時指定文件夾中的文件是否爲文本渲染? (即像csv,html等可以顯示爲文本的文件)如何知道文件是否爲文本渲染? (Java)
我不想通過擴展匹配(通過檢查.txt,.html擴展等)來做到這一點。
假設如果有一個jpg文件,我故意將擴展名重命名爲.txt,而且java代碼應該能夠檢測到該文件(儘管帶有.txt extn)不能被渲染爲文本。
我該如何在java中實現這個功能?
如何知道運行時指定文件夾中的文件是否爲文本渲染? (即像csv,html等可以顯示爲文本的文件)如何知道文件是否爲文本渲染? (Java)
我不想通過擴展匹配(通過檢查.txt,.html擴展等)來做到這一點。
假設如果有一個jpg文件,我故意將擴展名重命名爲.txt,而且java代碼應該能夠檢測到該文件(儘管帶有.txt extn)不能被渲染爲文本。
我該如何在java中實現這個功能?
您可以通過掃描該文件並使用Character.html#isISOControl來檢查是否包含不可打印的字符,從而猜出該類型。
二進制文件通常包含通常包含控制字符的標頭,請參閱此list of File Signatures其中大多數將由isISOControl檢測到。
實現一個啓發式匹配器,它掃描已知簽名的文件。
一個典型的例子是file
命令:http://en.wikipedia.org/wiki/File_(command)和libmagic庫。
在Java中幾個變種,如提卡:http://tika.apache.org/
我不認爲這是一個100%萬無一失的方法來做到這一點,因爲這是一個見仁見智什麼算是「可以顯示爲文本「...但如果您可以將其限制爲英文文本,則可以檢查文件的字節,並且如果大部分或全部字節值在32到126(十進制無符號)的範圍內,則很可能是vanilla ASCII text。
這是要求某種統計模式匹配。例如,如果您只使用英文,請檢查前100個字符中出現多少「外來」字符。這應該給你一個很好的主意,看它是否是文本文檔。如果遇到太多不是a..zA..Z0..9 [punctutation]的字符,則可以猜測它不是文本。使用英文文件和主要用ASCII字符列表表示的語言,你應該相對安全。
當你開始使用外國語言的時候,這些當然會走出窗口,其中一些字符可能看起來像是特殊字符,但只對不會說這種語言的人有用。
另一種選擇是使用文件標記(就像在Java中,一個類文件以一個特定的頭文件開頭),並將文件中的值與頭文件庫進行比較。它也很麻煩,也容易出錯,因爲你可能沒有記錄文件,因此可能認爲它是一個文本文件。
您可以維護可接受的MIME類型的列表,然後獲取您正在閱讀的文件的MIME類型。如果它匹配很好去。
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
class GetMimeType {
public static void main(String args[]) {
File f = new File("gumby.gif");
System.out.println("Mime Type of " + f.getName() + " is " +
new MimetypesFileTypeMap().getContentType(f));
// expected output :
// "Mime Type of gumby.gif is image/gif"
}
}
使用的a Character#isISOControl是一件好事。你也應該考慮編碼(p.ex.UTF-8)。在這裏我的功能:
/**
* Test is a file is a text file. It is the case only if it has no well-known control characters.
* (see {@link Character#isISOControl(int)})
* @param file
* @return
* @throws IOException
*/
public static boolean isTextFile (final File file) throws IOException
{
BufferedInputStream is = null;
try
{
final BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-16"));
boolean isText;
int read;
do
{
read = in.read();
isText = read == -1;
isText |= read == 13; // newline
isText |= read == 10; // newline
isText |= read == 9; // tab
isText |= !Character.isISOControl(read);
}
while (isText && read != -1);
return isText;
}
finally {
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
throw new Error(e);
}
}
}
}
不要忘記CR \ LF ;-) – Jimmy
是的,也是標籤! –