File.length()在Java中返回不正确的值

时间:2012-10-11 23:48:42

标签: java file

在文件对象上调用.length()时,超过2 GB的文件会返回不正确的值。

这是在tomcat容器中运行的Web应用程序中发生的。

例如,Windows报告为2,083,344,714字节的文件将从java返回为1887961088。

以下是环境细节:

  • jdk 1.6.0_24(64位)
  • Java JotSpot(TM)64位服务器VM(版本17.0-b17,混合模式)
  • Tomcat 6.0.29
  • Windows Server 2008 r2

所以我立即怀疑与32位虚拟机有关,但一切似乎都是以64位运行。我完全难过,任何帮助将不胜感激,如果只是帮助开发一些测试,看看问题是否与32模式运行的东西有关..

编辑:

回答一些意见: 当我使用相同的JVM(只输出file.length)运行一个非常简单的测试用例时,我得到了正确的值:2,083,344,714。

我非常有信心这个应该工作,我只是觉得我的tomcat配置/ java配置/应用程序让我很难过。它只影响超过一定大小的文件的事实真的让它看起来像32位对64位的问题,但据我所知,一切都是64位。

编辑2:开始怀疑这几乎是不可能的,并且我可能会遇到一个线程在完全复制之前获取文件长度的问题。如果有人关心的话,我会在这里发布,如果有人关心: - )

1 个答案:

答案 0 :(得分:5)

似乎对我工作正常......

Windows 7 x64上的

pagefile.sys,由DOS报告为8446545920字节

Java 7.0_02 x32 8446545920 / 7.87 gb

Java 1.6_30 x32 8446545920 / 7.87 gb

import java.io.File;
import java.text.NumberFormat;

public class TestFileSize {

    public static void main(String[] args) {
        File test1 = new File("C:/pagefile.sys");
        File test2 = new File("C:/hiberfil.sys");

        System.out.println(test1.length() + " / " + ByteFormatter.format(test1.length()));
        System.out.println(test2.length() + " / " + ByteFormatter.format(test2.length()));

    }

    public static class ByteFormatter {

        public static final long KILO_BYTES = 1024;
        public static final long MEGA_BYTES = 1024 * KILO_BYTES;
        public static final long GIGA_BYTES = 1024 * MEGA_BYTES;
        public static final long TERA_BYTES = 1024 * GIGA_BYTES;
        public enum Format {

            TeraBytes(TERA_BYTES),
            GigaBytes(GIGA_BYTES),
            MegaBytes(MEGA_BYTES),
            KiloBytes(KILO_BYTES);
            private long multiplier;

            private Format(long multiplier) {
                this.multiplier = multiplier;
            }

            public long getMultiplier() {
                return multiplier;
            }
        }

        public static String format(long bytes) {
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMaximumFractionDigits(2);
            nf.setMinimumFractionDigits(0);
            String format = bytes + " bytes";
            if (bytes / TERA_BYTES > 0) {
                format = nf.format((double) bytes / TERA_BYTES) + " tb";
            } else if (bytes / GIGA_BYTES > 0) {
                format = nf.format((double) bytes / GIGA_BYTES) + " gb";
            } else if (bytes / MEGA_BYTES > 0) {
                format = nf.format((double) bytes / MEGA_BYTES) + " mb";
            } else if (bytes / KILO_BYTES > 0) {
                format = nf.format((double) bytes / KILO_BYTES) + " kb";
            } else {
                format = nf.format(bytes) + " bytes";
            }

            return format;
        }

        public static String formatMegaBytes(long lMegaBytes) {

            return format((long) ((double) lMegaBytes * MEGA_BYTES));

        }

        public static String formatKiloBytes(long kbytes) {

            return format(kbytes * KILO_BYTES);

        }

        public static String formatGigaBytes(long gbytes) {

            return format(gbytes * GIGA_BYTES);

        }

        public static String formatTeraBytes(long gbytes) {

            return format(gbytes * TERA_BYTES);

        }

        public static long toBytes(String value, Format format) {

            long multipler = format.getMultiplier();

            long bytes = (long) (Double.parseDouble(value.trim()) * multipler);

            return bytes;

        }

        public static long toBytes(String sValue) {

            long lBytes = 0;

            if (sValue.indexOf(" ") > -1) {

                String sElements[] = sValue.split(" ");

                lBytes = Long.parseLong(sElements[0]);

                if (sElements[1].toLowerCase().startsWith("gb")) {

                    lBytes *= GIGA_BYTES;

                } else if (sElements[1].toLowerCase().startsWith("mb")) {

                    lBytes *= MEGA_BYTES;

                } else if (sElements[1].toLowerCase().startsWith("kb")) {

                    lBytes *= KILO_BYTES;

                }

            } else {

                sValue = sValue.trim();
                long lMultiplier = 1;
                String sBytes = null;

                if (sValue.toLowerCase().endsWith("gb")) {

                    sBytes = sValue.substring(0, sValue.toLowerCase().indexOf("gb"));
                    lMultiplier = GIGA_BYTES;

                } else if (sValue.toLowerCase().endsWith("mb")) {

                    sBytes = sValue.substring(0, sValue.toLowerCase().indexOf("mb"));
                    lMultiplier = MEGA_BYTES;

                } else if (sValue.toLowerCase().endsWith("kb")) {

                    sBytes = sValue.substring(0, sValue.toLowerCase().indexOf("kb"));
                    lMultiplier = KILO_BYTES;

                }

                lBytes = Long.parseLong(sBytes);

                lBytes *= lMultiplier;

            }

            return lBytes;

        }
    }
}