在文件对象上调用.length()时,超过2 GB的文件会返回不正确的值。
这是在tomcat容器中运行的Web应用程序中发生的。
例如,Windows报告为2,083,344,714字节的文件将从java返回为1887961088。
以下是环境细节:
所以我立即怀疑与32位虚拟机有关,但一切似乎都是以64位运行。我完全难过,任何帮助将不胜感激,如果只是帮助开发一些测试,看看问题是否与32模式运行的东西有关..
编辑:
回答一些意见: 当我使用相同的JVM(只输出file.length)运行一个非常简单的测试用例时,我得到了正确的值:2,083,344,714。
我非常有信心这个应该工作,我只是觉得我的tomcat配置/ java配置/应用程序让我很难过。它只影响超过一定大小的文件的事实真的让它看起来像32位对64位的问题,但据我所知,一切都是64位。
编辑2:开始怀疑这几乎是不可能的,并且我可能会遇到一个线程在完全复制之前获取文件长度的问题。如果有人关心的话,我会在这里发布,如果有人关心: - )
答案 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;
}
}
}