首页 > 编程语言 >Java文件流(IO流)

Java文件流(IO流)

时间:2023-05-06 16:32:45浏览次数:35  
标签:文件 读取 Java 字节 字符 IO 序列化 String

在编程中,数据存储是重中之重,在之前的学习中所有程序中的数据都是临时存放在内存中的,不能做到有效存储和长久保存,而本次的文件流就暂时解决了数据不能长久存储的问题(虽然后面会学习数据库存储,但文件流存储也很常用)。

须知无论是读取文件还是写入文件等操作,在计算机中都是以流的形式进行操作的,就像水的流动一样,以内存为自身来看,内存向外写就是写操作,从文件读取到内存就是读操作。输入流和输出流的区分:以内存为参照,如果数据向内存流动,则是输入流,反之是输出流。

Java文件流(IO流)_IO流

IO流中分为字节流和字符流,详细分类如图:

Java文件流(IO流)_序列化_02

字符流和字节流的主要区别在于每次读取数据的大小不同,字节流读取的时候,读到一个字节就返回一个字节,字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据,每次读取一个字符大小。但是只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。字节输入流类包括:FileInputStream、BufferedInputStream和DataInputStream;字节输出流类包括:FileOutputStream、BufferedOutputStream和DataOutputStream。字符流输入类:FileReader:用来读取字符文件的便捷类;字符流输出类:FileWriter:用来写入字符文件的便捷类,可用于写入字符流。由此看出:结尾由Stream的流是字节流,而由Reader或Writer的流是字符流。具体流的使用场景如下图:

流分类

使用分类

字节输入流

字节输出流

字符输入流

字符输出流


抽象基类

InputStream

OutputStream

Reader

Writer

节点流

访问文件

FileInputStream

FileOutStream

FileReader

FileWriter


访问数值

ByteArrayInputStream

ByteArrayOutStream

CharArrayReader

CharArrayWriter


访问管道

PipedInputStream

PipedOutStream

PipedReader

PipedWriter


访问字符串



StringReader

StringWriter

处理流

缓冲流

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter


转换流



InputStreamReader

OutputStreamWriter


对象流

ObjectInputStream

ObjectOutputStream




抽象基类(过滤)

FilterInputStream

FilterOutputStream

FilterReader

FilterWriter


打印流


PrintStream


PrintWriter


推回输入流

PushbackInputStream


PushbackReader



特殊流

DataInputStream

DataOutputStream



接下来对文件字节流的读写的FileInputStream和FileOutPutStream和文件字符流FileWriter和FileReader进行详细的解读。FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作,FileInputStream()的构造函数需要传入一个文件对象来指定读取的具体文件,FileInputStre中读取文件的方法为read(),可以传入一个自定义大小的byte[]数组,结束标志是读取到的字节数为-1。

Java文件流(IO流)_序列化_03

FileOutputStream流是指文件字节输出流,专用于输出原始字节流如图像数据等,其继承OutputStream类,拥有输出流的基本特性。FileOutputStream()的构造函数同样需要传入一个文件对象,FileOutputStream中写入文件的方法为write(),也能传入一个byte[]数组。注意:写入数据后需要使用close()关闭流。

Java文件流(IO流)_IO流_04

FileWriter:用来写入字符文件的便捷类。此类的构造方法可以设置默认字符编码和默认字节缓冲区大小。FileWriter被称为文件字符输出流,FileWriter也需要传入一个文件对象,不过与字节输出流不同的是字符流的write()方法可以直接传入字符串,为了保证能够在文件中看到写入的数据需要使用flush()刷新或者直接关闭流来实现,两者的区别在于使用flush()后还可以使用该流,仍能对流进行操作,而使用close()之后不能再对该流进行操作。

Java文件流(IO流)_序列化_05

FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。FileReader被称为文件字符输入流,FileReader也需要传入一个文件对象,不过与字节输入流不同的是字符流的read()方法可以直接传入字符数组,使用完流后一定要用close()释放资源。

Java文件流(IO流)_bug问题_06

这里在说一下文件流操作中最容易出现的中文乱码问题,1:存入和取出时的编码方式不同就会产生中文乱码,例如设置一个对象的存入编码方式为GBK编码,而IDEA集成开发环境默认是UTF-8的话读取出来的数据就会是乱码显示。2:使用字节流读取含有中文的文件时会产生中文乱码,英文字母和数字不会产生乱码因为字节流读取是按照一个字节一个字节来读取的,英文字母和数字只占用一个字节,就像分割一样,读到一个就拿出,而中文在UTF-8下是由3个字节组成,所以这样一个中文本该是3个字节组成一个汉字,而读取的时候拆分成了3个小份,单独显示就是看不懂的乱码了。测试代码如下:

