是否有可能实现这个功能?如果有用的话,我正在使用JFileChooser来打开文件。
编辑:
用户应提供包含URL的文本文件。
我要避免的是用户加载MP3文件或MS Word文档等其他格式的文件。
一个文件只是一系列字节,如果没有更多的信息,你无法确定这些字节是否应该是某个字符串编码中的代码点(比如ASCII或UTF-8或ANSI-something)或者其他内容。你需要采用一些启发式方法,例如:
但这里还有另一个解决方案:将你收到的所有内容视为文本,在需要时应用必要的转换(例如发送到Web浏览器时进行HTML编码)。只要防止文件被解释为二进制数据(例如用户双击文件),你最糟糕的情况就是产生一些无意义的数据。
文本也是一种二进制数据形式。
我想你想要检查的是输入中是否有任何字符小于32。如果你可以安全地假设你的文本是多字节编码的,那么你可以扫描整个文件,并在遇到范围为[0,32)(不包括9、10、13和其他你可能期望在“文本”中除外的内容,或者最坏情况下仅检查空字节[感谢tdammers!])的字节时中止。如果你可能会收到UTF-16或UTF-32编码的文本,则需要更加努力。
您还可以检查初始字节是否为BOM,这应该表示一个UTF文件:
- UTF-8 => 0xEF, 0xBB, 0xBF
- UTF-16 BE => 0xFE, 0xFF
- UTF-16 LE => 0xFF, 0xFE
罗桑
如果您不想通过文件扩展名猜测文件类型,您可以读取文件的前一部分。但下一个问题将是字符编码。使用BufferedInputStream
(在mark()
之前和reset()
之后),用编码为"ISO-8859-1"
的InputStreamReader
包装,并使用Character.isLetterOrDigit()
或Character.isWhitespace()
计算读取的字符数,以获取典型文本内容的比率。我认为对于文本文件,这个比率应该超过80%。
您也可以尝试其他编码,如UTF-8,但当它不是UTF-8时,可能会遇到无效字符的问题。
你可以从Java中调用shell命令file -i ${filename}
,并检查输出以查看是否包含类似于charset=binary
的内容。如果是,则它是二进制文件。否则它是基于文本的文件。
你可以在shell中尝试使用file
来处理各种文件,并熟悉它。在Groovy中,我会写出类似于:
'file -i ${path/to/myfile}'.execute().getText().contains('charset=binary')
在Java中,你也可以调用shell命令。请参考this。