No_16_0324 Java基础学习第二十三天

文档版本 开发工具 测试平台 工程名字 日期 作者 备注
V1.0 2016.03.24 lutianfei none

登录注册IO版

  • 如下代码仅为UserDaoImpl类文件,其他原码参考day22_login_regist工程
public class UserDaoImpl implements UserDao {
    // 为了保证文件一加载就创建
    private static File file = new File("user.txt");

    static {
        try {
            file.createNewFile();
        } catch (IOException e) {
            System.out.println("创建文件失败");
            // e.printStackTrace();
        }
    }

    @Override
    public boolean isLogin(String username, String password) {
        boolean flag = false;

        BufferedReader br = null;
        try {
            // br = new BufferedReader(new FileReader("user.txt"));
            br = new BufferedReader(new FileReader(file));
            String line = null;
            while ((line = br.readLine()) != null) {
                // 用户名=密码
                String[] datas = line.split("=");
                if (datas[0].equals(username) && datas[1].equals(password)) {
                    flag = true;
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            System.out.println("用户登录找不到信息所在的文件");
            // e.printStackTrace();
        } catch (IOException e) {
            System.out.println("用户登录失败");
            // e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    System.out.println("用户登录释放资源失败");
                    // e.printStackTrace();
                }
            }
        }

        return flag;
    }

    @Override
    public void regist(User user) {
        /*
         * 为了让注册的数据能够有一定的规则,我就自己定义了一个规则: 用户名=密码
         */
        BufferedWriter bw = null;
        try {
            // bw = new BufferedWriter(new FileWriter("user.txt"));
            // bw = new BufferedWriter(new FileWriter(file));
            // 为了保证数据是追加写入,必须加true
            bw = new BufferedWriter(new FileWriter(file, true));
            bw.write(user.getUsername() + "=" + user.getPassword());
            bw.newLine();
            bw.flush();
        } catch (IOException e) {
            System.out.println("用户注册失败");
            // e.printStackTrace();
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    System.out.println("用户注册释放资源失败");
                    // e.printStackTrace();
                }
            }
        }
    }
}

操作基本数据类型的流

  • 可以读写基本数据类型的数据

    • 数据输入流:DataInputStream

      • DataInputStream(InputStream in)
    • 数据输出流:DataOutputStream
      • DataOutputStream(OutputStream out)
public class DataStreamDemo {
    public static void main(String[] args) throws IOException {
        // 写
        // write();

        // 读
        read();
    }

    private static void read() throws IOException {
        // DataInputStream(InputStream in)
        // 创建数据输入流对象
        DataInputStream dis = new DataInputStream(
                new FileInputStream("dos.txt"));

        // 读数据
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        char c = dis.readChar();
        boolean bb = dis.readBoolean();

        // 释放资源
        dis.close();

        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(c);
        System.out.println(bb);
    }

    private static void write() throws IOException {
        // DataOutputStream(OutputStream out)
        // 创建数据输出流对象
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(
                "dos.txt"));

        // 写数据了
        dos.writeByte(10);
        dos.writeShort(100);
        dos.writeInt(1000);
        dos.writeLong(10000);
        dos.writeFloat(12.34F);
        dos.writeDouble(12.56);
        dos.writeChar(‘a‘);
        dos.writeBoolean(true);

        // 释放资源
        dos.close();
    }
}

内存操作流

  • 内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用后就可以删除。
  • 使用完毕后,不需要close()方法,关闭流。
  • 操作字节数组
    • ByteArrayInputStream
    • ByteArrayOutputStream
  • 操作字符数组
    • CharArrayReader
    • CharArrayWrite
  • 操作字符串
    • StringReader
    • StringWriter
public class ByteArrayStreamDemo {
    public static void main(String[] args) throws IOException {
        // 写数据
        // ByteArrayOutputStream()
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // 写数据
        for (int x = 0; x < 10; x++) {
            baos.write(("hello" + x).getBytes());
        }

        // 释放资源
        // 通过查看源码我们知道这里什么都没做,所以根本不需要close()
        // baos.close();

        // public byte[] toByteArray()
        byte[] bys = baos.toByteArray();

        // 读数据
        // ByteArrayInputStream(byte[] buf)
        ByteArrayInputStream bais = new ByteArrayInputStream(bys);

        int by = 0;
        while ((by = bais.read()) != -1) {
            System.out.print((char) by);
        }

        // bais.close();
    }
}

