@w460461339
2016-11-15T23:08:41.000000Z
字数 11596
阅读 1060
Java基础
今天学习了超级多的流以及用IO的方法重写了一下login&Regist的任务,发现还是挺多问题的。
下面一一介绍
需求分析:
A:可以实现注册功能,并将用户存储至本地文件,下次仍可调用
B:实现注册功能,重名用户显示注册失败
C:实现登陆功能,用户名,密码均一致显示成功,否则显示失败
分包:
A:用户类包
|---用于构建用户类,以便今后调用来创建用户对象,存储存储用户信息。
B:用户功能接口包
|---定义可以针对用户类的功能接口,描述可以对用户类进行的操作。
C:用户功能实现包
|---实现对用户类的功能。
D:测试包
|---添加测试程序。
package lr_User;//这个很简单,不解释了public class User {private String accout;private String password;public User() {super();// TODO Auto-generated constructor stub}public User(String accout, String password) {super();this.accout = accout;this.password = password;}public String getAccout() {return accout;}public void setAccout(String accout) {this.accout = accout;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User [accout=" + accout + ", password=" + password + "]";}}
package lr_function;import lr_User.User;//定义方法的名称,参数类型,访问属性等。但不包含具体实现public interface User_function {//登陆方法,成功返回true,失败返回falsepublic abstract boolean login(String account,String password);//注册方法,成功返回true,失败返回falsepublic abstract boolean regist(User myuser);}
package lr_function_impl;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import lr_User.User;import lr_function.User_function;public class User_funciton_impl implements User_function{private static File file=new File("account.txt");//静态代码块,在调用该类的时候仅且运行一次。用来创建存储数据的文件。static{try {if(!file.exists()){file.createNewFile();}} catch (IOException e) {System.out.println("内存不足,初始文件失败");//e.printStackTrace();}}//实现登陆方法@Overridepublic boolean login(String account, String password) {boolean flag=false;try {//按行得到account.txt中的数据BufferedReader br=new BufferedReader(new FileReader("account.txt"));String line=null;while((line=br.readLine())!=null){//以“=“为分割标志将数据分割String[] acc_pass=line.split("=");//比较用户名和账户if(acc_pass[0].equals(account)&&acc_pass[1].equals(password)){System.out.println("登陆成功");flag=true;}}} catch (FileNotFoundException e) {// TODO Auto-generated catch blockSystem.out.println("文件不存在");//e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blockSystem.out.println("登录失败");//e.printStackTrace();}return flag;}@SuppressWarnings("finally")@Overridepublic boolean regist(User myuser) {boolean flag=false;BufferedWriter bw=null;BufferedReader br=null;try {//判断用户名是否重复br=new BufferedReader(new FileReader("account.txt"));String line = null;while((line=br.readLine())!=null){String[] acc_pass=line.split("=");if(acc_pass[0].equals(myuser.getAccout())){System.out.println("用户名重复");return flag=false;}}} catch (IOException e1) {// TODO Auto-generated catch blockSystem.out.println("IOException");//e1.printStackTrace();}try {//写入新的用户br=new BufferedReader(new FileReader("account.txt"));bw=new BufferedWriter(new FileWriter("account.txt",true));bw.write(myuser.getAccout()+"="+myuser.getPassword());bw.newLine();bw.flush();System.out.println("注册成功");flag=true;} catch (IOException e) {// TODO Auto-generated catch blockSystem.out.println("注册失败");flag=false;//e.printStackTrace();}finally{if(bw!=null){try {bw.close();} catch (final IOException e) {System.out.println("释放资源失败");//e.printStackTrace();}}return flag;}}}
package lr_test;import java.util.Scanner;import lr_User.User;import lr_function_impl.User_funciton_impl;public class LogRegTest {/*** @param args*/public static void main(String[] args) {User_funciton_impl usefun=new User_funciton_impl();Scanner sc=new Scanner(System.in);String account=null;String password=null;for(int i=1;i<6;i++){account=sc.nextLine();password=sc.nextLine();User myuser=new User(account,password);usefun.regist(myuser);}boolean flag=false;do{account=sc.nextLine();password=sc.nextLine();flag=usefun.login(account, password);if(!flag){System.out.println("用户名或者密码不对");}}while(!flag);}}
(1)可以操作基本类型的数据
八种基本数据类型,int,byte,long,char,short,double,float,boolean
(2)流对象名称
DataInputStream
DataOutputStream
package trynewStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class DataStreamDemo {public static void main(String[] args) throws IOException {//注意,只能直接操作8种基本数据类型,String之类的就不行了。//仅有读写配对才能顺利读写,不然报错DataOutputStream dos=new DataOutputStream(new FileOutputStream("datademo.txt"));DataInputStream dis=new DataInputStream(new FileInputStream("datademo.txt"));//写的时候写intdos.writeInt(10);dos.close();//读的时候就要用int读System.out.println(dis.readInt());dis.close();}}
(1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。意思就是说把产生的东西丢到内存中,然后从内存中拿出来。多用于临时文件存储。
(2)三种
字节数组: A:ByteArrayInputStream,ByteArrayOutputStream
字符数组: B:CharArrayReader,CharArrayWriter
字符串 : C:StringReader,StringWriter
就演示下字符数组的好了= - 不好玩= -
package trynewStream;import java.io.CharArrayReader;import java.io.CharArrayWriter;import java.io.IOException;public class CharArrayReaderDemo {public static void main(String[] args)throws IOException {// TODO Auto-generated method stubCharArrayWriter caw=new CharArrayWriter();char[] ca={97,98,99,100};char[] ca2=new char[4];caw.write(ca);CharArrayReader car=new CharArrayReader(ca);car.read(ca2);System.out.println(ca2);}}
(1)字节打印流,字符打印流
PrintStream,PritnWriter
(2)特点:
A:只操作目的地,不操作数据源
B:可以操作任意类型的数据
C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
D:可以直接操作文件
问题:哪些流可以直接操作文件呢?
看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(3)复制文本文件
package trynewStream;import java.io.BufferedReader;import java.io.File;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.PrintStream;public class PrintDemo {public static void main(String[] args)throws IOException {//封装数据源BufferedReader br=new BufferedReader(new FileReader("account.txt"));//封装目的地PrintStream ps=new PrintStream(new FileOutputStream(new File("copy.txt")),true);String line=null;while((line=br.readLine())!=null){ps.println(line);//直接完成写入,换行,刷新三个动作}br.close();ps.close();}}
其实就这么理解,标准输入流使用BufferedWriter实现的,标准输出流使用PrintSteram实现的。
(1)System类下面有这样的两个字段
in 标准输入流
out 标准输出流
(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));
(1)可以按照文件指针的位置写数据和读数据。
RandomAccessFile();这货可读可写啊~~
(2)案例:
A:写数据
B:读数据
C:获取和改变文件指针的位置
package trynewStream;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;public class RandomStreamDemo {public static void main(String[] args) throws IOException{RandomAccessFile raf=new RandomAccessFile(new File("account.txt"), "rw");System.out.println(raf.readLine()+"---"+raf.getFilePointer());System.out.println(raf.readLine()+"---"+raf.getFilePointer());System.out.println(raf.readLine()+"---"+raf.getFilePointer());//文件指针重新指到18的位置上,再次读取后,最后一行又被读了raf.seek(18);System.out.println(raf.readLine()+"---"+raf.getFilePointer());}}
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration e)
import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;public class SequenceStreamDemo {public static void main(String[] args)throws IOException {//封装数据源SequenceInputStream sis=new SequenceInputStream(new FileInputStream("account.txt"),new FileInputStream("datademo.txt"));//封装目的地BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(new File("copy2.txt")));//复制byte[] bys=new byte[1024];int len=0;while((len=sis.read(bys))!=-1){bos.write(bys, 0, len);}//释放资源,关闭sis.close();bos.close();}}
写不动了,抄了一遍代码,这个说白了就是用vector存储所有要复制的流,然后一起输出。
import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;/** 以前的操作:* a.txt -- b.txt* c.txt -- d.txt* e.txt -- f.txt** 现在想要:* a.txt+b.txt+c.txt -- d.txt*/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();}}
主要目的就是直接往流中添加对象
(1)可以把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能需要实现。
(3)注意问题:
把数据写到文件后,在去修改类会产生一个问题。
如何解决该问题呢?
在类文件中,给出一个固定的序列化id值。
而且,这样也可以解决黄色警告线问题
(4)面试题:
什么时候序列化?
如何实现序列化?
什么是反序列化?
package cn.itcast_08;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.Reader;import java.io.Writer;import java.util.Properties;/** 这里的集合必须是Properties集合:* public void load(Reader reader):把文件中的数据读取到集合中* public void store(Writer writer,String comments):把集合中的数据存储到文件** 单机版游戏:* 进度保存和加载。* 三国群英传,三国志,仙剑奇侠传...** 吕布=1* 方天画戟=1*/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);}}
import java.io.Serializable;/** 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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}
(1)JDK4出现的NIO,对以前的IO操作进行了优化,提供了效率。但是大部分我们看到的还是以前的IO
(2)JDK7的NIO的使用
Path:路径
Paths:通过静态方法返回一个路径
Files:提供了常见的功能
复制文本文件
把集合中的数据写到文本文件
写不动了…睡觉= -