Java IO流

 

一、流的分类
1.按照操作数据的单位:字节流、字符流
2.按照数据的流向:输出流、输入流
3.按照流的角色:节点流、处理流

二、流的体系结构
抽象基类 节点流(文件流) 缓冲流(处理流的一种)
InputStream FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream
Reader FileReader BufferedReader
Writer FileWriter BufferedWriter

将文件读入并输出到console
说明点:
1.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
2.异常的处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理
3.读入的文件一定要存在,否则就会报FileNotFoundException

 

 

 

 

 

 

 

读取数据的标准操作流程,使用read()方法:

   @Test
    public void testFileReader() throws IOException {
        FileReader fr = null;
        try{
           //1.实例化File类的对象,指明要操作的文件
           File file = new File("hello.txt");
           //2.提供具体的流
           fr = new FileReader(file);
           //3.数据的读入
           //read():返回读入的一个字符,如果达到文件末尾,返回-1
            int data = fr.read();
           //方式一:

//        while(data !=-1){
//            System.out.println((char)data);
//            data = fr.read();
//        }
            //方式二:
           while((data=fr.read()) != -1){
               System.out.println((char)data);
           }
       }catch (IOException e){
           e.printStackTrace();
       }finally {
           //4.流的关闭操作
           if( fr != null){
               try{
                   fr.close();
               }catch (IOException e){
                   e.printStackTrace();
               }
           }
       }

    }

