java รับขนาดไฟล์ได้อย่างมีประสิทธิภาพ


166

ในขณะที่ googling ฉันเห็นว่าการใช้java.io.File#length()อาจช้า FileChannelมีsize()วิธีการที่ใช้ได้เช่นกัน

มีวิธีที่มีประสิทธิภาพใน java เพื่อให้ได้ขนาดไฟล์หรือไม่


7
คุณสามารถให้ลิงค์ที่บอกว่า File.length () "สามารถช้า" ได้หรือไม่?
matt b

1
ขออภัยนี่คือลิงค์javaperformancetuning.com/tips/rawtips.shtml ค้นหา "ข้อมูลไฟล์เช่น File.length () ต้องใช้การเรียกของระบบและอาจช้า" มันเป็นคำสั่งที่สับสนจริงๆดูเหมือนว่าเกือบจะคิดว่ามันจะเป็นการเรียกของระบบ
joshjdevl

25
การรับความยาวไฟล์จะต้องมีการเรียกของระบบไม่ว่าคุณจะทำอย่างไร อาจช้าถ้าใช้ผ่านเครือข่ายหรือระบบไฟล์ช้าอื่น ๆ ไม่มีวิธีที่เร็วกว่าที่จะได้รับมากกว่า File.length () และคำจำกัดความของ "ช้า" ที่นี่เพียงหมายความว่าอย่าโทรไปโดยไม่จำเป็น
jsight

ฉันคิดว่านั่นคือสิ่งที่ GHad พยายามทดสอบด้านล่าง ผลลัพธ์ของฉันคือ (ใน ubuntu 8.04): มีเพียงหนึ่ง URL ที่เข้าถึงได้เร็วที่สุด วิ่ง 5 ครั้ง 50 ครั้ง CHANNEL ทำให้สับสนเร็วที่สุด? :) สำหรับจุดประสงค์ของฉันฉันจะทำการเข้าถึงเพียงครั้งเดียว แม้ว่ามันจะแปลก ว่าเราได้ผลลัพธ์ที่แตกต่าง
joshjdevl

1
การดำเนินการนี้อาจช้ามากหากข้อมูลอยู่บนดิสก์มากกว่าในแคช (เช่น 1000x ช้าลง) แต่มีเล็ก ๆ น้อย ๆ ที่คุณสามารถทำได้เกี่ยวกับเรื่องนี้อื่น ๆ นอกเหนือจากการสร้างความมั่นใจข้อมูลที่คุณต้องการอยู่เสมอในแคช (เช่นโหลดก่อนมันและมีหน่วยความจำเพียงพอดังนั้นจึงยังคงอยู่ในหน่วยความจำ)
ปีเตอร์ Lawrey

คำตอบ:


102

ฉันพยายามวัดด้วยรหัสด้านล่าง:

สำหรับการวิ่ง = 1 และการวนซ้ำ = 1 วิธี URL นั้นเร็วที่สุดตามด้วยช่อง ฉันเรียกใช้สิ่งนี้ด้วยความหยุดชั่วคราวประมาณ 10 ครั้ง ดังนั้นสำหรับการเข้าถึงครั้งเดียวการใช้ URL เป็นวิธีที่เร็วที่สุดที่ฉันนึกได้:

LENGTH sum: 10626, per Iteration: 10626.0

CHANNEL sum: 5535, per Iteration: 5535.0

URL sum: 660, per Iteration: 660.0

สำหรับการวิ่ง = 5 และการวนซ้ำ = 50 ภาพจะแตกต่างกัน

LENGTH sum: 39496, per Iteration: 157.984

CHANNEL sum: 74261, per Iteration: 297.044

URL sum: 95534, per Iteration: 382.136

ไฟล์จะต้องทำการแคชการเรียกไปยังระบบไฟล์ขณะที่แชนเนลและ URL มีค่าใช้จ่าย

รหัส:

import java.io.*;
import java.net.*;
import java.util.*;

public enum FileSizeBench {

