/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.util; import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.text.DecimalFormat; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 以易读的方式来解析和显示字节数。 * * @author Michael Zhou */ public class HumanReadableSize { private final static Long ONE = 1L; private final static Long ONE_KILO = 1024L; private final static Long ONE_MEGA = 1024 * 1024L; private final static Long ONE_GIGA = 1024 * 1024 * 1024L; private final static Long ONE_TERA = 1024 * 1024 * 1024 * 1024L; private final static Map<String, Long> UNIT_NAMES = createHashMap(); private final static Pattern REGEXP = Pattern.compile("(\\d+(\\.\\d+)?)\\s*(K|M|G|T)?", Pattern.CASE_INSENSITIVE); static { UNIT_NAMES.put("B", ONE); UNIT_NAMES.put("K", ONE_KILO); UNIT_NAMES.put("M", ONE_MEGA); UNIT_NAMES.put("G", ONE_GIGA); UNIT_NAMES.put("T", ONE_TERA); } /** * 将易读的字节数转换成真实字节数。 * <ul> * <li><code>1</code> 转换成 <code>1</code>。</li> * <li><code>1K</code> 转换成 <code>1024</code>。</li> * <li><code>1M</code> 转换成 <code>1048576</code>。</li> * <li><code>1G</code> 转换成 <code>1073741824</code>。</li> * <li><code>1T</code> 转换成 <code>1099511627776</code>。</li> * <li>支持小数点,例如:<code>1.5K</code>。</li> * </ul> */ public static long parse(String humanReadbleSize) { return parse(humanReadbleSize, (String[]) null); } private static long parse(String humanReadbleSize, String... nas) { humanReadbleSize = assertNotNull(trimToNull(humanReadbleSize), "human readble size"); if (nas != null) { for (String na : nas) { if (na != null && na.equalsIgnoreCase(humanReadbleSize)) { return -1; } } } Matcher matcher = REGEXP.matcher(humanReadbleSize); assertTrue(matcher.matches(), "wrong format: %s", humanReadbleSize); double size = Double.parseDouble(matcher.group(1)); String unit = trimToNull(matcher.group(3)); if (unit != null) { size *= UNIT_NAMES.get(unit.toUpperCase()); } return (long) size; } /** * 将字节数取整,并转换成易读的概要字节数。 * <ul> * <li><code>1</code>转换成<code>1</code>。</li> * <li><code>1024</code>转换成<code>1K</code>。</li> * <li><code>1048576</code>转换成<code>1M</code>。</li> * <li><code>1073741824</code>转换成<code>1G</code>。</li> * <li><code>1099511627776</code>转换成<code>1T</code>。</li> * <li>小于<code>0</code>的一律转换成<code>n/a</code>。</li> * </ul> */ public static String toHumanReadble(long size) { if (size < 0) { return "n/a"; } DecimalFormat format = new DecimalFormat("#.##"); if (size / ONE_TERA > 0) { return format.format((double) size / ONE_TERA) + "T"; } if (size / ONE_GIGA > 0) { return format.format((double) size / ONE_GIGA) + "G"; } if (size / ONE_MEGA > 0) { return format.format((double) size / ONE_MEGA) + "M"; } if (size / ONE_KILO > 0) { return format.format((double) size / ONE_KILO) + "K"; } return String.valueOf(size); } private final long value; private final String humanReadable; public HumanReadableSize(String humanReadable) { this.value = parse(humanReadable, "-1", "n/a"); this.humanReadable = toHumanReadble(this.value); } public HumanReadableSize(long value) { this.value = value < 0 ? -1 : value; this.humanReadable = toHumanReadble(this.value); } public long getValue() { return value; } public String getHumanReadable() { return humanReadable; } @Override public int hashCode() { return 31 + (int) (value ^ value >>> 32); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof HumanReadableSize) { return value == ((HumanReadableSize) obj).value; } return false; } @Override public String toString() { return humanReadable; } }