2011-07-02 93 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

相关问题