    LENGTH {
        @Override
        public long getResult() throws Exception {
            File me = new File(FileSizeBench.class.getResource(
                    "FileSizeBench.class").getFile());
            return me.length();
        }
    },
    CHANNEL {
        @Override
        public long getResult() throws Exception {
            FileInputStream fis = null;
            try {
                File me = new File(FileSizeBench.class.getResource(
                        "FileSizeBench.class").getFile());
                fis = new FileInputStream(me);
                return fis.getChannel().size();
            } finally {
                fis.close();
            }
        }
    },
    URL {
        @Override
        public long getResult() throws Exception {
            InputStream stream = null;
            try {
                URL url = FileSizeBench.class
                        .getResource("FileSizeBench.class");
                stream = url.openStream();
                return stream.available();
            } finally {
                stream.close();
            }
        }
    };

    public abstract long getResult() throws Exception;

    public static void main(String[] args) throws Exception {
        int runs = 5;
        int iterations = 50;

        EnumMap<FileSizeBench, Long> durations = new EnumMap<FileSizeBench, Long>(FileSizeBench.class);

        for (int i = 0; i < runs; i++) {
            for (FileSizeBench test : values()) {
                if (!durations.containsKey(test)) {
                    durations.put(test, 0l);
                }
                long duration = testNow(test, iterations);
                durations.put(test, durations.get(test) + duration);
                // System.out.println(test + " took: " + duration + ", per iteration: " + ((double)duration / (double)iterations));
            }
        }

        for (Map.Entry<FileSizeBench, Long> entry : durations.entrySet()) {
            System.out.println();
            System.out.println(entry.getKey() + " sum: " + entry.getValue() + ", per Iteration: " + ((double)entry.getValue() / (double)(runs * iterations)));
        }

    }

    private static long testNow(FileSizeBench test, int iterations)
            throws Exception {
        long result = -1;
        long before = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            if (result == -1) {
                result = test.getResult();
                //System.out.println(result);
            } else if ((result = test.getResult()) != result) {
                 throw new Exception("variance detected!");
             }
        }
        return (System.nanoTime() - before) / 1000;
    }

}

1
ดูเหมือนว่าวิธี URL เป็นวิธีที่ดีที่สุดในการเข้าถึงแบบครั้งเดียวไม่ว่าจะเป็น XP หรือ Linux Greetz GHad
GHad

73
stream.available()ไม่ส่งคืนความยาวของไฟล์ ส่งคืนจำนวนไบต์ที่สามารถอ่านได้โดยไม่ปิดกั้นสตรีมอื่น ไม่จำเป็นต้องมีจำนวนไบต์เท่ากับความยาวไฟล์ ในการรับความยาวจริงจากสตรีมคุณต้องอ่านจริงๆ(และนับจำนวนไบต์ที่อ่าน)
BalusC

11
มาตรฐานนี้หรือค่อนข้างตีความไม่ถูกต้อง ในการวนซ้ำต่ำการทดสอบในภายหลังใช้ประโยชน์จากการแคชไฟล์ของระบบปฏิบัติการ ในการทดสอบการวนซ้ำที่สูงกว่าการจัดอันดับนั้นถูกต้อง แต่ไม่ใช่เพราะ File.length () กำลังแคชบางอย่าง แต่เนื่องจากตัวเลือกอื่น ๆ 2 ตัวเลือกนั้นใช้วิธีการเดียวกัน แต่ทำงานพิเศษที่ทำให้ช้าลง
x4u

2
@ เปาโลการแคชและการเพิ่มประสิทธิภาพการเข้าถึงระบบไฟล์เป็นหนึ่งในความรับผิดชอบที่สำคัญของระบบปฏิบัติการ faqs.org/docs/linux_admin/buffer-cache.htmlเพื่อให้ได้ผลลัพธ์การเปรียบเทียบที่ดีควรทำการล้างแคชก่อนการรันแต่ละครั้ง
z0r

3
นอกเหนือจากสิ่งที่ javadoc สำหรับ InputStream.available () กล่าวว่าความจริงที่ว่าเมธอด available () ส่งคืนค่า int ควรเป็นค่าสถานะสีแดงกับวิธี URL ลองกับไฟล์ 3GB และจะเห็นได้ชัดว่าไม่ใช่วิธีที่ถูกต้องในการกำหนดความยาวของไฟล์
Scrubbie

32

