简单的目录分离
问题:
开发web应用的过程中,我们通常会有文件上传的需求,一般由客户端上传到服务器上的文件不会被保存到数据库中(这样会产生一定的安全性问题),而是将上传的文件保存到服务器上的一个特定的目录中.如果单单将所有的文件都保存到一个目录中,也会产生一些问题,当网站访问量很大,上传文件很多时,服务器上保存文件的目录会由于保存太多的文件,而产生打开和读写都很缓慢的问题.解决这个问题的思路就是对上传的文件按照一定的规则,保存到不同的目录中.
解决方案:
思路一:可以按照上传的时间将文件保存到不同的目录中,如2018年1月份上传的文件,保存到 /2018/1 目录中.当然根据网站的流量,这样的目录层次还可以继续划分下去.
代码实现:
/** * 目录规则:/yyyy/MM/dd * 按时间生成上传文件的存储路径的思路简单,而且一般的web应用使用这种方式也可以满足需求. * 如果网站访问量很大,上传文件很多时,还可以继续往下分:/yyyy/MM/dd/hh/mm.. * */ public static String getPathByTime() { StringBuilder path = new StringBuilder(); // 按系统当前时间计算出存储路径 Calendar currTime = Calendar.getInstance(); int year = currTime.get(Calendar.YEAR); int month = currTime.get(Calendar.MONTH) + 1; int day = currTime.get(Calendar.DAY_OF_MONTH); // 字符串拼接 path.append(File.separator + year).append(File.separator + month).append(File.separator + day); return path.toString(); }
思路二:目录分离算法,其实就是一个小技巧,使用它可以得到一个目录结构,这个目录结构可以保证每个目录中的文件数量不会太多.
步骤1.给定一个唯一的文件名,获取这个文件名的哈希码值 code.
步骤2.code 值是一个整数,我们将 code 和 0xf 相与,得到一个 int 值作为第一层目录名(思考一下,这个 int 值的范围,就是0-15).
步骤3.然后将 code 值无符号右移4位,得到一个新的 int 值赋予 code,然后将 code 再和 0xf 相与,得到第二层目录名.
因为 Java 中一个整数占4个字节,也就是32位,那么一个整数按照上述规则,最多右移8次就会归0.所以我们可以将上述过程进行8次,得到8级目录,由于每次右移4位,所以每级目录中最多有16个子目录(0-15).好啦,我只能表述到这里啦.直接看看代码吧.
代码实现:
/** * 目录分离算法:由此算法可以得到8级目录,每一级目录中最多有16个子目录,所以此算法最大可计算出42.9亿多个存储路径. * 由唯一文件名计算出一个存储路径,可以有效避免在一个目录中存储太多的文件. * */ public static String getPath(String name) { int hash = name.hashCode(); StringBuilder path = new StringBuilder(); for (int i=0; i<8; i++) { // hash & 0xf 后,得到0-15中的一个整数 int dir = hash & 0xf; // 将 hash 码无符号右移 4 位(一个整数最多右移8次就归0) hash = hash >>> 4; // 字符串拼接 path.append(File.separator + dir); } return path.toString(); }
总结:当然了,这样的目录划分还有很多其它的规则,根据不同的需求,我们可以选择适合自己的方案.至于上述的方案,第一种简单直接,符合人类思维方式,上传的文件组织的很有规律,比较方便整理;第二种则更加符合计算机思维,对于上传量很大,又没有什么必要管理的应用,也是很好的选择.