File.length () returns invalid value in Java

When .length () is called in a file object, files larger than 2 GB return an invalid value.

This happens in a web application running in a tomcat container.

For example, the file that reports Windows requests is 2083 344 714 bytes returned from java as 1887961088.

Here are the environmental details:

  • jdk 1.6.0_24 (64 bit)
  • Java JotSpot (TM) 64-bit server VM (build 17.0-b17, mixed mode)
  • Tomcat 6.0.29
  • Windows Server 2008 r2

Therefore, I immediately suspected something that was connected with a 32-bit virtual machine, but everything worked on 64 bits. I am completely shocked that any help would be greatly appreciated if it only helped to develop some tests to see if the problem is related to something running in 32nd mode.

EDIT:

To answer some comments: When I run a really simple test case using the same JVM (only output file.length), I get the correct value: 2,083,344,714.

I am pretty sure this should work, I just feel that something about my tomcat configuration / java configuration / application makes my time difficult. The fact that it only affects files with a certain size really makes it seem like a problem with 32-bit and 64-bit, but as far as I can tell, it's all 64 bits.

EDIT 2: start to suspect that this is pretty much impossible, and I might have a problem with a stream occupying the length of the file before it is completely copied. I will send here when I find out if someone cares :-)

+6
source share
1 answer

Everything seems to be fine for me ...

pagefile.sys on Windows 7 x64 reported by DOS as 8446545920 bytes

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; } } } 
+5
source

Source: https://habr.com/ru/post/927516/


All Articles