มาตรฐานที่กำหนดโดย GHad วัดสิ่งอื่น ๆ อีกมากมาย (เช่นการสะท้อนการสร้างอินสแตนซ์วัตถุเป็นต้น) นอกเหนือจากการรับความยาว หากเราพยายามที่จะกำจัดสิ่งเหล่านี้ดังนั้นสำหรับการโทรครั้งหนึ่งฉันจะได้เวลาต่อไปนี้เป็นไมโครวินาที:

   ไฟล์รวม ___ 19.0 ต่อการย้ำ ___ 19.0
    raf sum ___ 16.0 ต่อ Iteration ___ 16.0 ต่อครั้ง
ช่อง sum__273.0 ต่อ Iteration__273.0

สำหรับ 100 รอบและ 10,000 รอบฉันได้รับ:

   ไฟล์ sum__1767629.0 ต่อ Iteration__1.7676290000000001
    raf sum ___ 881284.0 ต่อ Iteration__0.8812840000000001
ผลรวมของช่อง ___ 414286.0 ต่อ Iteration__0.414286

ฉันเรียกใช้รหัสที่แก้ไขแล้วต่อไปนี้ซึ่งให้ชื่ออาร์กิวเมนต์ของไฟล์ 100MB

import java.io.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;

public class FileSizeBench {

  private static File file;
  private static FileChannel channel;
  private static RandomAccessFile raf;

  public static void main(String[] args) throws Exception {
    int runs = 1;
    int iterations = 1;

    file = new File(args[0]);
    channel = new FileInputStream(args[0]).getChannel();
    raf = new RandomAccessFile(args[0], "r");

    HashMap<String, Double> times = new HashMap<String, Double>();
    times.put("file", 0.0);
    times.put("channel", 0.0);
    times.put("raf", 0.0);

    long start;
    for (int i = 0; i < runs; ++i) {
      long l = file.length();

      start = System.nanoTime();
      for (int j = 0; j < iterations; ++j)
        if (l != file.length()) throw new Exception();
      times.put("file", times.get("file") + System.nanoTime() - start);

      start = System.nanoTime();
      for (int j = 0; j < iterations; ++j)
        if (l != channel.size()) throw new Exception();
      times.put("channel", times.get("channel") + System.nanoTime() - start);

      start = System.nanoTime();
      for (int j = 0; j < iterations; ++j)
        if (l != raf.length()) throw new Exception();
      times.put("raf", times.get("raf") + System.nanoTime() - start);
    }
    for (Map.Entry<String, Double> entry : times.entrySet()) {
        System.out.println(
            entry.getKey() + " sum: " + 1e-3 * entry.getValue() +
            ", per Iteration: " + (1e-3 * entry.getValue() / runs / iterations));
    }
  }
}

3
จริง ๆ แล้วในขณะที่คุณพูดถูกต้องว่ามาตรการด้านอื่น ๆ ฉันควรชัดเจนยิ่งขึ้นในคำถามของฉัน ฉันกำลังมองหาขนาดไฟล์ของหลายไฟล์และฉันต้องการวิธีที่เร็วที่สุดที่เป็นไปได้ ดังนั้นผมจึงทำจริงๆจำเป็นต้องใช้ในการสร้างวัตถุบัญชีและค่าใช้จ่ายเนื่องจากว่าเป็นสถานการณ์จริง
joshjdevl

3
ใช้เวลาประมาณ 90% ในสิ่งที่ getResource ฉันสงสัยว่าคุณต้องใช้การสะท้อนเพื่อรับชื่อของไฟล์ที่มี Java bytecode บางส่วน

20

กรณีทดสอบทั้งหมดในโพสต์นี้มีข้อบกพร่องในขณะที่พวกเขาเข้าถึงไฟล์เดียวกันสำหรับแต่ละวิธีการทดสอบ ดังนั้นการแคชดิสก์จะทดสอบซึ่งประโยชน์จากการทดสอบที่ 2 และ 3 เพื่อพิสูจน์ประเด็นของฉันฉันได้ทำการทดสอบโดย GHAD และเปลี่ยนลำดับการแจงนับและด้านล่างเป็นผลลัพธ์

ดูผลลัพธ์ฉันคิดว่า File.length () เป็นผู้ชนะจริงๆ

ลำดับการทดสอบคือลำดับของเอาต์พุต คุณสามารถดูเวลาที่ใช้ในเครื่องของฉันแตกต่างกันระหว่างการประมวลผล แต่ File.Length () เมื่อไม่ใช่ครั้งแรกและการเข้าถึงดิสก์ครั้งแรกจะเกิดขึ้น

