کلاس InputStreamReader

در آموزش های قبلی با کلاس های انتزاعی Reader و InputStream آشنا شدیم ، کلاس InputStreamReader به عنوان واسط بین این دو کلاس عمل می کند ، این کلاس داده ها را به صورت جریان بایتی از ورودی میخواند و بر اساس یک charset مشخص آن ها را به جریان کاراکتری تبدیل می کند ، مهم ترین کاربرد این کلاس استفاده از آن در کاربرد های شبکه است بدین صورت که اطلاعات به صورت جریان بایتی از شبکه خوانده می شوند و سپس به جریان متنی تبدیل می شوند. از این کلاس می توان برای خواندن از فایل ، خواندن از وروردی سیستم (کنسول) و یا خواندن از یک حافظه بافر نیز استفاده کرد. برای استفاده از این کلاس باید از یکی از سازنده های زیر برای ساخت شی جدید از آن استفاده کنیم :

InputStreamReader(InputStream in)
InputStreamReader(InputStream in,Charset cs)
InputStreamReader(InputStream in,String charsetName)

متد های پر کاربرد InputStreamReader در جدول زیر آمده است:

متد کاربرد
close () جریان ورودی را بسته و منابع استفاده شده را آزاد می کند
read() یک کاراکتر از جریان ورودی خوانده و آن را به صورت یک int بر می گرداند ، در صورتی که به انتهای جریان ورودی رسیده باشیم خروجی این متد مقدار 1- خواهد بود.
read(char [] cbuf,int offset,int length) کاراکتر ها را از جریان ورودی خوانده و در آرایه cbuf ذخیره می کند و تعداد کاراکتر های خوانده شده را بر می گرداند ، در صورتی که کاراکتری برای خواندن وجود نداشته باشد خروجی این متد مقدار 1- خواهد بود.

  • cbuf :آرایه ای است که کاراکتر ها در آن بافر می شوند
  • offset : اندیس شروع نوشتن در آرایه مورد نظر
  • length : حداکثر کاراکتر هایی که باید خوانده شوند
ready () مشخص می کند که قادر به خواندن از جریان ورودی هستیم یا خیر، خروجی این متد به صورت true یا false است.

خواندن از فایل با متد read

در مثال زیر با استفاده از متد read محتوی یک فایل متنی را کاراکتر به کاراکتر خوانده و چاپ می کنیم.

import java.io.*;

public class InputStreamReaderDemo
{
    public InputStreamReaderDemo()
    {
        File myFile = new File("C:/Test.txt");
        InputStreamReader inputstreamreader = null;
        FileInputStream fileinputstream = null;
        try
        {
            fileinputstream = new FileInputStream(myFile);

            inputstreamreader = new InputStreamReader(fileinputstream);

            int c;
            while ((c = inputstreamreader.read()) != -1)
            {
                System.out.print((char)c);
            }

        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                inputstreamreader.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)
    {
        new InputStreamReaderDemo();
    }
}

همانطور که در کد بالا مشاهده می کنید ابتدا باید فایلی که قصد خواندن از آن داریم را با یک شی از کلاس File مشخص کنیم (شی myFile در مثال بالا) سپس با استفاده از FileInputStream فایل مورد نظر را به یک جریان بایتی تبدیل کنیم (شی fileinputstream در مثال بالا) و در آخرین مرحله از تبدیلات، جریان بایتی را با استفاده از InputStreamReader به جریان متنی تبدیل می کنیم (شی inputstreamreader در مثال بالا). در ادامه با استفاده از متد read کاراکتر به کاراکتر از inputstreamreader میخوانیم و تا زمانی که نتیجه فراخوانی این متد -1 نباشد آن را در خروجی چاپ می کنیم. از آنجایی که ممکن است فایل وجود نداشته باشد یا در هنگام عملیات خواندن با خطای پیش بینی نشده مواجه شویم باید حتماً از بلوک try-catch برای به دام انداختن خطا ها استفاده کنیم.

خواندن از فایل با کمک یک آرایه

همانطور که در ابتدا دیدیم متد read دیگری نیز وجود دارد که از یک آرایه بافر برای خواندن از جریان ورودی استفاده می کند، در بسیاری از کاربرد ها خواندن کاراکتر به کاراکتر زمان بر بوده و بهتر است با استفاده از یک آرایه بافر عملیات خواندن را تسریع بخشیم. مثال زیر به شرح این موضوع می پردازد :

import java.io.*;

public class InputStreamReaderDemo
{
    public InputStreamReaderDemo()
    {
        File myFile = new File("C:/Test.txt");
        InputStreamReader inputstreamreader = null;
        FileInputStream fileinputstream = null;

        char charbuffer[] = new char[200];
        int readed;
        try
        {
            fileinputstream = new FileInputStream(myFile);

            inputstreamreader = new InputStreamReader(fileinputstream);

            readed = inputstreamreader.read(charbuffer, 0, charbuffer.length);

            for (int i = 0; i < readed; i++)
            {
                System.out.print(charbuffer[i]);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                inputstreamreader.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)
    {
        new InputStreamReaderDemo();
    }
}

متغیر readed تعداد کاراکتر های خوانده شده از فایل را مشخص می کند.

خواندن از ورودی سیستم (کنسول)

خواندن از ورودی سیستم مشابه خواندن از فایل است با این تفاوت که در این حالت دیگری نیازی به FileInputStream نداریم و با استفاده از System.in مستقیماً از ورودی سیستم می خوانیم. مثال زیر متنی را که کاربر در ورودی سیستم تایپ می کند (و در پایان کلید اینتر را می زند) در خروجی استاندارد چاپ می کند.

import java.io.*;

public class InputStreamReaderDemo
{
    public InputStreamReaderDemo()
    {
        InputStreamReader inputstreamreader = null;

        char charbuffer[] = new char[200];
        int readed;
        try
        {
            inputstreamreader = new InputStreamReader(System.in);

            readed = inputstreamreader.read(charbuffer, 0, charbuffer.length);

            for (int i = 0; i < readed; i++)
            {
                System.out.print(charbuffer[i]);
            }

        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                inputstreamreader.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)
    {
        new InputStreamReaderDemo();
    }
}

خواندن از یک حافظه بافر

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

import java.io.*;

public class InputStreamReaderDemo
{
    public InputStreamReaderDemo()
    {
        String test = "Test String!";

        byte[] memoryBuffer = test.getBytes();

        InputStreamReader inputstreamreader = null;
        ByteArrayInputStream bytearrayinputstream = null;

        char charbuffer[] = new char[200];
        int readed;
        try
        {
            bytearrayinputstream = new ByteArrayInputStream(memoryBuffer);

            inputstreamreader = new InputStreamReader(bytearrayinputstream);

            readed = inputstreamreader.read(charbuffer, 0, charbuffer.length);

            for (int i = 0; i < readed; i++)
            {
                System.out.print(charbuffer[i]);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                inputstreamreader.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)
    {
        new InputStreamReaderDemo();
    }
}

در مثال بالا از یک حافظه بافر (memoryBuffer در کد) به عنوان جریان ورودی استفاده کردیم ، برای ساخت حافظه بافر ابتدا رشته test را به آرایه ای از بایت ها (متغیر memoryBuffer) تبدیل کردیم ، سپس این آرایه از بایت ها را با استفاده از ByteArrayInputStream به یک جریان ورودی بایتی (متغیر bytearrayinputstream) تبدیل کردیم و در نهایت با استفاده از InputStreamReader جریان ورودی را به یک جریان کاراکتری (inputstreamreader) تبدیل کردیم. مابقی قسمت ها مشابه کد های قبلی است.