public class IoDemo8 {
    public static void main(String[] args) {
        String s = "abc里";
        byte[] bytes = s.getBytes();
        String s1 = null;
        try {
            // 如果存入和取出时的编码方式不同就会产生中文乱码
            s1 = new String(bytes,"GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(s1);

        try {
            PrintWriter printWriter = new PrintWriter("test.txt");
            printWriter.print("haha拜");
            printWriter.flush();
            printWriter.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            // 使用字节流读取会产生中文乱码
           FileInputStream fileInputStream = new FileInputStream("test.txt");
           int flag = 0;
           while((flag = fileInputStream.read()) !=-1) {
               System.out.println((char)flag);
           }
           fileInputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

Java文件流(IO流)_IO流_07


最后在简述一下如何使用对象流实现对象序列化和反序列化。对象的序列化指将一个Java对象写入IO流中,与此对应的是,对象的反序列化则指从IO流中恢复该Java对象如果需要让某个对象支持序列化机制,则必须让它的类是可序列化的。为了让某个类是可序列化的,必须实现Serializable接口,实现该接口并不需要重写任何方法,它只是作为一个标记接口,标记该类是可序列化的。(唯一需要注意的是可以为该类建立唯一序列号来区分,如果在序列化类中重新添加属性并使用该属性,再次反序列化的时候就会报错,因为已经对类进行修改和重新使用,系统会自动把默认的序列号修改,导致你重新反序列化的时候因为找不到原来序列号版本的文件数据而失败。)只需要了解出错的原理,以后出现问题知道解决方向就能很快搞定。对象序列化及反序列化的代码应用,建一个Student学生列,实现Serializable接口,定义一些常用属性如学号,姓名等,在建一个.txt的文本文件来存储序列化信息,然后就使用ObjectOutputStream对象流进行序列化,用ObjectInputStream进行反序列化。参考代码如下:

public class Student implements Serializable {
    // 建立唯一序列号
//    public static final long serialVersionUID = 1L;
    private String sno;
    private  String name;
//    private String tel;


    public Student() {
    }

    public Student(String sno,String name) {
        this.sno = sno;
        this.name = name;


    }


    public String getSno() {
        return sno;
    }

    public void setSno(String sno) {
        this.sno = sno;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sno='" + sno + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
  
}


public class IoDemo2 {
    public static void main(String[] args) throws Exception {
        List<Student> list = new ArrayList<>();
        list.add(new Student("s001","zs"));
        list.add(new Student("s002","li"));
        list.add(new Student("s003","wy"));
        // 序列化
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("demo.txt"));
        outputStream.writeObject(list);
        outputStream.close();

        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("demo.txt"));
        List<Student> list1 = (List<Student>) ois.readObject();
        for (Student student : list1) {
            System.out.println(student);
        }
        ois.close();

    }
}

运行结果:

Java文件流(IO流)_bug问题_08

至此文件流的基本知识及应用也阐述完了,知识学完,也喝一口鸡汤暖心提神,代码之路,bug无穷,要么出彩,要么出局!



标签:文件,读取,Java,字节,字符,IO,序列化,String
From: https://blog.51cto.com/u_15101214/6250757

相关文章

  • 【SSH】SSH框架(三)——Spring IOC和AOP的容器框架
    一、前言      在上一篇博客《【SSH】SSH框架(二)——Struts2框架的简单认识》中小编向大家简单的介绍了SSH框架中的第一个S,也就是Struct2。接下来小编将会向大家分享第二个S——Spring。二、Spring是干什么用的?      其实在小编以前做过的项目中也使用过Spring,那个时候......
  • 指数分布和泊松过程(Exponential Distribution and Poisson Process)--1
    ExponentialDistribution随机变量\(X\)服从指数分布的参数为\(\lambda\)的密度函数是:\(f(x)=\left\{\begin{align*}&\lambdae^{-\lambdax},\quadx\geq0\\&0,\quadelse\end{align*}\right.\),通过矩母函数\(\phi(t)=E(e^{tX})\)在0处的一阶和二阶导数可以比较容易......
  • javaScript 常用去除 ‘console
    javaScript常用去除‘console.log’办法手动注释掉console.log语句:可以手动在代码中注释掉所有console.log语句,但是这种方法比较繁琐,并且需要手动维护,不太适合大型项目。使用Babel插件去除console.log:Babel是一个JavaScript编译器,它可以将ES6+的代码转换成......
  • java类序列化和反序列化
    参考:https://zhuanlan.zhihu.com/p/144535172?utm_id=0https://blog.csdn.net/qq_42617455/article/details/1096223901、问题解答(1)序列化和反序列化都需要哪些操作对象要实现java.io.Serializable接口增加序列化ID(privatestaticfinallongserialVersionUID)转化成便于传......
  • java内存监控工具及命令
    关键字:内存监控工具及命令一篇非常好的内存监控知识,分享给爱学习的亲们.....jinfo:可以输出并修改运行时的java进程的opts。jps:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。jstat:一个极强的监视VM......
  • 文件上传框样式
    关键字:文件上传框样式附件是已经实现的现成的文件框的样式,直接部署即可,或者直接将其中的index.jsp放到您的项目中运行就可以看效果了,希望能帮到大家,谢谢!!!......
  • cookie与session
    目录一、cookie与session简介二、django操作cookie三、django操作session一、cookie与session简介知识点回顾回忆:HTTP协议四大特性1.基于请求响应 2.基于TCP、IP作用于应用层之上的协议3.无状态不保存客户端的状态4.无连接需求变化分析最开始的网站都不需要用户注......
  • 泛型字典TDictionary
    //声明bplList:TDictionary<string,Integer>;//创建bplList:=TDictionary<string,Integer>.Create;//往字典里增加一条h:=LoadPackage(bplName);bplList.Add(bplName,h);//查字典ifnotbplList.ContainsKey(bplName)then//遍历字典vari:Integer;............
  • 《asyncio 系列》6. 在 asyncio 中引入多进程
    楔子到目前为止我们使用asyncio获得的性能提升,一直专注在并发运行IO密集型工作上面,当然运行IO密集型工作是asyncio的主要工作,并且按照目前编写代码的方式,需要注意不要在协程中运行任何的CPU密集型代码。但这似乎严重限制了asyncio的使用,因为这个库能做的事情不仅仅限......
  • 在java 中, 如果三目运算符 是个函数,函数是一定会被执行吗
    在Java中,如果三目运算符中的取值是一个函数,函数不一定会被执行。这取决于三目运算符的条件表达式的结果。如果三目运算符的条件表达式的结果为true,那么执行函数并返回其结果;如果条件表达式的结果为false,那么不执行函数,直接返回另一个值。下面是一个示例代码:intx=5;int......