---
LENGTH sum: 1163351, per Iteration: 4653.404
CHANNEL sum: 1094598, per Iteration: 4378.392
URL sum: 739691, per Iteration: 2958.764

---
CHANNEL sum: 845804, per Iteration: 3383.216
URL sum: 531334, per Iteration: 2125.336
LENGTH sum: 318413, per Iteration: 1273.652

--- 
URL sum: 137368, per Iteration: 549.472
LENGTH sum: 18677, per Iteration: 74.708
CHANNEL sum: 142125, per Iteration: 568.5

9

เมื่อฉันแก้ไขรหัสของคุณเพื่อใช้ไฟล์ที่เข้าถึงได้โดยเส้นทางแบบสัมบูรณ์แทนที่จะเป็นทรัพยากรฉันจะได้รับผลลัพธ์ที่แตกต่างกัน (สำหรับการรัน 1 ครั้งการวนซ้ำ 1 ครั้งและการตี 100,000 ไฟล์ - ครั้งสำหรับไฟล์ 10 ไบต์เท่ากับ 100,000 ไบต์ )

ความยาวรวม: 33, ต่อการย้ำ: 33.0

จำนวนช่อง: 3626 ต่อการพูดซ้ำ: 3626.0

ผลรวม URL: 294 ต่อการพูดซ้ำ: 294.0


9

ในการตอบสนองต่อเกณฑ์มาตรฐานของ rgrig เวลาที่ใช้ในการเปิด / ปิดอินสแตนซ์ FileChannel & RandomAccessFile จะต้องนำมาพิจารณาด้วยเนื่องจากคลาสเหล่านี้จะเปิดสตรีมสำหรับอ่านไฟล์

หลังจากแก้ไขเกณฑ์มาตรฐานฉันได้ผลลัพธ์เหล่านี้เป็นเวลา 1 รอบในไฟล์ 85MB:

file totalTime: 48000 (48 us)
raf totalTime: 261000 (261 us)
channel totalTime: 7020000 (7 ms)

สำหรับ 10,000 การวนซ้ำในไฟล์เดียวกัน:

file totalTime: 80074000 (80 ms)
raf totalTime: 295417000 (295 ms)
channel totalTime: 368239000 (368 ms)

หากสิ่งที่คุณต้องการคือขนาดไฟล์ file.length () เป็นวิธีที่เร็วที่สุดที่จะทำ หากคุณวางแผนที่จะใช้ไฟล์เพื่อวัตถุประสงค์อื่นเช่นการอ่าน / เขียน RAF น่าจะเป็นทางออกที่ดีกว่า อย่าลืมปิดการเชื่อมต่อไฟล์ :-)

import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;

public class FileSizeBench
{    
    public static void main(String[] args) throws Exception
    {
        int iterations = 1;
        String fileEntry = args[0];

        Map<String, Long> times = new HashMap<String, Long>();
        times.put("file", 0L);
        times.put("channel", 0L);
        times.put("raf", 0L);

        long fileSize;
        long start;
        long end;
        File f1;
        FileChannel channel;
        RandomAccessFile raf;

        for (int i = 0; i < iterations; i++)
        {
            // file.length()
            start = System.nanoTime();
            f1 = new File(fileEntry);
            fileSize = f1.length();
            end = System.nanoTime();
            times.put("file", times.get("file") + end - start);

            // channel.size()
            start = System.nanoTime();
            channel = new FileInputStream(fileEntry).getChannel();
            fileSize = channel.size();
            channel.close();
            end = System.nanoTime();
            times.put("channel", times.get("channel") + end - start);

            // raf.length()
            start = System.nanoTime();
            raf = new RandomAccessFile(fileEntry, "r");
            fileSize = raf.length();
            raf.close();
            end = System.nanoTime();
            times.put("raf", times.get("raf") + end - start);
        }

        for (Map.Entry<String, Long> entry : times.entrySet()) {
            System.out.println(entry.getKey() + " totalTime: " + entry.getValue() + " (" + getTime(entry.getValue()) + ")");
        }
    }