流的基本分类

  • 基本流:就是能够直接读写文件
  • 高级流:在基本流基础上提供了一些其他的功能

打印流

打印流概述

  • 字节流打印流 PrintStream
  • 字符打印流 PrintWriter

打印流特点

  • 只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。
  • 可以操作任意类型的数据。
  • 如果启动了自动刷新,能够自动刷新。
  • 可以直接操作文本文件的
  • 可以操作任意类型的数据
    • print()
    • println()
      • 这个时候不仅仅自动刷新了,还实现了数据的换行。
哪些流对象是可以直接操作文本文件的呢?
  • FileInputStream
  • FileOutputStream
  • FileReader
  • FileWriter
  • PrintStream
  • PrintWriter
  • 具体方法:看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。
  • 基本功能
public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        // 作为Writer的子类使用
        PrintWriter pw = new PrintWriter("pw.txt");

        pw.write("hello");
        pw.write("world");
        pw.write("java");
        pw.close();
    }
}
  • 自动刷新换行的高级功能
/*
 * 1:可以操作任意类型的数据。
 *         print()
 *         println()
 * 2:启动自动刷新
 *         PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);
 *         还是应该调用println()的方法才可以
 *         这个时候不仅仅自动刷新了,还实现了数据的换行。
 *
 *         println()
 *        其实等价于于:
 *        bw.write();
 *        bw.newLine();
 *        bw.flush();
 */
public class PrintWriterDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建打印流对象
        // PrintWriter pw = new PrintWriter("pw2.txt");
        PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);

        // write()是搞不定的,怎么办呢?
        // 我们就应该看看它的新方法
        // pw.print(true);
        // pw.print(100);
        // pw.print("hello");

        pw.println("hello");
        pw.println(true);
        pw.println(100);

        pw.close();
    }
}
  • 打印流复制文本文件
/*
 * 需求:DataStreamDemo.java复制到Copy.java中
 * 数据源:
 *         DataStreamDemo.java -- 读取数据 -- FileReader -- BufferedReader
 * 目的地:
 *         Copy.java -- 写出数据 -- FileWriter -- BufferedWriter -- PrintWriter
 */
public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
        // 以前的版本
        // 封装数据源
        // BufferedReader br = new BufferedReader(new FileReader(
        // "DataStreamDemo.java"));
        // // 封装目的地
        // BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
        //
        // String line = null;
        // while ((line = br.readLine()) != null) {
        // bw.write(line);
        // bw.newLine();
        // bw.flush();
        // }
        //
        // bw.close();
        // br.close();

        // 打印流的改进版
        // 封装数据源
        BufferedReader br = new BufferedReader(new FileReader(
                "DataStreamDemo.java"));
        // 封装目的地
        PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);

        String line = null;
        while((line=br.readLine())!=null){
            pw.println(line);
        }

        pw.close();
        br.close();
    }
}

标准输入输出流(重点掌握)

  • (1)System类中的两个成员变量:

    • public static final InputStream in* “标准”输入流*
    • public static final PrintStream out* “标准”输出流*
    • InputStream is = System.in;
    • PrintStream ps = System.out;
    • 它们各代表了系统标准的输入和输出设备。
    • 默认输入设备是键盘,输出设备是显示器。
    • System.in的类型是InputStream
    • System.out的类型是PrintStreamOutputStream的子类FilterOutputStream 的子类.
  • (2)三种键盘录入方式
    • A:main方法的args接收参数
    • B:System.in通过BufferedReader进行包装
      • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    • C:Scanner
      • Scanner sc = new Scanner(System.in);
  • (3)输出语句的原理和如何使用字符流输出数据
    • A:原理

      • System.out.println(“helloworld”);
      • PrintStream ps = System.out;
      • ps.println(“helloworld”);
    • B:把System.out用字符缓冲流包装一下使用
      • BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
/*
 * 标准输入输出流
 * System类中的两个成员变量:
 *        public static final InputStream in “标准”输入流。
 *         public static final PrintStream out “标准”输出流。
 *
 *         InputStream is = System.in;
 *         PrintStream ps = System.out;
 */
