6

ファイルオブジェクトで.length()を呼び出すと、2GBを超えるファイルは誤った値を返します。

これは、Tomcatコンテナで実行されているWebアプリケーションで発生しています。

たとえば、Windowsが2,083,344,714バイトとして報告するファイルは、Javaから1889761088として返されます。

環境の詳細は次のとおりです。

  • jdk 1.6.0_24(64ビット)
  • Java JotSpot(TM)64ビットサーバーVM(ビルド17.0-b17、混合モード)
  • Tomcat 6.0.29
  • Windows Server 2008 r2

そのため、すぐに32ビットVMに関係があるのではないかと思いましたが、すべてが64ビットで実行されているようです。私は完全に困惑しています。問題が32モードで実行されているものに関連しているかどうかを確認するためのテストの開発に役立つだけであれば、どんな助けでも大歓迎です。

編集:

いくつかのコメントに答えるには:同じJVMを使用して非常に単純なテストケースを実行すると(file.lengthを出力するだけ)、正しい値が得られます:2,083,344,714。

私はこれがうまくいくはずだとかなり確信しています、私はちょうど私のtomcat構成/java構成/アプリケーションについて何かが私に苦労しているように感じています。特定のサイズを超えるファイルにのみ影響しているという事実は、実際には32ビットと64ビットの問題のように見えますが、私が知る限り、すべてが64ビットです。

編集2:これはほとんど不可能であると疑うようになり、ファイルが完全にコピーされる前にスレッドがファイルの長さを取得するという問題が発生する可能性があります。誰かが気になったら、私がそれを理解したときにここに投稿します:-)

4

1 に答える 1

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;

        }
    }
}
于 2012-10-12T00:19:19.377 に答える