    public static String getTime(Long timeTaken)
    {
        if (timeTaken < 1000) {
            return timeTaken + " ns";
        } else if (timeTaken < (1000*1000)) {
            return timeTaken/1000 + " us"; 
        } else {
            return timeTaken/(1000*1000) + " ms";
        } 
    }
}

8

ฉันพบปัญหาเดียวกันนี้ ฉันต้องการรับขนาดไฟล์และวันที่แก้ไขจำนวน 90,000 ไฟล์ในเครือข่ายที่ใช้ร่วมกัน การใช้จาวาและใช้วิธีที่ง่ายที่สุดเท่าที่จะเป็นไปได้มันจะใช้เวลานานมาก (ฉันจำเป็นต้องได้รับ URL จากไฟล์และพา ธ ของวัตถุด้วยเช่นกันดังนั้นมันจึงค่อนข้างหลากหลาย แต่มากกว่าหนึ่งชั่วโมง) จากนั้นฉันก็ใช้ Win32 ที่ปฏิบัติการได้แบบดั้งเดิมและทำงานเดียวกันเพียงแค่ทิ้งไฟล์ พา ธ การแก้ไขและขนาดไปยังคอนโซลและดำเนินการนั้นจาก Java ความเร็วนั้นยอดเยี่ยมมาก กระบวนการดั้งเดิมและการจัดการสตริงของฉันเพื่ออ่านข้อมูลสามารถประมวลผลได้มากกว่า 1,000 รายการต่อวินาที

ดังนั้นแม้ว่าผู้คนที่อยู่ในอันดับความคิดเห็นข้างต้นนี่เป็นวิธีแก้ปัญหาที่ถูกต้องและแก้ไขปัญหาของฉันได้ ในกรณีของฉันฉันรู้ว่าโฟลเดอร์ที่ฉันต้องการขนาดล่วงหน้าและฉันสามารถผ่านที่บรรทัดคำสั่งไปยังแอป win32 ของฉัน ฉันไปจากหลายชั่วโมงเพื่อประมวลผลไดเรกทอรีเป็นนาที

ปัญหาก็ดูเหมือนจะเฉพาะ Windows OS X ไม่มีปัญหาเดียวกันและสามารถเข้าถึงข้อมูลไฟล์เครือข่ายได้เร็วเท่าที่ระบบปฏิบัติการสามารถทำได้

การจัดการไฟล์ Java บน Windows นั้นแย่มาก การเข้าถึงดิสก์ในตัวเครื่องสำหรับไฟล์นั้นทำได้ดี มันเป็นเพียงการแชร์เครือข่ายที่ทำให้ประสิทธิภาพแย่ลง Windows สามารถรับข้อมูลเกี่ยวกับการแชร์เครือข่ายและคำนวณขนาดทั้งหมดภายในไม่กี่นาที

--Ben


3

Files.walkFileTreeหากคุณต้องการขนาดไฟล์หลายไฟล์ในไดเรกทอรีที่ใช้ คุณสามารถรับขนาดจากสิ่งBasicFileAttributesที่คุณจะได้รับ

นี้จะได้เร็วขึ้นมากแล้วโทร.length()ผลการใช้File.listFiles()หรือใช้ผลการFiles.size() Files.newDirectoryStream()ในกรณีทดสอบของฉันมันเร็วกว่าประมาณ 100 เท่า


FYI Files.walkFileTreeพร้อมใช้งานบน Android 26+
Joshua Pinter

2

ที่จริงฉันคิดว่า "ls" อาจเร็วกว่านี้ มีปัญหาบางอย่างใน Java ที่เกี่ยวข้องกับการรับข้อมูลไฟล์ น่าเสียดายที่ไม่มีวิธีการที่ปลอดภัยเทียบเท่ากับการเรียกใช้ซ้ำสำหรับ Windows (DIR / S ของ cmd.exe อาจสับสนและสร้างข้อผิดพลาดในลูปไม่สิ้นสุด)

ใน XP การเข้าถึงเซิร์ฟเวอร์บน LAN ใช้เวลา 5 วินาทีใน Windows เพื่อรับจำนวนไฟล์ในโฟลเดอร์ (33,000) และขนาดโดยรวม