public class SystemOutDemo {
    public static void main(String[] args) {
        // 有这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。
        System.out.println("helloworld");

        // 获取标准输出流对象
        PrintStream ps = System.out;
        ps.println("helloworld");

        ps.println();
        // ps.print();//这个方法不存在

        // System.out.println();
        // System.out.print();
    }
}
  • 用System.in实现键盘录入数据。用BufferedReader改进。
/*
 * System.in 标准输入流。是从键盘获取数据的
 *
 * 键盘录入数据:
 *         A:main方法的args接收参数。
 *             java HelloWorld hello world java
 *         B:Scanner(JDK5以后的)
 *             Scanner sc = new Scanner(System.in);
 *             String s = sc.nextLine();
 *             int x = sc.nextInt()
 *         C:通过字符缓冲流包装标准输入流实现
 *             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 */
public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        // //获取标准输入流
        // InputStream is = System.in;
        // //我要一次获取一行行不行呢?
        // //行。
        // //怎么实现呢?
        // //要想实现,首先你得知道一次读取一行数据的方法是哪个呢?
        // //readLine()
        // //而这个方法在哪个类中呢?
        // //BufferedReader
        // //所以,你这次应该创建BufferedReader的对象,但是底层还是的使用标准输入流
        // // BufferedReader br = new BufferedReader(is);
        // //按照我们的推想,现在应该可以了,但是却报错了
        // //原因是:字符缓冲流只能针对字符流操作,而你现在是字节流,所以不能使用?
        // //那么,我还就想使用了,请大家给我一个解决方案?
        // //把字节流转换为字符流,然后在通过字符缓冲流操作
        // InputStreamReader isr = new InputStreamReader(is);
        // BufferedReader br= new BufferedReader(isr);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        System.out.println("请输入一个字符串:");
        String line = br.readLine();
        System.out.println("你输入的字符串是:" + line);

        System.out.println("请输入一个整数:");
        // int i = Integer.parseInt(br.readLine());
        line = br.readLine();
        int i = Integer.parseInt(line);
        System.out.println("你输入的整数是:" + i);
    }
}
  • 用System.out实现控制台输出数据。用BufferedWriter改进。
/*
 * 转换流的应用。
 */
public class SystemOutDemo2 {
    public static void main(String[] args) throws IOException {
        // 获取标准输入流
        // // PrintStream ps = System.out;
        // // OutputStream os = ps;
        // OutputStream os = System.out; // 多态
        // // 我能不能按照刚才使用标准输入流的方式一样把数据输出到控制台呢?
        // OutputStreamWriter osw = new OutputStreamWriter(os);
        // BufferedWriter bw = new BufferedWriter(osw);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                System.out));

        bw.write("hello");
        bw.newLine();
        // bw.flush();
        bw.write("world");
        bw.newLine();
        // bw.flush();
        bw.write("java");
        bw.newLine();
        bw.flush();

        bw.close();
    }
}

随机访问流

RandomAccessFile概述

  • RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。支持对随机访问文件的读取和写入。

访问模式

  • “r” 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
  • “rw” 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
  • “rws” 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据每个更新都同步写入到底层存储设备
  • “rwd” 打开以便读取和写入,对于 “rw”,还要求对文件内容每个更新都同步写入到底层存储设备
  • 一般使用rw模式
  • 案例演示

public static void main(String[] args) throws IOException {
    write();
    read();
}

private static void read() throws IOException {
    RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
    int i = raf.readInt();
    System.out.println(i);
    System.out.println("当前指针位置:" + raf.getFilePointer());
    char ch = raf.readChar();
    System.out.println(ch);
    System.out.println("当前指针位置:" + raf.getFilePointer());
    String s = raf.readUTF();
    System.out.println(s);
    System.out.println("当前指针位置:" + raf.getFilePointer());
    System.out.println("读取数据完毕");

    System.out.println("当前指针位置:" + raf.getFilePointer());
    raf.seek(0);// 返回数据开头
    int ii = raf.readInt();
    System.out.println(ii);
}

