IO编程之IO流

Java的IO流是实现输入、输出的基础,它可以方便的实现数据的输入输出操作。在Java中把不同的输入输出源(键盘、文件、网络连接)抽象表述为流(stream)。通过流可以使java程序使用相同的方式访问不同的输入输出源。

一、流的分类

    1、按照流的流向分:输入流和输出流

            输入流:只能从中读取数据,不能向其写入数据

            InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流

            输出流:只能向其写入数据,不能从中读取数据

            OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流      

    2、按照流的内容分:字节流和字符流

            字节流主要是有InputStream/OutputStream作为基类

            字符流主要是有Reader/Writer作为基类

    3、按照流的角色分:节点流和处理流

            从一个特定的IO设备读/写数据的流称为节点流,在已经存在的流进行连接或封装,封装后的流称为处理流。

二、代码测试

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PushbackReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import org.junit.Test;
public class StreamTest {
/**
     * 字节输入流读取文件内容
     * 
     */
    @Test
    public void inputStreamTest() {
        File f = new File("G://test//a1.txt");
        InputStream input = null;
        try {
            input  = new FileInputStream(f);
            byte[] bbuf = new byte[1024];
            int hasRead = 0;
            while((hasRead =input.read(bbuf)) > 0) {
                System.out.println(new String(bbuf,0,hasRead));
            }
             
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
     
    /**
     * 字符输入流读取文件内容
     */
    @Test
    public void fileReaderTest() {
        File f = new File("G://test//a1.txt");
        Reader reader = null;
        try {
            reader = new FileReader(f);
            char[] cbuf = new char[32];
            int hasRead = 0;
            while((hasRead = reader.read(cbuf))>0) {
                System.out.println(new String(cbuf,0,hasRead));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
/**
     * 使用FileInputStream输入文件,FileOutPutStream输出文件,实现文件复制
     */
    @Test
    public void fileOutputStreamTest() {
        //字节输入流
        FileInputStream fis = null;
        byte[] bbuf = new byte[1024];
        int hasRead = 0;
        //字节输出流
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("G://test//a1.txt");
            fos =  new FileOutputStream("G://test//a2.txt");
            while((hasRead = fis.read(bbuf))>0) {
                fos.write(bbuf, 0, hasRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                fos.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
/**
     * 字符输出流
     */
    @Test
    public void FileWriterTest() {
        FileWriter fw =null;
        try {
            fw = new FileWriter("G://test//a3.txt");
            fw.write("窗前明月光");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
     
    /**
     * 转换流的使用:InputStreamReader:将字节输入流转换成字符输入流 ,
     *  OutputStreamWriter将字节输出流转换成字符输出流
     */
    public void convertedStreamTest() {
        try 
        (
         InputStreamReader reader = new InputStreamReader(new 
         FileInputStream("G://test//temp.txt"),"UTF-8");
         OutputStreamWriter writer = new OutputStreamWriter(new 
         FileOutputStream("G://test//temp1.txt"),"UTF-8");
                )
        {
            char[] cbuf = new char[32];
            int hasRead = 0;
            while((hasRead=reader.read(cbuf))>0) {
                System.out.print(new String(cbuf, 0, hasRead));
                writer.write(cbuf, 0, hasRead);;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    /**
     * 缓冲流BufferReader:具有缓冲功能,它可以一次读取一行文本(以换行符为标识),如果没有读到换行符,则程序堵塞
     * 下面程序键盘输入字符串,只有等到按下回车键后,输入的内容才会打印出来
     */
    @Test
    public void bufferReaderTest() {
        try 
        (
         InputStreamReader reader = new InputStreamReader(System.in);
        //用缓存流包装输入流
         BufferedReader br = new BufferedReader(reader);
                )
        {
            String line = null;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    /**
     * 处理流
     * 处理流的优势:1、处理流进行输入输出操作更简单  2、使用处理流的效率更高
     * 
     *使用PrintStream 代替 OutputStream
     *PrintStream类的输出功能非常强大,通常如果我们要输出文本内容,应该将输出流包装成PrintStream
     */
    @Test
    public void printStreamTest() {
         
        try (
            FileOutputStream fos = new FileOutputStream("G://test//a4.txt");
            PrintStream ps = new PrintStream(fos);
            )
        {
            //输出字符串
            ps.println("使用PrintStream处理流输出文件");
            //输出对象
            ps.println(new StreamTest());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    /**
     * 推回输入流PushbackInputStream和PushbackReader
     * 推回输入流都带有一个推回缓冲区,当程序调用这两个推回输入流的unread()方法,系统会把指定数组的内容推回到该缓冲区里,而推回输入流每次调用read()方法时总是先
     * 从推回缓冲区中读取内容,只有完全读取了缓冲区的内容,但还没有装满read()所需的数组时才会从原输入流中读取。
     * 下面程序利用推回缓冲区,返回文件中"rdb"字符串之前的字符串
     */
    @Test
    public void pushBackTest() {
        try 
        (
            //创建PushbackReader对象,指定缓冲区长度为64
            PushbackReader pr = new PushbackReader(new FileReader("G://test//a1.txt"),64);
        )
        {
            char[] cbuf = new char[32];
            //用于保存上次读取字符串的内容。
            String lastContent = "";
            int hasRead = 0;
            while((hasRead = pr.read(cbuf))>0) {
                //将读取内容转换成字符串
                String content = new String(cbuf,0,hasRead);
                //用于记录 ‘rdb’字符串的位置
                int targetIndex = 0;
                if((targetIndex = (content + lastContent).indexOf("rdb"))>0) {
                    //回推包含‘rdb’的字符串
                    pr.unread((content+lastContent).toCharArray());
                    int len = targetIndex > 32? 32:targetIndex;
                    pr.read(cbuf, 0, len);
                    System.out.print(new String(cbuf,0,len));
                    System.exit(0);
                }else {
                    System.out.println(lastContent);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    /**
     * 缓冲流BufferReader:具有缓冲功能,它可以一次读取一行文本(以换行符为标识),如果没有读到换行符,则程序堵塞
     * 下面程序键盘输入字符串,只有等到按下回车键后,输入的内容才会打印出来
     */
    @Test
    public void bufferReaderTest() {
        try 
        (
         InputStreamReader reader = new InputStreamReader(System.in);
        //用缓存流包装输入流
         BufferedReader br = new BufferedReader(reader);
                )
        {
            String line = null;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    /**
     * RandomAcessFile类支持"随机访问的方式".程序可以直接跳转到文件的任意地方来读写数据
     * 如果我们只想访问文件的部分内容,使用RandomAcessFile更好
     * RandomAcessFile允许自由定位文件记录指针,所以RandomAcessFile可以不从开始的地方开始输出,所以RandomAcessFile可以向已经存在的文件
     * 后面追加内容。如果程序想在已存在的文件后追加内容,应该使用RandomAcessFile
     * 
     */
    @Test
    public void randomAcessFile() {
         
        try (
            //创建RandomAccessFile对象时需要一个mode参数
            //r:以只读方式打开文件,rw:以读写方式打开文件
            //rws:以读写方式打开文件,还要求对文件内容或元数据的每个更新都同步写入底层存储设备
            //rwd:以读写方式打开文件,还要求对文件内容的每个更新都同步写入到底层存储设备
            RandomAccessFile raf = new RandomAccessFile(new File("G://test//a1.txt"), "rw");
                )
        {
            //RandomAccessFile的文件初始位置,初始是0
            System.out.println("文件指针初始位置:"+raf.getFilePointer());
            //移动文件指针位置,从移动后的位置开始读取文件内容
            raf.seek(32);
            byte[] bbuf = new byte[32];
            int hasRead = 0;
            while((hasRead = raf.read(bbuf))>0) {
                System.out.println(new String(bbuf,0,hasRead));
            }
             
            //指针移动到文件最后
            raf.seek(raf.length());
            //向文件后追加内容
            raf.write("追加内容".getBytes());
             
        } catch (Exception e) {
            e.printStackTrace();
        }
         
    }
}

 

posted @ 2019-03-15 11:04  技术小白丁  阅读(339)  评论(0编辑  收藏  举报