เมื่อฉันทำซ้ำสิ่งนี้ซ้ำใน Java มันใช้เวลามากกว่า 5 นาที ฉันเริ่มวัดเวลาที่ใช้ในการทำ file.length (), file.lastModified () และ file.toURI () และสิ่งที่ฉันพบคือ 99% ของเวลาของฉันถูกเรียกโดยการโทร 3 ครั้งเหล่านั้น 3 สายที่ฉันต้องทำ ...

ความแตกต่างสำหรับไฟล์ 1,000 ไฟล์คือ 15ms ในเครื่องเทียบกับ 1800ms บนเซิร์ฟเวอร์ การสแกนพา ธ ของเซิร์ฟเวอร์ใน Java ช้าลงอย่างน่าขัน หากระบบปฏิบัติการดั้งเดิมสามารถสแกนโฟลเดอร์เดียวกันนั้นได้อย่างรวดเร็วทำไม Java จึงไม่สามารถทำได้

จากการทดสอบที่สมบูรณ์ยิ่งขึ้นฉันใช้ WineMerge บน XP เพื่อเปรียบเทียบวันที่แก้ไขและขนาดของไฟล์บนเซิร์ฟเวอร์กับไฟล์ในเครื่อง นี่เป็นการวนซ้ำทั้งแผนผังไดเรกทอรีทั้งหมด 33,000 ไฟล์ในแต่ละโฟลเดอร์ เวลาทั้งหมด 7 วินาที java: มากกว่า 5 นาที

ดังนั้นข้อความและคำถามดั้งเดิมจาก OP จึงเป็นจริงและถูกต้อง มันน้อยลงอย่างเห็นได้ชัดเมื่อจัดการกับระบบไฟล์ในท้องถิ่น การเปรียบเทียบโฟลเดอร์ในเครื่องกับรายการ 33,000 รายการใช้เวลา 3 วินาทีใน WinMerge และใช้เวลา 32 วินาทีในเครื่องใน Java ดังนั้นอีกครั้ง java กับ native คือการชะลอตัว 10 เท่าในการทดสอบพื้นฐานเหล่านี้

Java 1.6.0_22 (ล่าสุด), Gigabit LAN และการเชื่อมต่อเครือข่าย ping น้อยกว่า 1 มิลลิวินาที (ทั้งคู่ในสวิตช์เดียวกัน)

Java ช้า


2
นี่ก็ดูเหมือนจะเป็นระบบปฏิบัติการที่เฉพาะเจาะจง การทำแอพพลิเคชั่นจาวาเดียวกันหลังจากโฟลเดอร์เดียวกันจาก OS X โดยใช้แซมบ้าใช้เวลา 26 วินาทีในการแสดงรายการขนาดและวันที่ทั้งหมด 33,000 รายการ ดังนั้นเครือข่าย Java เป็นเพียงช้าใน Windows แล้ว? (OS X คือ java 1.6.0_22 เช่นกัน)
Ben Spink

2

จากมาตรฐานของ GHad มีคนพูดถึงสองสามประเด็น:

1> Like BalusC ที่กล่าวถึง: stream.available () ถูกไหลในกรณีนี้

เนื่องจาก available () ส่งคืนการประมาณจำนวนไบต์ที่สามารถอ่าน (หรือข้าม) จากสตรีมอินพุตนี้โดยไม่ปิดกั้นโดยการเรียกใช้เมธอดถัดไปสำหรับสตรีมอินพุตนี้

ดังนั้นก่อนที่จะลบ URL วิธีนี้

2> ดังที่ StuartH กล่าวถึง - ลำดับการทดสอบการทำงานสร้างความแตกต่างของแคชดังนั้นจึงทำการทดสอบโดยแยกการทดสอบออกจากกัน


ตอนนี้เริ่มทดสอบ:

เมื่อ CHANNEL ทำงานเพียงอย่างเดียว:

CHANNEL sum: 59691, per Iteration: 238.764

เมื่อ LENGTH หนึ่งรันเพียงอย่างเดียว:

LENGTH sum: 48268, per Iteration: 193.072

ดังนั้นดูเหมือนว่า LENGTH คนหนึ่งจะเป็นผู้ชนะที่นี่:

@Override
public long getResult() throws Exception {
    File me = new File(FileSizeBench.class.getResource(
            "FileSizeBench.class").getFile());
    return me.length();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.