private static void write() throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
    raf.writeInt(100); // 写入int类型
    raf.writeChar(‘爱‘);// 写入字符
    raf.writeUTF("中国你好");// 写入字符串
    raf.close();
    System.out.println("写入成功");
}

合并流

SequenceInputStream概述

  • SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。

SequenceInputStream的构造方法

  • SequenceInputStream(InputStream s1, InputStream s2)
  • SequenceInputStream(Enumeration
/*
 * 以前的操作:
 * a.txt -- b.txt
 * c.txt -- d.txt
 *
 * 现在想要:
 * a.txt+b.txt -- c.txt
 */
public class SequenceInputStreamDemo {
    public static void main(String[] args) throws IOException {
        // SequenceInputStream(InputStream s1, InputStream s2)
        // 需求:把ByteArrayStreamDemo.java和DataStreamDemo.java的内容复制到Copy.java中
        InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
        InputStream s2 = new FileInputStream("DataStreamDemo.java");
        SequenceInputStream sis = new SequenceInputStream(s1, s2);
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("Copy.java"));

        // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        sis.close();
    }
}
  • 方式二:
public class SequenceInputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 需求:把下面的三个文件的内容复制到Copy.java中
        // ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java

        // SequenceInputStream(Enumeration e)
        // 通过简单的回顾我们知道了Enumeration是Vector中的一个方法的返回值类型。
        // Enumeration<E> elements()
        Vector<InputStream> v = new Vector<InputStream>();
        InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
        InputStream s2 = new FileInputStream("CopyFileDemo.java");
        InputStream s3 = new FileInputStream("DataStreamDemo.java");
        v.add(s1);
        v.add(s2);
        v.add(s3);
        Enumeration<InputStream> en = v.elements();
        SequenceInputStream sis = new SequenceInputStream(en);
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("Copy.java"));

        // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        sis.close();
    }
}

序列化流

序列化流概述

  • 对象序列化是将对象状态转换为可保持或传输的过程。一般的格式是与平台无关的二进制流,可以将这种二进制流持久保存在磁盘上,也可以通过网络将这种二进制流传输到另一个网络结点。
  • 序列化流:可以把对象写入文本文件或者在网络中传输
    • ObjectOutputStream
  • 反序列化流:把这种二进制流数据还原成对象
    • ObjectInputStream
  • 序列化操作问题
    • 为什么要实现序列化?
    • 如何实现序列化?
      • 让被序列化的对象所属类实现序列化接口。
      • 该接口是一个标记接口。没有功能需要实现。
    • 序列化数据后,再次修改类文件,读取数据会出问题,如何解决呢?
      • 在类文件中,给出一个固定的序列化id值。而且,这样也可以解决黄色警告线问题
    • 使用transient关键字声明不需要序列化的成员变量
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException,
            ClassNotFoundException {
        // 由于我们要对对象进行序列化,所以我们先自定义一个类
        // 序列化数据其实就是把对象写到文本文件
        // write();

        read();
    }

    private static void read() throws IOException, ClassNotFoundException {
        // 创建反序列化对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                "oos.txt"));

        // 还原对象
        Object obj = ois.readObject();

        // 释放资源
        ois.close();

        // 输出对象
        System.out.println(obj);
    }

    private static void write() throws IOException {
        // 创建序列化流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
                "oos.txt"));

        // 创建对象
        Person p = new Person("林青霞", 27);

        // public final void writeObject(Object obj)
        oos.writeObject(p);

        // 释放资源
        oos.close();
    }
}
  • person类
/*
 * NotSerializableException:未序列化异常
 *
 * 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
 * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。
 *
 * java.io.InvalidClassException:
 * cn.itcast_07.Person; local class incompatible:
 * stream classdesc serialVersionUID = -2071565876962058344,
 * local class serialVersionUID = -8345153069362641443
 *
 * 为什么会有问题呢?
 *         Person类实现了序列化接口,那么它本身也应该有一个标记值。
 *         这个标记值假设是100。
 *         开始的时候:
 *         Person.class -- id=100
 *         wirte数据: oos.txt -- id=100
 *         read数据: oos.txt -- id=100
 *
 *         现在:
 *         Person.class -- id=200
 *         wirte数据: oos.txt -- id=100
 *         read数据: oos.txt -- id=100
 * 我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
 * 回想一下原因是因为它们的id值不匹配。
 * 每次修改java文件的内容的时候,class文件的id值都会发生改变。
 * 而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。
 * 但是呢,如果我有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗?
 * 不会。现在的关键是我如何能够知道这个id值如何表示的呢?
 * 不用担心,你不用记住,也没关系,点击鼠标即可。
 * 你难道没有看到黄色警告线吗?
 *
 * 我们要知道的是:
 *         看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值。
 *         而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。
 *
 * 注意:
 *         我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
 *         使用transient关键字声明不需要序列化的成员变量
 */
