既然选择了远方,那只能风雨兼程!
1:登录注册IO版本案例
2:数据操作流(操作基本类型数据的流)
(1)可以操作基本类型的数据
(2)流对象名称
DataInputStream
DataOutputStream
3:内存操作流
(1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
(2)三种
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
4:打印流
(1)字节打印流,字符打印流
(2)特点:
A:只操作目的地,不操作数据源
B:可以操作任意类型的数据
C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
D:可以直接操作文件
问题:哪些流可以直接操作文件呢?
看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(3)复制文本文件
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();
5:标准输入输出流
(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));
6:随机访问流
(1)可以按照文件指针的位置写数据和读数据。
(2)案例:
7:合并流
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration<? extends InputStream> e)
8:序列化流
(1)可以把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能需要实现。
(3)注意问题:
把数据写到文件后,在去修改类会产生一个问题。
如何解决该问题呢?
在类文件中,给出一个固定的序列化id值。
而且,这样也可以解决黄色警告线问题
9:Properties
(1)是一个集合类,Hashtable的子类
(2)特有功能
A:public Object setProperty(String key,String value)
B:public String getProperty(String key)
C: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)
(4)案例:
10:NIO
(1)JDK4出现的NIO,对以前的IO操作进行了优化,提供了效率。但是大部分我们看到的还是以前的IO
(2)JDK7的NIO的使用
Path:路径
Paths:通过静态方法返回一个路径
Files:提供了常见的功能
复制文本文件
把集合中的数据写到文本文件
package cn.itcast.pojo;
/**
* 这是用户基本描述类
*
* @author 风清扬
* @version V1.1
*
*/
public 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;
}
}
package cn.itcast.dao;
import cn.itcast.pojo.User;
/**
* 这是针对用户进行操作的接口
*
* @author 风清扬
* @version V1.1
*
*/
public interface UserDao {
/**
* 这是用户登录功能
*
* @param username
* 用户名
* @param password
* 密码
* @return 返回登录是否成功
*/
public abstract boolean isLogin(String username, String password);
/**
* 这是用户注册功能
*
* @param user
* 要注册的用户信息
*/
public abstract void regist(User user);
}
ackage cn.itcast.dao.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 cn.itcast.dao.UserDao;
import cn.itcast.pojo.User;
/**
* 这是用户操作的具体实现类(IO版)
*
* @author 风清扬
* @version V1.1
*
*/
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();
}
}
}
}
}
package cn.itcast.test;
import java.util.Scanner;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.impl.UserDaoImpl;
import cn.itcast.game.GuessNumber;
import cn.itcast.pojo.User;
/**
* 用户测试类
*
* @author 风清扬
* @version V1.1
*
*/
public class UserTest {
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();
// switch语句的多个地方要使用,我就定义到外面
UserDao ud = new UserDaoImpl();
// 经过简单的思考,我选择了switch
switch (choiceString) {
case "1":
// 登录界面,请输入用户名和密码
System.out.println("--------------登录界面--------------");
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
// 调用登录功能
// UserDao ud = new UserDaomImpl();
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);
// 调用注册功能
// 多态
// UserDao ud = new UserDaoImpl();
// 具体类使用
// UserDaoImpl udi = new UserDaoImpl();
ud.regist(user);
System.out.println("注册成功");
break;
case "3":
default:
System.out.println("谢谢使用,欢迎下次再来");
System.exit(0);
break;
}
}
}
}
2:数据操作流(操作基本类型数据的流)
(1)可以操作基本类型的数据
(2)流对象名称
DataInputStream
DataOutputStream
package cn.itcast_01;
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 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();
}
}
3:内存操作流
(1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
(2)三种
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
package cn.itcast_02;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/*
* 内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失。
* 字节数组:
* ByteArrayInputStream
* ByteArrayOutputStream
* 字符数组:
* CharArrayReader
* CharArrayWriter
* 字符串:
* 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();
}
}
4:打印流
(1)字节打印流,字符打印流
(2)特点:
A:只操作目的地,不操作数据源
B:可以操作任意类型的数据
C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
D:可以直接操作文件
问题:哪些流可以直接操作文件呢?
看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(3)复制文本文件
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();
package cn.itcast_03;
import java.io.IOException;
import java.io.PrintWriter;
/*
* 打印流
* 字节流打印流 PrintStream
* 字符打印流 PrintWriter
*
* 打印流的特点:
* A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。
* B:可以操作任意类型的数据。
* C:如果启动了自动刷新,能够自动刷新。
* D:该流是可以直接操作文本文件的。
* 哪些流对象是可以直接操作文本文件的呢?
* 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();
}
}
5:标准输入输出流
(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));
package cn.itcast_04;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
* 转换流的应用。
*/
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();
}
}
6:随机访问流
(1)可以按照文件指针的位置写数据和读数据。
(2)案例:
package cn.itcast_05;
import java.io.IOException;
import java.io.RandomAccessFile;
/*
* 随机访问流:
* RandomAccessFile类不属于流,是Object类的子类。
* 但它融合了InputStream和OutputStream的功能。
* 支持对文件的随机访问读取和写入。
*
* public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。
* 模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据
*/
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", "rw");
int i = raf.readInt();
System.out.println(i);
// 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。
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());
// 我不想重头开始了,我就要读取a,怎么办呢?
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.close();
}
}
7:合并流
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration<? extends InputStream> e)
package cn.itcast_06;
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();
}
}
8:序列化流
(1)可以把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能需要实现。
(3)注意问题:
把数据写到文件后,在去修改类会产生一个问题。
如何解决该问题呢?
在类文件中,给出一个固定的序列化id值。
而且,这样也可以解决黄色警告线问题
9:Properties
(1)是一个集合类,Hashtable的子类
(2)特有功能
A:public Object setProperty(String key,String value)
B:public String getProperty(String key)
C: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)
(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;
import java.util.Set;
/*
* 我有一个文本文件(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();
}
}
10:NIO
(1)JDK4出现的NIO,对以前的IO操作进行了优化,提供了效率。但是大部分我们看到的还是以前的IO
(2)JDK7的NIO的使用
Path:路径
Paths:通过静态方法返回一个路径
Files:提供了常见的功能
复制文本文件
把集合中的数据写到文本文件