# فناوری جاوا > برنامه‌نویسی جاوا > Java SE : نگارش استاندارد جاوا >  گرفتن داده از کاربر

## Hengameh.Hoseini

سلام. 
(من تقریبا تازه جاوا خوندن رو شروع کردم)

اکثر برنامه های جاوایی که روی اینترنت هست, به جای اسکنر از 
Input Stream Reader و Buffered Reader 
برای گرفتن ورودی از کاربر استفاده کردن

مثلا این برنامه:
http://www.java-examples.com/calcula...g-java-example

می دونم که روش اسکنر, روش جدید هست؛ و این که می دونم روش های دیگه هم برای گرفتن ورودی از کاربر هست. 
خواستم بدونم بین برنامه نویس های حرفه ای, بین این دو تا روش, کدوم رایج تر و مقبول تره؟

----------


## ahmad.mo74

سلام

روش های مختلفی برای گرفتن ورودی از کاربر هست از جمله همین هایی که نام بردید. اما اینکه از کدوم و در چه شرایطی استفاده کنید بستگی به شما و نیازتون داره.

مثلا اگر میخواید بر روی ورودی ای که کاربر میده بیشترین کنترل رو داشته باشید و مثلا ورودی رو tokenize کنید یا از regex استفاده کنید و ... یا اینکه راحت از ورودی عدد بخونید و ... بهتره از Scanner استفاده کنید. در کل Scanner امکانات زیادی داره.

اما اگر میخواید از ورودی فقط String بخونید (به صورت خط به خط) و کاری به مسائل دیگه مثل خوندن عدد و ... ندارید، BufferedReader گزنیه مناسبیه (این به این معنی نیست که با BufferedReader نشه عدد خوند) . مزایای استفاده از BufferedReader اینه که این کلاس کار خوندن از ورودی رو به صرفه تر انجام میده (بخاطر وجود buffer) و همچنین thread-safe هست.

این کلاس ها تنها برای خوندن ورودی از کنسول نیستند و تقریبا برای هر نوع ورودی ای مثل فایل، سوکت، ... میشه ازشون استفاده کرد.

اگر میخواید هم از مزایای BufferedReader بهره ببرید و هم از امکانات فراوان Scanner استفاده کنید، میتونید BufferedReader رو به عنوان source به Scanner بدید تا Scanner بتونه ورودی رو از طریق BufferedReader بخونه.

یعنی :


Scanner scanner = new Scanner(new BufferedReader(new InputStreamReader(System.in)));


روش های دیگه ای که برای خوندن از کنسول میشه ازشون استفاده کرد، مثل Console و حتی خود System.in که ساده ترین روش هست.

کلاس Console همیشه در دسترس نیست (مثلا تو eclipse) و بهتره موقعی که برنامتون رو از طریق cmd یا terminal اجرا میکنید ازش استفاده کنید.
ویژگی خوبی که Console داره امکان خوندن password از کنسول هست :


Console console = System.console();
console.readPassword();


در مورد System.in هم که یه InputStream هست و فقط میشه باهاش آرایه ای از byte خوند. مثلا :


public static void main(String[] args) throws IOException {
    byte[] bytes = new byte[48];
    System.in.read(bytes);
    System.out.println(new String(bytes));
}


در نهایت من یه تست از Scanner و BufferedReader گرفتم (از فایل برای ورودی استفاده کردم) و به نظر میاد BufferedReader سرعت بیشتری داره :


import java.io.*;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;


/**
 * @author avb
 */
public class Test {


    public static void main(String[] args) {
        int it = 10000;
        String fileName = "D:\\test.txt";
        double bufferedReaderAvg, scannerAvg;


        warmUp(it, fileName);
        System.out.println();


        double linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileInputStream fileInputStream = new FileInputStream(name);
                 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
                while (bufferedReader.readLine() != null) {
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("BufferedReader + InputStreamReader + FileInputStream -> " + linesPerSec + " (line / sec)");
        bufferedReaderAvg = linesPerSec;


        linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileReader fileReader = new FileReader(name);
                 BufferedReader bufferedReader = new BufferedReader(fileReader)) {
                while (bufferedReader.readLine() != null) {
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("BufferedReader + FileReader -> " + linesPerSec + " (line / sec)");
        bufferedReaderAvg += linesPerSec;


        linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileInputStream fileInputStream = new FileInputStream(name);
                 Scanner scanner = new Scanner(fileInputStream)) {
                while (scanner.hasNextLine()) {
                    scanner.nextLine();
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("Scanner + FileInputStream -> " + linesPerSec + " (line / sec)");
        scannerAvg = linesPerSec;


        linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileReader fileReader = new FileReader(name);
                 Scanner scanner = new Scanner(fileReader)) {
                while (scanner.hasNextLine()) {
                    scanner.nextLine();
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("Scanner + FileReader -> " + linesPerSec + " (line / sec)");
        scannerAvg += linesPerSec;


        linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileInputStream fileInputStream = new FileInputStream(name);
                 BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
                 Scanner scanner = new Scanner(bufferedInputStream)) {
                while (scanner.hasNextLine()) {
                    scanner.nextLine();
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("Scanner + BufferedInputStream + FileInputStream -> " + linesPerSec + " (line / sec)");
        scannerAvg += linesPerSec;


        linesPerSec = testReadLinesPerSec(it, fileName, name -> {
            int lines = 0;
            try (FileInputStream fileInputStream = new FileInputStream(name);
                 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                 Scanner scanner = new Scanner(bufferedReader)) {
                while (scanner.hasNextLine()) {
                    scanner.nextLine();
                    lines++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        });


        System.out.println("Scanner + BufferedReader + InputStreamReader + FileInputStream -> " + linesPerSec + " (line / sec)");
        scannerAvg += linesPerSec;


        System.out.println();
        System.out.println("Scanner Average Read Lines Per Second : " + (scannerAvg / 4));
        System.out.println("BufferedReader Average Read Lines Per Second : " + (bufferedReaderAvg / 2));
    }


    interface ReadRunnable {


        int readLines(String fileName);


    }


    private static void warmUp(int iteration, String fileName) {
        ReadRunnable runnable = name -> {
            try (FileInputStream fileInputStream = new FileInputStream(name)) {
                byte[] bytes = new byte[2048];
                while (true) {
                    if (fileInputStream.read(bytes) == -1) {
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return 0;
        };
        long start = System.currentTimeMillis();
        for (int i = 0; i < iteration; i++) {
            runnable.readLines(fileName);
        }
        System.out.println("Warm Up : " + (System.currentTimeMillis() - start) + " ms");
    }


    static double testReadLinesPerSec(int iteration, String fileName, ReadRunnable runnable) {
        long lines = 0, start = System.nanoTime();
        for (int i = 0; i < iteration; i++) {
            lines += runnable.readLines(fileName);
        }
        return lines * TimeUnit.SECONDS.toNanos(1) / (double) (System.nanoTime() - start);
    }


}


خروجی تست :


Warm Up : 1166 ms


BufferedReader + InputStreamReader + FileInputStream -> 1615903.5373240712 (line / sec)
BufferedReader + FileReader -> 1821731.489591279 (line / sec)
Scanner + FileInputStream -> 151491.21943727555 (line / sec)
Scanner + FileReader -> 151759.5795178512 (line / sec)
Scanner + BufferedInputStream + FileInputStream -> 151546.38366343756 (line / sec)
Scanner + BufferedReader + InputStreamReader + FileInputStream -> 151157.6425589665 (line / sec)


Scanner Average Read Lines Per Second : 151488.70629438272
BufferedReader Average Read Lines Per Second : 1718817.513457675

----------