public class Person implements Serializable {
    private static final long serialVersionUID = -2071565876962058344L;

    private String name;

    // private int age;

    private transient int age;

    // int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = 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 "Person [name=" + name + ", age=" + age + "]";
    }
}

Properties集合

Properties概述

  • (1)是一个集合类Hashtable的子类,是一个可以和IO流相结合使用的集合类。可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
  • (2)特有功能
    • public Object setProperty(String key,String value):添加元素
    • public String getProperty(String key):获取元素
    • public Set<String> stringPropertyNames():获取所有的键的集合
  • (3)和IO流结合的方法
    • 键值对形式的文本文件内容加载到集合

      • public void load(Reader reader)
      • public void load(InputStream inStream)
    • 集合中的数据存储到文本文件
      • public void store(Writer writer,String comments)
      • public void store(OutputStream out,String comments)

Properties作为Map集合的使用

/*
 * 是Hashtable的子类,说明是一个Map集合。
 */
public class PropertiesDemo {
    public static void main(String[] args) {
        // 作为Map集合的使用
        // 下面这种用法是错误的,一定要看API,如果没有<>,就说明该类不是一个泛型类,在使用的时候就不能加泛型
        // Properties<String, String> prop = new Properties<String, String>();

        Properties prop = new Properties();

        // 添加元素
        prop.put("it002", "hello");
        prop.put("it001", "world");
        prop.put("it003", "java");

        // System.out.println("prop:" + prop);

        // 遍历集合
        Set<Object> set = prop.keySet();
        for (Object key : set) {
            Object value = prop.get(key);
            System.out.println(key + "---" + value);
        }
    }
}

Properties的特殊功能

  • public Object setProperty(String key,String value):添加元素
  • public String getProperty(String key):获取元素
  • public Set<String> stringPropertyNames():获取所有的键的集合

public class PropertiesDemo2 {
    public static void main(String[] args) {
        // 创建集合对象
        Properties prop = new Properties();

        // 添加元素
        prop.setProperty("张三", "30");
        prop.setProperty("李四", "40");
        prop.setProperty("王五", "50");

        // public Set<String> stringPropertyNames():获取所有的键的集合
        Set<String> set = prop.stringPropertyNames();
        for (String key : set) {
            String value = prop.getProperty(key);
            System.out.println(key + "---" + value);
        }
    }
}

/*
 * class Hashtalbe<K,V> { public V put(K key,V value) { ... } }
 *
 * class Properties extends Hashtable { public V setProperty(String key,String
 * value) { return put(key,value); } }
 */

Properties和IO流的结合使用

  • public void load(Reader reader):把文件中的数据读取到集合中

    • public void store(Writer writer,String comments):把集合中的数据存储到文件
/*
 * 这里的集合必须是Properties集合:
 * public void load(Reader reader):把文件中的数据读取到集合中
 * public void store(Writer writer,String comments):把集合中的数据存储到文件
 */
public class PropertiesDemo3 {
    public static void main(String[] args) throws IOException {
        // myLoad();

        myStore();
    }

    private static void myStore() throws IOException {
        // 创建集合对象
        Properties prop = new Properties();

        prop.setProperty("林青霞", "27");
        prop.setProperty("武鑫", "30");
        prop.setProperty("刘晓曲", "18");

        //public void store(Writer writer,String comments):把集合中的数据存储到文件
        Writer w = new FileWriter("name.txt");
        prop.store(w, "helloworld");
        w.close();
    }

