自学内容网 自学内容网

java——io流

文件:文件就是保存数据的地方,而文件在程序中是以流的形式来操作的。

输入输出概念:输入输出是以我们的java程序(内存)来定义的。

javaIO流的原理和分类:

  1. 按着操作的单位不同分为:字节流(8bit),字符流(按字符,具体的一个字符相当于几个字节是按着编码来看的,例如UTF-8一个汉字是三个字节),仅仅只是在速度上讨论的话,还是字符流的速度快。但是如果是操作二进制文件:视频文件,音频文件,是无损操作。字符流适合操作文本文件。
  2. 按着数据流向的不同分为:输入流,输出流
  3. 按着流的角色不同分为:节点流,处理流/包装流
  • 节点流是针对特定的数据源的读写操作。

  • 处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。它本身不直接连接到数据源或目的地,而是对其他流进行处理,提供更高级的、更方便的读写功能。可以把处理流看作是对流的一种 “装饰”,在原始流的基础上添加新的功能。

  • 处理流引出的设计模式:(修饰器模式)

抽象基类

字节流

字符流

输入流

inputStream

Reader

输出流

outputStream

Writer

InputStream:字节输入流

三个常用子类:

文件字节输入流:FileinputStream

展示常见方法read():

public void test() {
        String filePath="d:/text.txt";
        FileInputStream fileInputStream=null;
        int read=0;
        try {
            fileInputStream= new FileInputStream(new File(filePath));
            while((read=fileInputStream.read())!=-1){
                System.out.print((char)read);
            }
            System.out.println();
        } catch (IOException e) {
            System.out.println("文件不存在");
            e.printStackTrace();
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

上面的方法在读取时按着一个字节一个字节的读取,时间实在是慢,所以我们可以采用另一个方法read(byte[]))

 public void test2() {
        String filePath="d:/text.txt";
        FileInputStream fileInputStream=null;
        int read=0;
        byte[] buffer=new byte[8];//一次读取8个字节
        try {
            fileInputStream= new FileInputStream(new File(filePath));
            //对于read(byte[])如果返回值时-1,证明去不读取完毕
            //如果不是-1的话,他的返回值是数组中文件的长度
            while((read=fileInputStream.read(buffer))!=-1){
                System.out.println(new String(buffer,0,read));
            }
            System.out.println();
        } catch (IOException e) {
            System.out.println("文件不存在");
            e.printStackTrace();
        }finally {
            try {
                //注意将流关闭
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
文件字节输出流:FileOutputStream
String context = "尝试写入数据";
    @Test
    public void test() {
        String filePath="d:/text.txt";
        FileOutputStream fos=null;
        //将文件放到数组中
        byte[] bytes = context.getBytes();
        try {
            //这里的方法重载如果,设置为true之后,实在已有文件的后面继续追加
            //如果new FileOutputStream(new File(filePath))的话,就是直接覆盖已有文件。
            fos = new FileOutputStream(new File(filePath),true);
            fos.write(bytes);
            System.out.println("文件写入成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                //注意!!!输入流必须关闭,不然无法写入
                fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
/*
*在这里对于他的write(int) 他的意思就是写单个字节,因为int和char是自动转换的,所以这个功能就达到了 
*/

假设我们现在有一个文件时图片,我们对于他的输入和输出就可以使用字节流。

文件字符输入流FileReader:

使用read()读取单个字符:

public void test() {
        String filePath="d:/text.txt";
        FileReader fr=null;
        int date=0;
        try {
            fr = new FileReader(new File(filePath));
            while((date=fr.read())!=-1){
                System.out.print((char)date);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
使用read(char[])

public void test2() {
        String filePath = "d:/text.txt";
        FileReader fr = null;
        int date=0;
        char[] buf = new char[1024];
        try {
            fr = new FileReader(new File(filePath));
            while ((date = fr.read(buf)) != -1) {
                System.out.print(new String(buf, 0, date));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
文件字符输出流:FileWriter

他有5种方式写入,这里为大家展示一个,其他的可以自己去尝试。

 public void test() {
        FileWriter fw=null;
        try {
            fw= new FileWriter(new File("d:/test.txt"),true);
            fw.write(context + "\n");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                //r如果不关闭后者是刷新的话数据无法写入。
                fw.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

缓冲流处理的文件的类型是通过出入的参数确定的,所以他的灵活性更好。

处理流BufferReader:
public void bufferReader() throws FileNotFoundException {
        String s =null;
        //在这个例子中,因为处理的是文件,所以使用的是文件字符输入流FileReader,在这里展现了他的零活性
        BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("d:/text.txt")));
        try {
             while((s=bufferedReader.readLine())!=null){
                 System.out.println(s);
             }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally{
            try {
                //在关闭流时,只需要关闭外层流
                bufferedReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

处理流BufferWriter:

String context="今天是2025年1月14日";
    @Test
    public void bufferWriter() throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("d:/text.txt"),true));
        bw.write(context);
        //尝试换行插入
        bw.newLine();
        bw.write(context);
        bw.close();
    }

当处理视频,音频,图片时,我们可以使用另外的两种处理流,BufferedInputStream,BufferedOutputStream.

对象字节输入流:ObjectInputStream和输出流ObjectOutputStream

例子演示需求,将int number =100 这个int数据保存到文件中,注意不是100数字,而是 int 100 ,并且,能够从文件中直接回复int 100.

将Dog dog = new Dog ("小黄",3)这个dog对象保存到文件中,并且可以从文件中恢复。

上面的两个例子展示了将基本的数据类型或者是对象的序列化和反序列化。

序列化:在保存数据时,保存数值和数据类型。
反序列化:恢复数据时回复的是值和数据类型

展示将我们的数据直接存储到.txt文件中:

public void test() {
        Dog dog = new Dog("小黄", 13);
        ObjectOutputStream oos=null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(new File("d:/text.txt")));
            oos.writeObject(dog);
            System.out.println("数据保存成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                oos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
   sr com.hdk.ropo.Dog f ]r ) L aget Ljava/lang/Integer;L namet Ljava/lang/String;xpsr java.lang.Integer⠤   8 I valuexr java.lang.Number       xp   
t 小黄

我们发下他在存储时,存储了例如包名,类名等信息。我们序列化之后的这个文件的后缀是随意的,以为他只是按着他的格式去序列化。

还有一个注意的点就是如果是自定义类型想要序列化,必须实现序列化接口.

现在将数据反序列化,获取对象的值:

反序列化的顺序要和我们的序列化的顺序相同。

   public void test() throws IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/text.txt")));
        try {
            Object o = ois.readObject();
            if(o instanceof Dog){
                Dog dog = (Dog) o;
                System.out.println(dog.getName());
                System.out.println(dog.getAge());
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        finally {
            ois.close();
        }
    }
序列化和反序列化的注意点:
  1. 序列护和反序列的顺序一定要一致
  2. 序列化和但序列化的类需要实现序列化接口
  3. 添加以下,提高兼容性,这时如果添加一个新的属性的化,他会认为这是一个修改,而不是直接创建了一个新的类型
private static final long seralVersionUID=1L;

4.序列化时,默认将所有的属性序列化,但是使用static修饰和transtic修饰的属性除外

5.序列化对象时,要求里面的属性类型也是需要实现序列化接口。

序列化具有继承性,如果一个类实现了序列的,他的子类默认实现了序列化。

标准输入输出流:

标准输入流:​​System.in​​ 他的编译类型是InputStream,他的运行类型是BufferInputStream.标准输入就是键盘

标准输出流:System.out 他的编译类型和运行类型都是PrintStream。

转换流:将一种字节流转换为字符流

java中有两种转换流:InputStreamReader和OutputStreamWriter。

在我们直接读取文本文件时,可能这个文本文件的编码形式不是我们默认的UTF_8,这是我们直接使用字符输入流读取的话就会出现问题。这是就展示了我们的转化流的重要性。

在使用时在字节流上指定编码的格式,之后在将他转化为字符流。

展示一个代码,将一个文本文件他的字符集编码是:GBK

public void test() throws IOException {
        /**
         * 我们的InputStreamReader他是一个字符流,就是Reader的子类
         */
        InputStreamReader isr =
                new InputStreamReader
                         //这里就是证明我们读取的文件的编码形式是
                        (new FileInputStream(new File("d:/text.txt")), "GBK");
        //将他出入缓冲流
        BufferedReader br = new BufferedReader(isr);
        System.out.println(br.readLine());
        br.close();
    }

案例代码二:将一句话写入到GBK文件中。这是我们查看刚刚写入的文件的话,他的格式是GBK.

打印流:PrintStream和PrintWriter

特点一:打印流只有输出流,没有输入流。

PrintStream他是一个字节流

它可以打印到文件,不仅仅只是打印到显示器中。

printWriter他是一个字符流

案例展示字节打印流:

public void test() throws FileNotFoundException {
        PrintStream out = System.out;
        //直接打印的话,默认是直接输出到屏幕上
        out.print(100);
        //------------------现在展示将数据打印到d:/test.txt中
        System.setOut(new PrintStream(new FileOutputStream(new File("d:/test.txt"))));
        System.out.println("我喜欢每一天早上升起的太阳");
    }

展示字符打印流:

public void test() throws IOException {
    //如果在里面出入的时标准输出的话,直接打印到屏幕上    PrintWriter printWriter = new PrintWriter(System.out, true);
    printWriter.println("Hello World");
    printWriter.close();
    //也可以出入地址输出到自定义的文件中    PrintWriter printWriter1 = new PrintWriter(new FileWriter(new File("d:/test.txt")), true);
    printWriter1.println("Hello World");
    printWriter1.close();
}

到这里小编就整理了常用的IO流的基本的用法,希望可以帮助到大家。


原文地址:https://blog.csdn.net/hdk5855/article/details/145173970

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!