使用read(char[] cbuf) :

   //使用read的重载方法
    @Test
    public void testFileReader1(){
        FileReader fr = null;
        try{
            //1.File类的实例
            File file = new File("hello.txt");
            //2.FileReader流的实例化
            fr = new FileReader(file);
            //3.读入的操作
            //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数,如果达到文件末尾,返回-1
            char[] cbuf = new char[5];
            int len;
            while((len = fr.read(cbuf)) != -1){
                for (int i = 0; i < len; i++) {
                    System.out.print(cbuf[i]);
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            //4.资源的关闭
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

 

从内存中写出数据到硬盘的文件里

说明;
1.输入操作,对应的File可以不存在
如果文件存在,在输出过程中,会自动创建此文件
如果不存在:
如果流使用的构造器是FileWriter(file,false)/FileWriter(file),则会对原文件进行覆盖
如果流使用的构造器是FileWriter(file,true),则不会对原有文件进行覆盖,而是在原有基础上追加。
   @Test
    public void testFileWriter() throws IOException {
        //1.提供File类对象,指明写出的目标文件
        File file = new File("hello.txt");
        //2.提供FileWriter 的对象,用于数据的写出
        FileWriter fw = new FileWriter(file);
        //3.写出的操作
        fw.write("I am hero\n");
        fw.write("You are stupid");

        //4.流资源关闭
        fw.close();
    }

 

读取一个文件并输入到另一个文件的操作:

    @Test
    public void testFileWriterFileReader(){
        FileReader fr = null;
        FileWriter fw = null;
        try{
         File file1 = new File("hello.txt");
         File file2 = new File("hello1.txt");

         fr = new FileReader(file1);
         fw = new FileWriter(file2);

         char[] cbuf = new char[5];
         int len;
         while((len= fr.read(cbuf)) != -1){
             fw.write(cbuf,0,len);
         }
     }catch (IOException e){
         e.printStackTrace();
     }finally{
            if(fw != null ){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if( fr != null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

对于文本文件,使用字符流处理

对于非文本文件(.jpg/.mp3/.mp4/.doc/.ppt),使用字节流处理。

 

 //复制图片
    @Test
    public void testCopyPic() {
        File srcFile = new File("/user/Desktop/me.jpeg");
        File destFile = new File("/user/Desktop/you.jpeg");

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(srcFile);
           fos = new FileOutputStream(destFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


        byte[] buf = new byte[5];
        int len;
        while(true){
            try {
                if (((len =fis.read(buf)) != -1))
                fos.write(buf,0,len);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

 

处理流之二转换流:

属于字符流:提供字节流与字符流之间的转换

inputStreamReader:将一个字节的输入流转换为字符的输入流

outputStreamWriter :将一个字符的输出流转换为字节的输出流

 

 

 

其他流的使用
1.标准的输入输出流
2.打印流
3.数据流

1.标准的输入,输出流

1.1
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出

1.2
System类的setIn(InputStream is)/setOut(PrintStream ps)方式重新指定输入和输出的流。

1.3练习:
从键盘中输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作。
直至当输入"e"或者"exit"时,退出程序。

 public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while(true){
            String s = scan.nextLine();

            if("e".equals(s) || "exit".equals(s)){
                break;
            }
            System.out.println(s.toUpperCase());
        }
    }

    @Test
    public void test1() throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        while(true){
            System.out.println("请输入字符串:");
            String data = br.readLine();
            if(data.equalsIgnoreCase("e") || data.equalsIgnoreCase("exit")){
                System.out.println("程序结束");
                break;
            }
            String upperCase = data.toUpperCase();
            System.out.println(upperCase);
        }
        br.close();
    }

 

2.打印流

 

 

  @Test
    public void test2(){
        PrintStream ps = null;

        FileOutputStream fos = null;

        try {
            File f = new File("/Users/lye/Downloads/test.txt");
            fos = new FileOutputStream(f);

        ps = new PrintStream(fos,true);
        if(ps != null){
            System.setOut(ps);
        }

        for (int i = 0; i <= 255; i++) {
            System.out.print((char) i);
            if( i % 50 == 0){
                System.out.println();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            ps.close();
        }
    }
}

 

3.数据流
DataInputStream 和 DataOutputStream
作用:用于持久化基本数据类型的变量或者字符串
练习:将内存中的字符串,基本数据类型的变量写到文件中。
 @Test
    public void test3(){
        DataOutputStream dos = null;
        try {
            dos = new DataOutputStream(new FileOutputStream("/Users/lye/Downloads/test.txt"));
            dos.writeUTF("张三");
            dos.flush();//刷新数据,将内存中的数据写入文件
            dos.write(23);
            dos.flush();
            dos.writeBoolean(true);
            dos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    //将文件中存储的基本数据类型的变量和字符串读取到内存中并保存在变量中
    //注意点:读取的顺序必须和写入的顺序一致
    @Test
    public void test4(){
        DataInputStream dis = null;
        try {
            dis = new DataInputStream(new FileInputStream("/Users/lye/Downloads/data.txt"));
            String name = dis.readUTF();
            int age = dis.readInt();
            boolean isMale = dis.readBoolean();
            System.out.println("isMale =" + isMale);
            System.out.println("name =" + name);
            System.out.println("age =" + age);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                dis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

4.对象流

将对象保存在持久化文件中的流。

ObjectInputStream 和 ObjectOutputStream

 

对象流的使用
1.ObjectInputStream 和 ObjectOutputStream
2.作用:用于存储和读取基本数据类型数据和对象的处理流。
它的强大之处是可以把Java中的对象转换成二进制流保存在磁盘中或通过网络传输出去
3.要想一个Java对象是可序列化的,需要满足响应的要求*
(1)对象类需要实现接口:Serializable
(2)当前类提供一个全局常量:serialVersionUID

public class ObjectInputOutputStreamTest {

    @Test
    public void test(){
            /*
    序列化过程:将内存中的Java对象保存在磁盘中或通过网络传输出去
     */

        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            oos.writeObject(new String("hello"));
            oos.flush();//刷新操作
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    /*
    反序列化过程,将磁盘文件中的对象还原为内存中的一个Java对象
    使用ObjectInputStream来实现
     */
    @Test
    public void objectInputStreamTest(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream( new FileInputStream("object.dat"));
            Object o = ois.readObject();
            String str = (String) o;
            System.out.println(str);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

5.RandomAccessFile的使用

1.RandomAccessFile 直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
2.RandomAccessFile既可以作为一个输入流,也可以作为一个输出流
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建
如果写出的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
4.可以通过相关操作,实现RandomAccessFile的插入数据的操作

public class RandomAccessFileTest {

    @Test
    public void test(){
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            raf1 = new RandomAccessFile(new File("hello.txt"),"r");
            raf2 = new RandomAccessFile(new File("hellome.txt"),"rw");

            byte[] buffer = new byte[1024];
            int len;
            while( (len = raf1.read(buffer)) != -1){
                raf2.write(buffer,0,len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                raf1.close();
                raf2.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    //可以通过相关操作,实现RandomAccessFile的插入数据的操作
    @Test
    public void test2(){
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(new File("hello.txt"),"rw");
            raf.seek(3);
            StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
            byte[] buffer = new byte[20];
            int len;
            while((len=raf.read(buffer)) != -1){
                builder.append(new String(buffer,0,len));

            }
            raf.seek(3);
            raf.write("I fine Thank you".getBytes());
            raf.write(builder.toString().getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}

 

 
posted @ 2021-11-10 21:43  donkey8  阅读(26)  评论(0)    收藏  举报