代码之家  ›  专栏  ›  技术社区  ›  yanchenko

确定Java中的二进制/文本文件类型?

  •  38
  • yanchenko  · 技术社区  · 15 年前

    也就是说,如何区分归档文件(jar/rar/etc)和文本文件(xml/txt,独立于编码)呢?

    10 回复  |  直到 12 年前
        1
  •  19
  •   Ahmed Ashour chim    4 年前

    没有保证的方法,但这里有两种可能性:

    1. 寻找定期重复的换行符模式。

        2
  •  15
  •   rince    8 年前

    http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType(java.nio.file.Path)

    boolean isBinaryFile(File f) throws IOException {
            String type = Files.probeContentType(f.toPath());
            if (type == null) {
                //type couldn't be determined, assume binary
                return true;
            } else if (type.startsWith("text")) {
                return false;
            } else {
                //type isn't text
                return true;
            }
        }
    
        3
  •  11
  •   Wilfred Springer    15 年前

    file -bi {filename} . 如果返回的内容以“text/”开头,则它是非二进制的,否则它是。;-)

        4
  •  10
  •   antimatter15    9 年前

    我做了这个。 稍微简单一点,但对于基于拉丁语的语言,它应该可以很好地工作,并进行比率调整。

    /**
     *  Guess whether given file is binary. Just checks for anything under 0x09.
     */
    public static boolean isBinaryFile(File f) throws FileNotFoundException, IOException {
        FileInputStream in = new FileInputStream(f);
        int size = in.available();
        if(size > 1024) size = 1024;
        byte[] data = new byte[size];
        in.read(data);
        in.close();
    
        int ascii = 0;
        int other = 0;
    
        for(int i = 0; i < data.length; i++) {
            byte b = data[i];
            if( b < 0x09 ) return true;
    
            if( b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D ) ascii++;
            else if( b >= 0x20  &&  b <= 0x7E ) ascii++;
            else other++;
        }
    
        if( other == 0 ) return false;
    
        return 100 * other / (ascii + other) > 95;
    }
    
        5
  •  9
  •   Daniel Hiller    8 年前

    JMimeMagic 图书馆

    确定文件或文件的MIME类型 溪流。

        6
  •  6
  •   Anonymous Penguin    11 年前

    我使用了此代码,它对英语和德语文本非常有效:

    private boolean isTextFile(String filePath) throws Exception {
        File f = new File(filePath);
        if(!f.exists())
            return false;
        FileInputStream in = new FileInputStream(f);
        int size = in.available();
        if(size > 1000)
            size = 1000;
        byte[] data = new byte[size];
        in.read(data);
        in.close();
        String s = new String(data, "ISO-8859-1");
        String s2 = s.replaceAll(
                "[a-zA-Z0-9ßöäü\\.\\*!\"§\\$\\%&/()=\\?@~'#:,;\\"+
                "+><\\|\\[\\]\\{\\}\\^°²³\\\\ \\n\\r\\t_\\-`´âêîô"+
                "ÂÊÔÎáéíóàèìòÁÉÍÓÀÈÌÒ©‰¢£¥€±¿»«¼½¾™ª]", "");
        // will delete all text signs
    
        double d = (double)(s.length() - s2.length()) / (double)(s.length());
        // percentage of text signs in the text
        return d > 0.95;
    }
    
        7
  •  4
  •   Matthew    15 年前

    如果文件由字节0x09(制表符)、0x0A(换行符)、0x0C(换行符)、0x0D(回车符)或0x20到0x7E组成,那么它可能是ASCII文本。

    对于任何具有高阶位的字节,UTF-8文本都遵循一种非常特定的模式,但像ISO-8859-1这样的固定长度编码则不然。UTF-16经常包含空字节(0x00),但仅在其他位置。

        8
  •  3
  •   yanchenko    15 年前

    1. 假设该文件是二进制文件,尝试执行应该执行的操作(例如反序列化)
    2. 将文件视为文本
    3. 如果失败,则说明文件本身有问题
        10
  •  2
  •   xenoterracide    3 年前

    你可以试试ApacheTika,我开了一个 request specifically for this feature

    但现在,我认为这可能会奏效。。。需要更彻底的测试,可能还有其他mime类型库的问题,在这些库中,您仍然需要从类型到是否为二进制的映射。

    var config = TikaConfig.getDefaultConfig();
    var tika = new Tika( config );
    var mimeTypes = config.getMimeRepository();
    
    var mimetype = tika.detect(Path.of("my/foo"));
    var rootType = mimeTypes.forName( mime ).getType().getType();
    rootType.endsWith( "text" ); // text and x-text
    
        11
  •  1
  •   Fabian Steeg    15 年前

    你可以试试这个 DROID