java-IO流相关知识

引言
在上一篇中提到了IO流中的字节流和字符流的相关概念,那么,在这个部分,主要说明其它相关IO流的知识。
LineNumberReader类:
跟踪行号的缓冲字符输入流,此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
String readLine():读取一行
做一个简单的案例进行理解:
案例:读取文件,每次读取一行打印并且加上行号

package com.stu_02;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
/*
   案例:读取文件,每次读取一行打印并且加上行号
 */
public class LineNumberReaderStu {
    public static void main(String[] args) throws IOException {
        //创建跟踪行号的字符缓冲输入流
        LineNumberReader lnr = new LineNumberReader(new FileReader("prop1.txt"));
        // public void setLineNumber(int lineNumber):设置起始行号
        lnr.setLineNumber(10);
        String line;
        //遍历
        while ((line=lnr.readLine())!=null) {
            //获取行号和内容
            System.out.println(lnr.getLineNumber()+" "+line);
        }
        //关流
        lnr.close();
    }
}

编译运行结果如下:
11 #Sat May 13 16:41:42 CST 2017
12 zhangsan=10
13 lisi=100
14 wangwu=4

操作基本数据类型的流
可以操作基本类型的流对象。
DataInputStream:读数据
DataOutputStream:写数据
注意:
读写顺序必须一致,否则数据有问题。
内存操作流
解决临时数据存储的问题。
操作字节数组
ByteArrayInputStream
ByteArrayOutputStream
byte[] toByteArray() 将之前写入内存的流转换成字节数组
操作字符数组
CharArrayReader
CharArrayWrite
操作字符串
StringReader
StringWriter
将数据写到流中保存在内存,并且读取,在这里,用一个操作字符数组做一解释说明:

package com.stu_04;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
/*
 * 操作字符数组
     CharArrayReader
     CharArrayWrite
 */
public class CharArrayReaderStu {
    public static void main(String[] args) throws IOException {
        //给内存中写数据
        CharArrayWriter caw = new CharArrayWriter();
        caw.write(99);
        //将内存中的数据读出来
        char[] ch=caw.toCharArray();
        int len;
        CharArrayReader car = new CharArrayReader(ch);
        while ((len=car.read())!=-1) {
            System.out.println((char)len);
        }
        //关流
        caw.close();
        car.close();
    }
}

编译运行结果如下:
c
打印流
字节打印流 PrintStream
字符打印流 PrintWriter
特点:
A:只能操作目的地,不能操作数据源
B:可以操作任意类型的数据
C:如果启动了自动刷新,能够自动刷新
D:可以操作文件的流
注意:什么流可以直接操作文件?
看流对象的API,如果其构造方法同时有File和String类型的参数,就可以直接操作文件。
如何启动自动刷新:利用构造
PrintWriter(OutputStream out, boolean autoFlush)
PrintWriter(Writer out, boolean autoFlush)
注意:如果启动了自动刷新,就要使用println、printf 或 format的时候,才可以实现自动刷新
启动自动刷新可以实现三个功能:1.写数据 2.换行 3.刷新
同样的,用一个简单的案例来理解:
利用字符流给文件中写数据(int类型,boolean类型),启动自动刷新

package com.stu_05;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
//利用字符流给文件中写数据(int类型,boolean类型),启动自动刷新
public class PrintWriterStu02 {
    public static void main(String[] args) throws IOException { 
        //创建打印字符流对象
        PrintWriter pw = new PrintWriter(new FileWriter("c.txt"),true);
        //写数据(写数据、换行、刷新)
        pw.println(20);
        pw.println(false);
        //关流
        pw.close(); 
    }
}

编译运行后会在命名为c.txt的文本文档下看到如下内容:
20
false
标准输入输出流
System类下有这样的两个成员变量:
标准输入流:
public static final InputStream in
标准输出流:
public static final PrintStream out
合并流
SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。
构造:
SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一个输入流,先读取s1后读取s2
利用该方法可以将两个java文件合并为一个java文件
对象的序列化和反序列化
序列化流:把对象按照流一样的方式写到文件或者在网络中传输。
反序列化流:把文件或者网络中的流对象数据还原对象。
ObjectOutputStream:序列化流
writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。
ObjectInputStream:反序列化流
Object readObject() 从 ObjectInputStream 读取对象。
注意:如果一个类不是实现Serializable接口无法把实例化,会报异常java.io.NotSerializableException
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
如何实现序列化?
让对象所属类的实现序列化接口。
举一个简单的例子来证明上面所说:

//创建学生对象
package com.stu_07;
import java.io.Serializable;
public class Student implements Serializable{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
}
//序列化流
package com.stu_07;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamStu {
    public static void main(String[] args) throws  IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
        Student s = new Student("薛之谦", 35);
        //将对象写入序列化流中
        oos.writeObject(s);
        //关流
        oos.close();    
    }
}
//反序列化流
package com.stu_07;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamStu {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
        Object object = ois.readObject();
        System.out.println(object);
        ois.close();
        }       
    }

编译运行后在oos.txt中会出现如下内容:
这里写图片描述
运行后在控制台输出入下:
Student [name=薛之谦, age=35]
Properties(查看api实现map接口本质是一个map集合)
Properties:Properties 类表示了一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。
特点:Properties 可保存在流中或从流中加载。
Properties的特有功能:
A:添加元素
public Object setProperty(String key,String value)
B:获取元素
public String getProperty(String key)
public Set stringPropertyNames()
可以和IO流进行结合使用:
把文件中的数据加载到集合中。注意:文件中的数据必须是键值对象形式的(例如:张杰=谢娜)。
public void load(InputStream inStream): 从输入流中读取属性列表(键和元素对)。
public void load(Reader reader):按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
把集合中的数据存储到文本文件中,并且是按照键值对形式存储的。
public void store(OutputStream out,String comments): 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
public void store(Writer writer,String comments): 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
结合上面所述,做一个简单的案例进行理解:
我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费

//猜数字代码
package com.stu_09;
import java.util.Scanner;
public class GuessNumber {
    public static void playGame(){
        int ran=(int) (Math.random()*100+1);
        Scanner sc=new Scanner(System.in);
        while(true){
            System.out.println("请输入你猜的数字:");
            int number =sc.nextInt();
            if(number<ran){
                System.out.println("猜小了,请重新输入:");
            }else if(number>ran){
                System.out.println("猜大了,请重新输入:");
            }else if(number==ran){
                System.out.println("恭喜你,猜对了!");
                break;
            }
        }
    }
}
//测试代码
package com.stu_09;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/*
 *我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,
      超过5次提示:游戏试玩已结束,请付费
 */
public class Test {
    public static void main(String[] args) throws IOException {
        Properties prop = new Properties();
        //将文件中的数据加载到集合中
        prop.load(new FileReader("count.txt"));
        //用指定的键在属性列表中搜索属性。
        String string = prop.getProperty("count");
        //转换成int类型
        int number=Integer.parseInt(string);
        //进行判断
        if(number>4){
            System.out.println("次数已到5次,请付费");
        }else{
            GuessNumber.playGame();
            number++;
            //将改变后的键值对重新存储到集合中去
            prop.setProperty("count", number+"");
            //将改变后的键值对存储到文件中
            prop.store(new FileWriter("count.txt"),null);   
        }   
    }
}

每一次玩一次游戏周,我们可以在count.txt中看到键值对的变化,如下:
第一次:
这里写图片描述
第二次:
这里写图片描述
第三次:
这里写图片描述
第四次:
这里写图片描述
第五次:
这里写图片描述
当猜完五次之后,第六次运行,在控制台会输出:
次数已到5次,请付费

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值