`
zpball
  • 浏览: 916293 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

用java流方式判断文件类型

阅读更多
原文:http://rainsilence.iteye.com/blog/842338

package org.filetype;

/**
 * 文件类型枚取
 */
public enum FileType {
	
	/**
	 * JEPG.
	 */
	JPEG("FFD8FF"),
	
	/**
	 * PNG.
	 */
	PNG("89504E47"),
	
	/**
	 * GIF.
	 */
	GIF("47494638"),
	
	/**
	 * TIFF.
	 */
	TIFF("49492A00"),
	
	/**
	 * Windows Bitmap.
	 */
	BMP("424D"),
	
	/**
	 * CAD.
	 */
	DWG("41433130"),
	
	/**
	 * Adobe Photoshop.
	 */
	PSD("38425053"),
	
	/**
	 * Rich Text Format.
	 */
	RTF("7B5C727466"),
	
	/**
	 * XML.
	 */
	XML("3C3F786D6C"),
	
	/**
	 * HTML.
	 */
	HTML("68746D6C3E"),
	
	/**
	 * Email [thorough only].
	 */
	EML("44656C69766572792D646174653A"),
	
	/**
	 * Outlook Express.
	 */
	DBX("CFAD12FEC5FD746F"),
	
	/**
	 * Outlook (pst).
	 */
	PST("2142444E"),
	
	/**
	 * MS Word/Excel.
	 */
	XLS_DOC("D0CF11E0"),
	
	/**
	 * MS Access.
	 */
	MDB("5374616E64617264204A"),
	
	/**
	 * WordPerfect.
	 */
	WPD("FF575043"),
	
	/**
	 * Postscript.
	 */
	EPS("252150532D41646F6265"),
	
	/**
	 * Adobe Acrobat.
	 */
	PDF("255044462D312E"),
	
	/**
	 * Quicken.
	 */
	QDF("AC9EBD8F"),
	
	/**
	 * Windows Password.
	 */
	PWL("E3828596"),
	
	/**
	 * ZIP Archive.
	 */
	ZIP("504B0304"),
	
	/**
	 * RAR Archive.
	 */
	RAR("52617221"),
	
	/**
	 * Wave.
	 */
	WAV("57415645"),
	
	/**
	 * AVI.
	 */
	AVI("41564920"),
	
	/**
	 * Real Audio.
	 */
	RAM("2E7261FD"),
	
	/**
	 * Real Media.
	 */
	RM("2E524D46"),
	
	/**
	 * MPEG (mpg).
	 */
	MPG("000001BA"),
	
	/**
	 * Quicktime.
	 */
	MOV("6D6F6F76"),
	
	/**
	 * Windows Media.
	 */
	ASF("3026B2758E66CF11"),
	
	/**
	 * MIDI.
	 */
	MID("4D546864");
	
	private String value = "";
	
	/**
	 * Constructor.
	 * 
	 * @param type 
	 */
	private FileType(String value) {
		this.value = value;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}



类型判断核心类

package org.filetype;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 文件类型判断类
 */
public final class FileTypeJudge {
	
	/**
	 * Constructor
	 */
	private FileTypeJudge() {}
	
	/**
	 * 将文件头转换成16进制字符串
	 * 
	 * @param 原生byte
	 * @return 16进制字符串
	 */
	private static String bytesToHexString(byte[] src){
		
        StringBuilder stringBuilder = new StringBuilder();   
        if (src == null || src.length <= 0) {   
            return null;   
        }   
        for (int i = 0; i < src.length; i++) {   
            int v = src[i] & 0xFF;  //java中byte转换int时与0xff进行与运算 ?
            String hv = Integer.toHexString(v);   
            if (hv.length() < 2) {   
                stringBuilder.append(0);   
            }   
            stringBuilder.append(hv);   
        }   
        return stringBuilder.toString();   
    }
   
	/**
	 * 得到文件头
	 * 
	 * @param filePath 文件路径
	 * @return 文件头
	 * @throws IOException
	 */
	private static String getFileContent(String filePath) throws IOException {
		
		byte[] b = new byte[28];
		
		InputStream inputStream = null;
		
		try {
			inputStream = new FileInputStream(filePath);
			inputStream.read(b, 0, 28);
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw e;
				}
			}
		}
		return bytesToHexString(b);
	}
	
	/**
	 * 判断文件类型
	 * 
	 * @param filePath 文件路径
	 * @return 文件类型
	 */
	public static FileType getType(String filePath) throws IOException {
		
		String fileHead = getFileContent(filePath);
		
		if (fileHead == null || fileHead.length() == 0) {
			return null;
		}
		
		fileHead = fileHead.toUpperCase();
		
		FileType[] fileTypes = FileType.values();
		
		for (FileType type : fileTypes) {
			if (fileHead.startsWith(type.getValue())) {
				return type;
			}
		}
		
		return null;
	}
}



测试类

package org.filetype;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String args[]) throws Exception {
		System.out.println(FileTypeJudge.getType("C:\\eclipse-jee-helios-win32.zip"));
	}

}


执行测试类,console上显示zip。。



java中byte转换int时为何与0xff进行与运算

在剖析该问题前请看如下代码
public static String bytes2HexString(byte[] b) {
  String ret = "";
  for (int i = 0; i < b.length; i++) {
   String hex = Integer.toHexString(b[ i ] & 0xFF);
   if (hex.length() == 1) {
    hex = '0' + hex;
   }
   ret += hex.toUpperCase();
  }
  return ret;
}

上面是将byte[]转化十六进制的字符串,注意这里b[ i ] & 0xFF将一个byte和 0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出
b[ i ] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b[ i ]);,将byte强转为int不行吗?答案是不行的.

其原因在于:
1.byte的大小为8bits而int的大小为32bits
2.java的二进制采用的是补码形式

在这里先温习下计算机基础理论

byte是一个字节保存的,有8个位,即8个0、1。
8位的第一个位是符号位,
也就是说0000 0001代表的是数字1
1000 0000代表的就是-1
所以正数最大位0111 1111,也就是数字127
负数最大为1111 1111,也就是数字-128

上面说的是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码

1、反码:
        一个数如果是正,则它的反码与原码相同;
        一个数如果是负,则符号位为1,其余各位是对原码取反;

2、补码:利用溢出,我们可以将减法变成加法
       对于十进制数,从9得到5可用减法:
       9-4=5    因为4+6=10,我们可以将6作为4的补数
       改写为加法:
       9+6=15(去掉高位1,也就是减10)得到5.

       对于十六进制数,从c到5可用减法:
       c-7=5    因为7+9=16 将9作为7的补数
       改写为加法:
       c+9=15(去掉高位1,也就是减16)得到5.

    在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。

    ⑴一个数为正,则它的原码、反码、补码相同
    ⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1
   
- 1的原码为                10000001
- 1的反码为                11111110
                                                   + 1
- 1的补码为                11111111

0的原码为                 00000000
0的反码为                 11111111(正零和负零的反码相同)
                                          +1
0的补码为               100000000(舍掉打头的1,正零和负零的补码相同)

Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位,
例如补码11111111的十进制数为-1转换为int时变为11111111111111111111111111111111好多1啊,呵呵!即0xffffffff但是这个数是不对的,这种补位就会造成误差。
和0xff相与后,高24比特就会被清0了,结果就对了。

----
Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。

而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。
分享到:
评论

相关推荐

    java实现上传文件类型检测过程解析

    然后,使用 HashMap 缓存文件头信息,通过文件头信息来判断文件的真正类型。 以下是 Java 实现上传文件类型检测过程解析的示例代码: ```java import java.io.*; import java.util.HashMap; public class ...

    根据头信息判断文件类型

    根据头信息判断文件类型是计算机科学中的一个常见技术,它基于这样一个事实:大多数文件格式在开始部分都会包含一些特定的字节序列,这些序列被称为“魔术数字”或“文件签名”,用于标识文件的类型。这种方法在很多...

    java如何实现判断文件的真实类型

    为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断上传文件是否符合格式。 二、Java获取文件头信息 Java可以通过文件输入流(FileInputStream)...

    Java判断文件的编码

    本文将详细介绍如何使用Java来判断文件是否为UTF-8或GBK编码,并提供一个示例代码。 #### 文件编码基础知识 1. **UTF-8**:一种可变长度的字符编码,适用于所有Unicode字符,它通过使用一种巧妙的方案来表示各种...

    java获取文件编码(判断有无BOM)

    本文将详细介绍如何在Java中获取文件的编码并判断文件是否带有BOM。 首先,让我们了解一下什么是BOM。BOM是UTF-8、UTF-16和UTF-32等编码格式中的一个可选标记,用于告知解析器文件的编码类型。例如,UTF-8的BOM是三...

    java判断编码方式

    在Java编程语言中,判断文件或字符串的编码方式是一个常见的需求。这主要涉及到字符集的概念,如ASCII、ISO-8859-1、UTF-8等,它们用于将二进制数据转换为人类可读的字符。在Java中,有多种方法可以用来识别或检测一...

    文件类型判断java

    本篇文章将深入探讨如何在Java中通过读取文件流的头二十个字节来判断文件类型。 首先,我们要理解为什么需要通过文件流的字节来判断类型。文件的后缀名仅仅是人为设定的标识,有时可能被篡改或丢失,而文件的实际...

    SpringBoot文件上传控制及Java 获取和判断文件头信息

    2. Java 获取和判断文件头信息:如何使用 Java 语言来获取和判断文件头信息,包括如何使用 MultipartFile 对象来获取文件信息,以及如何判断文件的类型和大小等信息。 3. Ajax 文件上传:如何使用 Ajax 方式上传文件...

    Java源代码打开指定类型的文件.rar

    在实际项目中,我们可能需要根据文件扩展名来判断文件类型,然后调用相应的处理方法。例如: ```java String extension = file.getName().substring(file.getName().lastIndexOf(".") + 1); if ("txt"....

    java文件流

    File 类提供了许多方法来操作文件和目录,如创建文件、删除文件、判断文件是否存在等。 文件操作——以字节流方式写文件 在 Java 中,可以使用字节流来写文件。写文件可以使用 FileOutputStream 类,将数据写入到...

    java 判断两个文件是否相同

    这时可以考虑使用`java.io.FileInputStream`流逐块读取并比较。另外,为了提高效率,可以先计算文件的MD5或SHA哈希值,这是一种快速且可靠的文件内容校验方法。 ```java import java.io.FileInputStream; import ...

    java读取excel多个sheet内容,用流的方式判断excel版本

    用poi读取excel多个sheet内容,用流的方式判断excel的版本,2003,还是2007版本,并附带所需jar包,文件下载后解压,直接导入eclipse中即可使用

    java 解析 tar gz文件 两种方法

    在Java中解析这种类型的文件,通常需要两个步骤:首先解压gzip,然后解包tar。这里我们将详细探讨两种不同的方法来实现这个过程。 方法一:使用Apache Commons Compress库 Apache Commons Compress库是Java社区...

    JAVA程序设计判断题题库81道

    Java是一种广泛使用的高级编程语言,以其跨平台、安全性强...总的来说,这些题目覆盖了Java程序设计的基础概念,包括语法、面向对象、数据类型、控制流、数组以及类和对象的使用,是学习和理解Java编程的良好练习材料。

    Java以流的形式上传文件

    - 通过 `if (inFile.length() * 1024 * 5)` 来判断文件大小是否小于5MB,这是一个简单的大小限制实现。 6. **读写操作**: - 使用 `in.read(buffer)` 读取缓冲区中的数据,当返回值大于0时,表示读取到了数据,...

    JAVA实现文件类型预处理

    在Java编程中,文件类型预处理是一个重要的环节,特别是在处理大量数据或进行文件操作时。这一过程涉及到识别、转换和优化文件以便后续处理。本文将深入探讨如何利用Java实现文件类型的预处理,以及与之相关的数据...

    Android中Java根据文件头获取文件类型的方法

    为了提高识别的准确性,我们可以依据文件头信息来判断文件类型。文件头通常包含特定的字节序列,这些序列是文件格式的标识符。 本文将详细介绍一种在Android中使用Java根据文件头获取文件类型的实现方法。这个方法...

    java 用户登录 文件流

    ### Java用户登录与文件流操作知识点解析 #### 一、概览 在给出的代码片段中,主要涉及到了几个核心的Java概念和技术点,包括文件流操作、接口和多态的应用,以及简单的用户输入和验证逻辑。这些技术点通常被用于...

    VC通过文件头格式,判断文件的真实格式

    以下是一个Java语言的示例代码,展示了如何通过文件头判断文件类型: ```java import java.io.FileInputStream; import java.io.IOException; public class FileHeaderCheck { /** * byte数组转换成16进制字符串...

    java 文件操作及IO流

    Java 文件操作与IO流是Java编程中的核心概念,主要用于数据的读取、写入和传输。在Java中,文件操作通常涉及到`java.io`包下的类,如...在实际开发中,根据需求选择合适的流类型和使用方式,确保数据的正确传输和存储。

Global site tag (gtag.js) - Google Analytics