    private static void myLoad() throws IOException {
        Properties prop = new Properties();

        // public void load(Reader reader):把文件中的数据读取到集合中
        // 注意:这个文件的数据必须是键值对形式
        Reader r = new FileReader("prop.txt");
        prop.load(r);
        r.close();

        System.out.println("prop:" + prop);
    }
}
  • 练习1:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100”
/*
 * 我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。
 * 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100”
 *
 * 分析:
 *         A:把文件中的数据加载到集合中
 *         B:遍历集合,获取得到每一个键
 *         C:判断键是否有为"lisi"的,如果有就修改其值为"100"
 *         D:把集合中的数据重新存储到文件中
 */
public class PropertiesTest {
    public static void main(String[] args) throws IOException {
        // 把文件中的数据加载到集合中
        Properties prop = new Properties();
        Reader r = new FileReader("user.txt");
        prop.load(r);
        r.close();

        // 遍历集合,获取得到每一个键
        Set<String> set = prop.stringPropertyNames();
        for (String key : set) {
            // 判断键是否有为"lisi"的,如果有就修改其值为"100"
            if ("lisi".equals(key)) {
                prop.setProperty(key, "100");
                break;
            }
        }

        // 把集合中的数据重新存储到文件中
        Writer w = new FileWriter("user.txt");
        prop.store(w, null);
        w.close();
    }
}
  • 练习2:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。
/*
 * 我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。
 */
public class PropertiesTest2 {
    public static void main(String[] args) throws IOException {
        // 读取某个地方的数据,如果次数不大于5,可以继续玩。否则就提示"游戏试玩已结束,请付费。"
        // 创建一个文件
        // File file = new File("count.txt");
        // if (!file.exists()) {
        // file.createNewFile();
        // }

        // 把数据加载到集合中
        Properties prop = new Properties();
        Reader r = new FileReader("count.txt");
        prop.load(r);
        r.close();

        // 我自己的程序,我当然知道里面的键是谁
        String value = prop.getProperty("count");
        int number = Integer.parseInt(value);

        if (number > 5) {
            System.out.println("游戏试玩已结束,请付费。");
            System.exit(0);
        } else {
            number++;
            prop.setProperty("count", String.valueOf(number));
            Writer w = new FileWriter("count.txt");
            prop.store(w, null);
            w.close();

            GuessNumber.start();
        }
    }
}

NIO包下的IO流

  • (1) JDK4出现NIO。新IO和传统的IO有相同的目的,都是用于进行输入输出的,但新IO使用了不同的方式来处理输入输出,采用内存映射文件的方式,将文件或者文件的一段区域映射到内存中,就可以像访问内存一样的来访问文件了,这种方式效率比旧IO要高很多,但是目前好多地方我们看到的还是旧IO的引用,所以我们仍以旧IO为主,知道NIO即可。
  • (2)JDK7的NIO的使用
    • Path:与平台无关的路径。
    • Paths:包含了返回Path的静态方法。
      • public static Path get(URI uri):根据给定的URI来确定文件路径。
    • Files:提供了常见的功能
      • 复制文本文件: public static long copy(Path source, OutputStream out)
      • 把集合中的数据写到文本文件:
        • public static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options)
  • 案例1:复制文件

    Files.copy(Paths.get("Demo.java"), newFileOutputStream("Copy.Java"));

  • 案例2:把集合中的数据写到文件
public class NIODemo {
    public static void main(String[] args) throws IOException {
        // public static long copy(Path source,OutputStream out)
        // Files.copy(Paths.get("ByteArrayStreamDemo.java"), new
        // FileOutputStream(
        // "Copy.java"));

        ArrayList<String> array = new ArrayList<String>();
        array.add("hello");
        array.add("world");
        array.add("java");
        Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));
    }
}
时间: 2024-10-06 12:53:28

No_16_0324 Java基础学习第二十三天的相关文章

No_16_0221 Java基础学习第二天

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.02.21 lutianfei none 第二章 Java基础语法(一)关键字(二)标识符1.常见命名规则(三)注释(四)常量原码.反码.补码有符号数据表示法(五)变量数据类型的默认转换数据类型的强制转换面试题1面试题2练习题1 byte b = 300:练习题2,写出下列程序结果 第二章 Java基础语法 本章内容 关键字 标识符 注释 常量.进制和进制转换 变量 数据类型和类型转换 运算符 语句 (一)关键字 关键

