IO流
用来处理设备之间的数据传输
I按照流向划分:
- 输入流:读取数据
- 输出流:写出数据
数据类型:
- 字节流
- 字符流:方便操作文本数据
如何选择流:
- 若操作的数据是文本数据,就用字符流;
- 若要操作的文件可以用记事本打开,打开后的数据是能读懂的,则可以用字符流,若不能读懂,则用字节流;
- 如果什么都不知道,就用字节流
字节流的抽象基类:InputStream,OutputStream
字符流的抽象基类:Reader,Writer
注:每种基类的子类都是以父类名作为后缀名
每次数据写成功后都需要close,原因如下:
- 让流对象变成垃圾,这样就可以被垃圾回收器回收了
- 通知系统去释放与该文件相关的资源
字节输出流操作步骤:
- 创建字节输出流对象
- 调用write()方法写数据
- 释放资源
注:不同的系统针对不同的换行符号的识别是不同的(一些常见的高级记事本,可以识别任意换行符)
- windows: \r, \n
- linux: \n
- mac: \r
实现追加写入数据:创建一个具有指定的name的文件中写入数据的输出文件流,如果第二个参数为true,则将字节写入文件末尾处,而不是写入文件开始处
字节输入流操作步骤:
- 创建字节输入流对象
- 调用read()方法读取数据,并把数据显示在控制台
- 释放资源
如果读取到了文件的末尾,则读取的数据为-1
字节流复制文本文件:(复制图片和视频同理)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//该方法对中文文本同样有效
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//封装数据源
FileInputStream fis = new FileInputStream("a.txt");
//封装目的地
FileOutputStream fos = new FileOutputStream("b.txt");
int by = 0;
while((by = fis.read()) != -1) {
fos.write(by);
}
//释放资源(先关谁都可以)
fis.close();
fos.close();
}
}
计算机是如何将两个字节转换成一个中文的:
在计算机中中文的存储分为两个字节,第一个字节肯定是负数,第二个字节常见的是负数,可能有正数,但是没有影响(当第一个字节是负数时,就和第二个字节拼起来)
FileInputStream按字节数组读取数据(比按一个字节要快)
import java.io.FileInputStream;
import java.io.IOException;
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
//数组的长度一般为1024或者1024的整数倍
byte[] bys = new byte[1024];
int len = 0;
while((len = fis.read(bys)) != -1) {
System.out.println(new String(bys,0,len));
}
fis.close();
}
}
字节缓冲流
带缓冲区的字节类,这种类被称为缓冲区类(高效类),可以指定缓冲区大小,一般情况下默认大小就够用
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
//按字节读取
int by = 0;
while((by = bis.read()) != -1) {
System.out.print((char)by);
}
System.out.println("\n--------------");
//按字节数组读取
byte[] bys = new byte[1024];
int len = 0;
while((len = bis.read(bys)) != -1) {
System.out.print(new String(bys,0,len));
}
bis.close();
}
}
转换流:
由于字节流操作中文不是很方便,所以java就提供了转换流
字符流 = 字节流 + 编码表
- OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换成字符流
- OutputStreamWriter(OutputStream out, String charsetName):根据指定编码把字节流的数据转换成字符流
close()和flush()的区别:
- close() 是关闭流对象,但是先刷新一次,关闭之后,流对象不能再继续使用
- flush()是刷新缓冲区,刷新之后,流对象还可以继续使用
因为转换流的名称有点长,所以Java提供了子类使用
转换流的简写:FileWriter和FileReader
字符缓冲流
特殊方法:
- BufferedWriter: public void newLine():根据系统来使用换行符
- BufferedReader:public String readLine():一次读取一行数据
字符缓冲流读取和写入数据
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedDemo {
public static void main(String[] args) throws IOException {
write();
read();
}
private static void read() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
//一次读取一行数据
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
private static void write() throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
for(int x = 0;x<10;x++) {
bw.write("hello" + x);
//换行
bw.newLine();
bw.flush();
}
bw.close();
}
}
hello0
hello1
hello2
hello3
hello4
hello5
hello6
hello7
hello8
hello9
字符缓冲流一次读写一个字符串
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//字符缓冲流一次读写一个字符串
public class demo {
public static void main(String[] args) throws IOException {
String srcString = "d:\\a.txt";
String destString = "d:\\b.txt";
method(srcString,destString);
}
public static void method(String srcString,String destString) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
String line = null;
while((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
标准输入输出流
System.out.println("hello world");
这个输出语句的本质是IO流操作,把数据输出到控制台,即如下所示:
PrintStream ps = System.out;
ps.println("hello world");
三种键盘录入方式
- main 方法的args接收参数
- System.in 通过BufferedReader进行包装
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - Scanner(最简单)
Scanner sc = new Scanner(System.in);
序列化
序列化:可以把对象写入文本文件或者在网络中传输(把对象写成流)
如何实现序列化:让被序列化的对象所属的类实现序列化接口(该接口是一个标记接口,没有功能需要实现)
反序列化:(把流还原成对象)
Properties
是一个集合类,Hashtable的子类
和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)
用户操作实现类(IO版)
/**
* 这是用户操作的具体实现类(IO版)
* @author Emotion
* @version V1.1
*/
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 dao.Userdao;
import pojo.User;
public class UserdaoImpl implements Userdao{
//为了保证文件一加载就创建
private static File file = new File("d:\\user.txt");
static {
try {
file.createNewFile();
} catch (IOException e) {
//e.printStackTrace();
System.out.println("文件创建失败!");
}
}
public boolean isLogin(String username,String password) {
BufferedReader br = null;
boolean flag = false;
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while((line = br.readLine()) != null) {
String[] data = line.split("=");
if(data[0].equals(username) && data[1].equals(password)) {
flag = true;
break;
}
}
} catch (FileNotFoundException e) {
//e.printStackTrace();
System.out.println("用户登录找不到信息所在的文件!");
} catch (IOException e) {
//e.printStackTrace();
System.out.println("用户登录失败!");
} finally {
if(br != null) {
try {
br.close();
} catch (IOException e) {
//e.printStackTrace();
System.out.println("用户登录释放资源失败");
}
}
}
return flag;
}
public void regist(User user) {
BufferedWriter bw = null;
try {
//为了保证数据是追加写入,必须加true
//bw = new BufferedWriter(new FileWriter(file));
bw = new BufferedWriter(new FileWriter(file,true));
bw.write(user.getUsername()+"="+user.getPassword());
bw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
System.out.println("用户注册失败!");
} finally {
try {
bw.close();
} catch (IOException e) {
//e.printStackTrace();
System.out.println("用户注册释放资源失败!");
}
}
}
}