操作流
流文件实现的登录注册校验
DAO-接口操作集
POJO-简单用户定义集
DAO.impl-接口操作实现
- Code总体逻辑:
-
定义操作接口:注册-登录。
-
定义具体实现接口:注册-登录。
操作类接口保证文件的存在性,必须将创建文件作为静态代码块实现。
注册将user对象的Name=PassWord通过打开user.txt文件对象流写入到user.txt,考虑写入可能失败所以需要使用try…catch…finally去实现,返回boolean型。
登录类,通过打开文件对象流,读取每一行数据,并且通过split函数获取账号=密码,与通过界面输入的值通过equals匹配,若成功,返回true。 -
对象类:定义简单的用户对象,以及对应的成员变量和成员方法。
-
主函数类:界面控制问题:获取选项;判断合理性;调用对应的函数即可。
-
eg:
/*for example*/ 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 java.util.Scanner; /*用户定义*/ class User { private String username; private String password; public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } /*操作接口定义*/ interface UserDao { public abstract boolean isLogin(String username, String password); public abstract void regist(User user); } /*接口具体实现*/ 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(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(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(); } } } } } /*Game主函数*/ class GuessNumber { private GuessNumber() { } public static void start() { int number = (int) (Math.random() * 100) + 1; int count = 0; while (true) { Scanner sc = new Scanner(System.in); System.out.println("请输入数据(1-100):"); int guessNumber = sc.nextInt(); count++; // 判断 if (guessNumber > number) { System.out.println("你猜的数据" + guessNumber + "大了."); } else if (guessNumber < number) { System.out.println("你猜的数据" + guessNumber + "小了."); } else { System.out.println("恭喜你," + count + "次就猜中了!"); break; } } } } /*主函数部分*/ public class InterCalc { public static void main(String[] args) { // 为了能够回来 while (true) { // 欢迎界面,给出选择项 System.out.println("--------------欢迎光临--------------"); System.out.println("1 登录"); System.out.println("2 注册"); System.out.println("3 退出"); System.out.println("请输入你的选择:"); Scanner sc = new Scanner(System.in); String choiceString = sc.nextLine(); // 多态,接口内部调用User。 UserDao ud = new UserDaoImpl(); switch (choiceString) { case "1": // 登录界面,请输入用户名和密码 System.out.println("--------------登录界面--------------"); System.out.println("请输入用户名:"); String username = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); boolean flag = ud.isLogin(username, password); if (flag) { System.out.println("登录成功。"); System.out.println("你玩吗?y/n"); while (true) { String resultString = sc.nextLine(); if (resultString.equalsIgnoreCase("y")) { // 玩游戏 GuessNumber.start(); System.out.println("你还玩吗?y/n"); } else { break; } } System.out.println("谢谢使用,欢迎下次再来!"); System.exit(0); // break; //这里写break,结束的是switch } else { System.out.println("用户名或者密码有误,登录失败!"); } break; case "2": // 欢迎界面,请输入用户名和密码 System.out.println("--------------注册界面--------------"); System.out.println("请输入用户名:"); String newUsername = sc.nextLine(); System.out.println("请输入密码:"); String newPassword = sc.nextLine(); User user = new User(); user.setUsername(newUsername); user.setPassword(newPassword); ud.regist(user); System.out.println("注册成功."); break; case "3": System.out.println("欢迎下次再来!"); System.exit(0); break; default: System.out.println("请重新选择正确的选项!"); break; } } } }
-
带本地文件验证次数的登录注册验证—转到文章最后。
-
数据操作流 - 操作基本类型数据的流
-
DataOutputStream(OutputStream out)
创建一个新的数据输出流,以将数据写入指定的底层输出流。
-
DataInputStream
-
DataOutputStream
-
codeDemo:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 数据输入流:DataInputStream * DataInputStream(InputStream in). * 数据输出流:DataOutputStream * DataOutputStream(OutputStream out). */ public class DataStream{ 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(); } }
-
内存操作流
描述:有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
- ByteArrayInputStream,ByteArrayOutputStream.
- CharArrayReader,CharArrayWriter.
- StringReader,StringWriter.
/*for example*/ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /* * 内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失,且数据的操作不需要关闭流对象。 * 字节数组: * ByteArrayInputStream * ByteArrayOutputStream * 字符数组: * CharArrayReader * CharArrayWriter * 字符串: * StringReader * StringWriter */ public class ByteArrayStream{ 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(); } }
打印流
- 描述:包括字节打印流,字符打印流。
- 特点:
只操作目的地,不操作数据源,也就是说只有写函数没有读取函数。
可以操作任意类型的数据。
如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新。
可以直接操作文件.
-
直接操作文件
/*for example*/ /*复制文本文件*/ BufferedReader br = new BufferedReader(new FileReader("a.txt")); /*启动自动刷新:包括写入,写入新行,刷新等操作。*/ PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true); String line = null; while((line=br.readLine())!=null) { pw.println(line); } pw.close(); br.close();
标准输入输出流
-
System类中的两个成员变量:
public static final InputStream in “标准”输入流。 public static final PrintStream out “标准”输出流。
-
三种键盘录入方式
-
输出语句的原理和如何使用字符流输出数据.
System.out.println("helloworld"); //reg. PrintStream ps = System.out; //reg1. ps.println("helloworld"); //reg2. /*System.out用字符缓冲流包装使用.*/ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); bw.write("hello"); bw.newLine(); bw.write("world"); bw.newLine(); bw.write("java"); bw.newLine(); bw.flush(); bw.close();
随机访问流
RandomAccessFile类不属于流,是Object类的子类。
它融合了InputStream和OutputStream的功能。
支持对文件的随机访问读取和写入。
public RandomAccessFile(String name,String mode):
第一个参数是文件路径,第二个参数是操作文件的模式。
模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据。
mode:must be one of "r", "rw", "rws", or "rwd"
/*for example*/
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
write();
read();
}
private static void read() throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "r");
int i = raf.readInt();
System.out.print(i);
System.out.println("\t当前指针位置:" + raf.getFilePointer());
char ch = raf.readChar();
System.out.print(ch);
System.out.println("\t当前指针位置:" + raf.getFilePointer());
String s = raf.readUTF();
System.out.print(s);
System.out.println("\t当前指针位置:" + raf.getFilePointer());
String ss = raf.readUTF();
System.out.print(ss);
System.out.println("\t当前指针位置:" + raf.getFilePointer());
String sss = raf.readUTF();
System.out.print(sss);
System.out.println("\t当前指针位置:" + raf.getFilePointer());
System.out.println("------this is a dividing line------");
raf.seek(4);
ch = raf.readChar();
System.out.println(ch);
}
private static void write() throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
raf.writeInt(100);
raf.writeChar('a');
raf.writeUTF("中华");
raf.writeUTF("人民");
raf.writeUTF("共和国");
raf.close();
}
}
result:
100 当前指针位置:4
a 当前指针位置:6
中华 当前指针位置:14
人民 当前指针位置:22
共和国 当前指针位置:33
------this is a dividing line------
a
/* 为什么a指针4,中华为14,因为多读两个,后面的几个string就是验证这个表现的.*/
合并流
-
简单的描述就是将把多个输入流的数据写到一个输出流中,可以作为文件的复制合并操作。
-
构造方法:
SequenceInputStream(InputStream s1, InputStream s2) . SequenceInputStream(Enumeration<? extends InputStream> e).
-
文件合并
/*for example:两种方式实现的文件合并.*/
/* 要求:a.txt+b.txt=c.txt */ import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; public class SequenceInputStreamDemo { public static void main(String[] args) throws IOException { /*SequenceInputStream(InputStream s1, InputStream s2)*/ InputStream s1 = new FileInputStream("a.txt"); InputStream s2 = new FileInputStream("b.txt"); SequenceInputStream sis = new SequenceInputStream(s1, s2); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("c.txt")); byte[] bys = new byte[1024]; int len = 0; while ((len = sis.read(bys)) != -1) { bos.write(bys, 0, len); } bos.close(); sis.close(); } }
/* 要求:a.txt+b.txt+c.txt=final.txt,如下: */ 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; public class SequenceInputStreamDemo2 { public static void main(String[] args) throws IOException { // ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java // SequenceInputStream(Enumeration e) // Enumeration<E> elements() Vector<InputStream> v = new Vector<InputStream>(); InputStream s1 = new FileInputStream("a.txt"); InputStream s2 = new FileInputStream("b.txt"); InputStream s3 = new FileInputStream("c.txt"); 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("final.txt")); 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)。
使用方法:
让要被序列化的对象所属类实现序列化接口-> 接口为:Serializable->由于一般是读取之前存储的数据对象,而不是存储&读取,所以一旦对原对象进行修改后,将报错:serialVersionUID的匹配性问题-> 解决办法:使用第一个选项使用默认or第二个使用动态serialVersionUID-> 可能对某些对象的成员变量不需要写入,可以使用transient来修饰。 Serializable-----该接口是一个标记接口。没有功能需要实现。
/*for example*/ /*POJO--简单对象类*/ import java.io.Serializable; public class Person implements Serializable { //序列化接口,无内容的标记接口,目的是对IO格式的匹配。 private String name; private transient 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 + "]"; } } /*主函数类*/ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class ObjectStream{ 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("Tom", 3 ); oos.writeObject(p); oos.close(); } }
Properties
描述:Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。
属性列表可以包含另一个属性列表作为其“默认值”; 如果在原始属性列表中找不到属性键,则会搜索此第二个属性列表。
因为Properties从继承Hashtable时, put种putAll方法可应用于Properties对象。 强烈不鼓励使用它们,因为它们允许调用者插入其键或值不是Strings 。 应该使用setProperty方法。 如果store或save方法在包含非String键或值的“受损害” Properties对象上调用,则调用将失败。 类似地,如果在包含非String密钥的“受损害” Properties对象上调用propertyNames或list方法的调用将失败。
简而言之:就是一组持久的属性Hashtable子类,键值对都是String的数集。
继承结构如下:
-
特有or常用函数
import java.util.Properties; import java.util.Set; /* * Properties:属性集合类,是一个可以和IO流相结合使用的集合类。 * Properties 可保存在流中或从流中加载,属性列表中每个键及其对应值都是一个字符串。 * * 是Hashtable的子类=>是一个Map集合。 */ public class PropertiesDemo { public static void main(String[] args) { //错误用法:Properties<String, String> prop = new Properties<String, String>(); Properties prop = new Properties(); prop.put("001", "hello"); prop.put("002", "world"); prop.put("003", "java"); Set<Object> set = prop.keySet(); for (Object key : set) { Object value = prop.get(key); System.out.println(key + "---" + value); } } }
/* public Object setProperty(String key,String value) //添加元素键值对组。 public String getProperty(String key) //由键获取值。 public Set<String> stringPropertyNames() //获取键集合,属性指定为String。 */ import java.util.Properties; import java.util.Set; public class PropertiesCc { public static void main(String[] args) { Properties prop = new Properties(); prop.setProperty("Jack", "5"); prop.setProperty("Tom", "2"); prop.setProperty("coffee", "3"); /*public Set<String> stringPropertyNames():获取所有的键的集合*/ Set<String> set = prop.stringPropertyNames(); for (String key : set) { String value = prop.getProperty(key); System.out.println(key + "---" + value); } } }
-
Properties&IO流
-
把集合中的数据存储到文本文件中
public void store(Writer writer,String comments). public void store(OutputStream out,String comments).
-
把键值对形式的文本文件内容加载到集合中
public void load(Reader reader). public void load(InputStream inStream).
-
Code-eg:
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Properties; public class PropertiesCc{ public static void main(String[] args) throws IOException { myLoad(); myStore(); } private static void myStore() throws IOException { Properties prop = new Properties(); prop.setProperty("Jack", "5"); prop.setProperty("Tom", "2"); prop.setProperty("coffee", "3"); /*public void store(Writer writer,String comments):把集合中的数据存储到文件。*/ Writer w = new FileWriter("Store.txt"); prop.store(w, "Tips:"); w.close(); } private static void myLoad() throws IOException { Properties prop = new Properties(); /*public void load(Reader reader):把文件中的数据读取到集合中,这个文件的数据必须是键值对形式。*/ Reader r = new FileReader("load.txt"); prop.load(r); r.close(); System.out.println("prop:" + prop); } }
-
Properties&读档
/*for example*/ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Properties; public class PropertiesDd { public static void main(String[] args) throws IOException { File file = new File("count.txt"); if (!file.exists()) { file.createNewFile(); Properties prop = new Properties(); prop.setProperty("count", "0"); Writer w = new FileWriter("count.txt"); prop.store(w, null); w.close(); } /*把数据加载到集合*/ 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 > 3) { 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
- JDK4出现的NIO,对以前的IO操作进行了优化,但是目前还是使用以前的IO流操作…
- JDK7的NIO
-
Path:路径
-
Paths:通过静态方法返回一个路径。
-
Files:常用函数如下使用。
-
code–eg:
import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; /* * Paths:静态方法返回一个路径. * public static Path get(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) */ public class NIOAa { public static void main(String[] args) throws IOException { /* public static long copy(Path source,OutputStream out)--复制文件 */ Files.copy(Paths.get("Source.java"), new FileOutputStream("Copy.java")); ArrayList<String> array = new ArrayList<String>(); array.add("hello"); array.add("world"); /*Windows简体中文GBK,linux使用UTF-8*/ Files.write(Paths.get("Array.txt"), array, Charset.forName("GBK")); } }
-