Java基础学习第二天——基础数据类型介绍

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.02.21 lutianfei none 第二章 Java基础语法 本章内容 关键字 标识符 注释 常量.进制和进制转换 变量 数据类型和类型转换 运算符 语句 (一)关键字 关键字概述 被Java语言赋予特定含义的单词 关键字特点 组成关键字的字母全部小写 关键字注意事项 goto和const作为保留字存在,目前并不使用(在JDK的新版本中可能提升为关键字) (二)标识符 标识符概述 就是给类,接口,方法,变量等起名

Java基础学习第二天

================每日必读==================== 写代码: 1.明确需求.我需要实现什么需求? 2.分析思路.我需要怎么实现需求? 3.确定步骤.我的每一部分思路需要使用到哪些语句,方法,对象? 4.代码实现.使用代码表现我的思路. ps:每天看一遍,每天向前进... ================每日必读==================== package code.day01; public class Demo {    public static v

No_16_0325 Java基础学习第二十四天—多线程学习总结

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.03.25 lutianfei none 第十章 多线程 多线程概述 什么是进程? 进程:就是正在运行的程序. 进程是系统进行资源分配和调用的独立单位.每一个进程都有它自己的内存空间和系统资源. 多进程有什么意义呢? 可以在一个时间段内执行多个任务. 可以提高CPU的使用率. 什么是线程呢? 在同一个进程内又可以执行多个任务,而这每一个任务我就可以看出是一个线程. 线程:是程序的执行单元,执行路径.是程序使用CPU的最

Java进阶学习第二十三天——国际化与AJAX、JSON

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.06.10 lutianfei none 国际化 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的.符合来访者阅读习惯的页面或数据. 国际化又称为 i18n:internationalization 软件实现国际化,需具备哪些特征: 对于程序中固定使用的文本元素,例如菜单栏.导航条等中使用的文本元素.或错误提示信息,状态信息等,需要根据来访者的地区和国家,选择不

Java基础学习第二十五天——多线程学习总结(二)

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.03.31 lutianfei none JDK5中Lock锁的使用 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock. Lock: void lock(): 获取锁. void unlock():释放锁. ReentrantLock是Lock的实现类. public class SellT

Java基础学习笔记十三 常用API之正则表达式、Date、DateFormat、Calendar

正则表达式 正则表达式(英语:Regular Expression,在代码中常简写为regex).正则表达式是一个字符串,使用单个字符串来描述.用来定义匹配规则,匹配一系列符合某个句法规则的字符串.在开发中,正则表达式通常被用来检索.替换那些符合某个规则的文本. 正则表达式的匹配规则 参照帮助文档,在Pattern类中有正则表达式的的规则定义,正则表达式中明确区分大小写字母.我们来学习语法规则. 正则表达式的语法规则: 字符:x 含义:代表的是字符x 例如:匹配规则为 "a",那么需要

linux基础学习第二十三天linux安全和加密之SSL\TLS协议、CA、openssl

内容: 1.通信加密类型及算法 2.TLS/SSL协议的引入及其通信过程 3.CA.数字签名的引入 4.一个安全的数据通信交换过程 5.openssl工具的使用 6.自制私有根CA过程 一.通信加密类型及算法 数据加密通信的重要性不言而喻,美国NIST,为了保证计算机的安全,提出了几个要求: (1).数据要有保密性:数据保密性和隐私性:确保信息不被别人获取,个人存储的信息不能被别人收集到: (2).完整性:包括数据完整性和系统完整性:数据完整性确保数据和程序只能以特定权限的进行授权和改变,只能授

linux基础学习第二十三天之openssh、sudo

内容: 1.openssh的介绍和使用 (1)sshd的服务端配置 (2)基于密钥登陆ssh的使用 (3)scp的使用 (4)rsync的使用 2.sudo的介绍和配置使用 一.openssh OpenSSH与SSH协议是远程登录的首选连接工具.它加密所有流量,以消除窃听,连接劫持和其它攻击. OpenSSH的套件包括以下工具: 远程操作使用 SSH, SCP,和 SFTP. 密钥管理 ssh-add, ssh-keysign, ssh-keyscan和ssh-keygen 服务端组成 sshd