I/O流

I/O流

I:intpt(输入)
O:output(输出)
流:数据(字节和字符) 8比特位=1字节 2字节=1 字符

硬盘-->内存 == 输入(读取Reader)
内存-->硬盘 == 输出(写入Writer)

字节流基类 字符流基类
InputStream Reader
OutputStream Writer
  • 这些基类本身(抽象类)并不能用来创建实例执行输入输出,但是他们会成为模板

字节流

几乎所有文件的操作都是字节流完成的,部分文件因为需要读写字符串,需要用到字符流,但是
字节流(字符流底层也是字节流)也可以完成,不过是需要进行一部分额外的转换。

字节输出流 OutputStream

FileOutputStream

硬盘存储的所有文件均为二进制文件
FileOutputStream创建实例对象,会指向一个路径(相对或者绝对)的文件,如果该文件不存在会自动创建

FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97); //写入文件中的值为a,97经过转码ascll码,得到结果

fos.close() 关闭文件输出流,节约资源

FileOutputStream写入多个字节

 FileOutputStream fos = new FileOutputStream(new File("a.txt"));
        //FOS如果写入字节是正整数(0-127),写入文件中的结果会转为ascll码,
        //如果是负数,则会连带其后一个数转为gbk
        byte[] byte1 = new byte[]{65,-65};  //第一个正常转换ascll,第二个因为没有后续数字,所以文件显示为“?”
        fos.write(byte1);
        fos.flush();
        System.out.println(Arrays.toString("你好,世界".getBytes()));
        byte[] byte2 = new byte[]{-28, -67, -96, -27, -91, -67, -17, -68, -116, -28, -72, -106, -25, -107, -116}; //该数组为你好的而字节数组
        fos.write(byte2);
        //最终结果为 A夸綘濂斤紝涓栫晫 因为后续流接了上去,引起前面负数的连带,
        //字节流输入最好不要用负数结尾
        fos.close();

字节输入流续写

FileOutputStream fos = new FileOutputStream("src//IO流//a.txt",true);

字节输入流

FileInputStream

创建一个实例对象,该对象会指向一个目录的文件,如果该目录不存在,抛出File不存在
FileInputStream

try {
            FileInputStream fis = new FileInputStream("a.txt");
            {
                byte[] bbuf = new byte[1024];
                int hashRead = 0;
                while((hashRead=fis.read(bbuf))>0){
                System.out.print(new String(bbuf,0,hashRead));
        }

字符输出流

Writer

  • FileWriter是Writer基类的子类OutputStream(字节流的转换流)的子类,是常用的,文件字节输出流
    FileWriter fw = new FileWriter("b.txt"); 
    //FileWriter fw = new FileWriter("b.txt",true);如果要续写的话,增加true,不会覆盖原有的文件,如果是false的话将会覆盖原有的文件
    fw.write("人生是一场旅途");
    fw.close();  //这里如果不关闭流的话,b.txt中没有任何内容,可以flush流,就会有内容。一般在close在彻底关闭之前会对流flush

字符输入流

Reader

  • FileReader是Reader基类的子类InputStream(字节流的转换流)的子类,是常用的,文件字节输入流
FileReader fr = new FileReader("src//IO流//a.txt");
        int aa =  0;
        while((aa=fr.read())!=-1){ //这是一个字节一个字节读的
            System.out.print((char) aa);
        }
char [] a = new char[100];
        while(fr.read(a,0,a.length)!=-1){ //多个字节读
            System.out.print(String.valueOf(a));
        }

缓冲流

  • 通过对字节和字符的输入输出流的包装来,提高性能。
    • 字符流,字节流,每次读入或者写出一个字节/字符,都会进行一个从内存到硬盘(或者相反)的过程,缓冲流相当于,给他们增加了一个数组,多个字节/字符(相当与read()读取数组的例子),循环一边该过程。
  • 缓冲流与输入输出多个字节,有些许不同,缓冲流字节可以根据电脑性能弹性控制

转换流

  • 转换流的两个方法可以指定,输入输出的编(utf-8或者gbk)

io流提供了两个转换流,这两个转换流用于实现将字节流转换为字符流。
字节流比字符流的使用宽泛很多,所以,只有在字符流更加方便的情况下,才会将字节流转换为字符流。

比如,从txt文件中读取文本,或者写入,如果是二进制,需要在写入前以及读入进行包装(如果一次性操作不玩,需要多次调用转换方法)
但是,转换流,在源头进行包装,一次操作就不需要过多重复调用转换方法。

输入流以及输出流包装方法
InputStreamRead|OutputStreamWriter|
--|---|---

//转换流输入

public static void main(String[] args) throws IOException {
       InputStreamReader reader = new InputStreamReader(System.in,"gbk"); //设置读取字符串为gbk
//        reader.read()
//        char[] tmp = new char[1];
       int tmp = 0;
       while((tmp =reader.read())!=-1){
           System.out.print((char) tmp);
       }
   }

//转换流输出

   FileOutputStream fis = null;
       OutputStreamWriter osw = null;
       try {
           fis = new FileOutputStream("keyintest.txt",true);
           osw = new OutputStreamWriter(fis,"gbk");
           osw.write("我的世界");
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (UnsupportedEncodingException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }finally {
           try {
               osw.close();
           } catch (IOException e) {
               e.printStackTrace();
           }

       }

RandomAccessFile

  • 随机访问文件(任意访问文件)
  • RandomAccsessFile 提供了InputStream和OutputStream的三种read和writer方法
  • 它可以,改变文件指针。

RandomAccessFile在创建对象的时候需要指定一个mode参数,该参数指定Random的访问
模式

参数 作用
r 只读
rw 读写
rws 读写(每步都会直与底层同步)
rwd 读写(每步都会直与底层同步)
  • 注意:如果RandonAccessFile想要在,文档中间插入的话,在确定插入指针之后,需要用一个临时文件将之后的内容全部保存,因为,该对象直接插入会覆盖之后的内容

例子:

 public static void main(String[] args) throws IOException {
        RandomAccessFile rsf = new RandomAccessFile("src//IO流//RandomAccessFileTest.java","rw");
        byte[] tmpByte = new byte[100];
        int pointValue = -1;
        int tmp = -1;
        while (rsf.read(tmpByte)!=-1){
            System.out.print(new String(tmpByte)+"\n-----------------\n");//这里
         if ((tmp=new String(tmpByte).indexOf("这里"))!=-1){
                pointValue = (int) rsf.getFilePointer();
//                pointValue=pointValue- (tmpByte.length-3*tmp);
                System.out.print("指针节点--"+pointValue);
                System.err.print(tmp);
                break;
            }
        }
        if (pointValue != -1) {
            rsf.write("\n\n\n\n".getBytes());
            for (int i = 0;i<20;i++){
                rsf.write("w".getBytes());
            }
//            rsf.write("\n123\n".getBytes());
        }
    }

对象序列化的引用


  • 对象可以保存在磁盘上,即为序列化。
  • 从磁盘上恢复该java对象,即为反序列化
  • 某个类需要实例化,该类必须实现两个接口的其中一个
    • Serializable
    • Externalizable
posted @ 2019-08-30 16:16  zlisang  阅读(181)  评论(0)    收藏  举报