操作流的基本步骤
1.创建源 2.选择流 3.操作(读入) 4.释放资源
一.节点流
从一个特定的数据源(节点)读写数据(如:文件、内存)的类叫做节点流类。
1.文件字节流
- 1.1字节输入流 FileInputStream
步骤:1.创建源 ;2.选择流; 3.操作(读入);4.释放资源
public static void main(String[] args) {
// 1.创建源
File src = new File("D:/workspace/stsworkspace/IO_study02/src/abc.txt");
// 2.选择流
InputStream is = null;
try {
is = new FileInputStream(src);
// 3.操作
// 缓冲容器-字节数组
byte[] flush = new byte[1024 * 10];
// 接收长度
int len = -1;
while ((len = is.read(flush)) != -1) {
// 字节数组-->字符串(解码)
String str = new String(flush, 0, len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 1.2字节输出流 FileOutputStream
1.创建源 2.选择流 3.操作(写出内容) 4.释放资源
public static void main(String[] args) {
// 1.创建源
File dest = new File("dest.txt");
// 2.选择流
OutputStream os = null;
try {
//true:在原来的数据后面是追加写入
//false:将原来的数据删掉,重写写入
os = new FileOutputStream(dest,true);
//3.操作(写出)
String msg = "IO is so easy";
//字符串-->字节数组(编码)
byte[] datas = msg.getBytes();
os.write(datas,0,datas.length);
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != os) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 1.3文件copy
public static void main(String[] args) {
// 1.创建源
//输入源
File inputSrc = new File("abc.txt");
//输出源
File outputSrc = new File("abc_cop.txt");
// 2.选择流
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(inputSrc);
os = new FileOutputStream(outputSrc,true);
// 3.操作
// 缓冲容器-字节数组(分段读取)
byte[] flush = new byte[1024 * 10];
// 接收长度
int len = -1;
while ((len = is.read(flush)) != -1) {
// // 字节数组-->字符串(解码)
// String str = new String(flush, 0, len);
//
// // 字符串-->字节数组(编码)
// byte[] datas = str.getBytes();
// 以上代码可以省略,由于is.read(flush)方法执行结束后,
// 不仅返回接受长度,还会将内容存入字节数组(更新fulsh),
// 所以在write方法中直接使用即可;
os.write(flush,0,len);
os.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.释放资源 分别关闭 先打开的后关闭
try {
if (null != os) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.文件字符流
- 2.1字符输入流 FileReader
public static void main(String[] args) {
// 1.创建源
File src = new File("D:/workspace/stsworkspace/IO_study02/abc.txt");
// 2.选择流
Reader reader = null;
try {
reader = new FileReader(src);
// 3.操作
// 缓冲容器-字节数组
char[] flush = new char[1024];
// 接收长度
int len = -1;
while ((len = reader.read(flush)) != -1) {
// 字节数组-->字符串
String str = new String(flush, 0, len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(null!=reader) {
reader.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
- 2.2字符输出流 FileWriter
public static void main(String[] args) {
// 1.创建源
File dest = new File("dest.txt");
// 2.选择流
Writer writer = null;
try {
writer = new FileWriter(dest);
//3.操作(写出)
String msg = "IO is so easy 文件字符输出流aaa";
//写法一
//字符串-->字节数组
// char[] datas = msg.toCharArray();
//
// writer.write(datas,0,datas.length);
// writer.flush();
//写法二
writer.write(msg);
writer.write("append");
writer.flush();
//写法三
writer.append(msg).append("append");
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != writer) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.文件字节数组流
- 3.1字节数组输入流 ByteArrayInputStream
步骤: 1.创建源:字节数组; 2.选择流; 3.操作; 4.释放资源:可以不处理
public static void main(String[] args) {
// 1.创建源
byte[] src = "talk is cheap show me the code".getBytes();
// 2.选择流
InputStream is = null;
try {
is = new ByteArrayInputStream(src);
// 3.操作(分段读取)
// 缓冲容器-字节数组
byte[] flush = new byte[5];
// 接收长度
int len = -1;
while ((len = is.read(flush)) != -1) {
// 字节数组-->字符串
String str = new String(flush, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//字节数组可以不释放内存
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 3.2字节数组输出流 ByteArrayOutputStream
步骤: 1.创建源:内部维护; 2.选择流:不关联源; 3.操作:(写出内容);4.释放资源:可以不处理
public static void main(String[] args) {
// 1.创建源
byte[] dest = null;
// 2.选择流
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
//3.操作(写出)
String msg = "show me the code";
//字符串-->字节数组(编码)
byte[] datas = msg.getBytes();
baos.write(datas,0,datas.length);
baos.flush();
//获取数据
dest = baos.toByteArray();
System.out.println(dest.length
+ "-->" + new String(dest,0,baos.size()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != baos) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
二.处理流
只用字节或是字符为单位来对数据做输入输出是不够的,有时候我们需要一行一行的读数据,有时我们需要读取特定格式的数据,因此Java提供了这样的机制,能把数据流作连接(chain),让原本没有特殊访问方法的流,通过连接到特殊的流后,变成可以用特定的方法来访问数据。
1.字节缓冲流
提升性能,建议在所有流外面都套一个。
- 1.1字节缓冲输入流 BufferedInputStream
public static void main(String[] args) {
// 1.创建源
File src = new File("abc.txt");
// 2.选择流
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(src));
// 3.操作(分段读取)
// 缓冲容器-字节数组
byte[] flush = new byte[1024];
// 接收长度
int len = -1;
while ((len = is.read(flush)) != -1) {
// 字节数组-->字符串
String str = new String(flush, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//字节数组可以不释放内存
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 1.2字节缓冲输出流 BufferedOutputStream
public static void main(String[] args) {
// 1.创建源
File dest = new File("destbuffer.txt");
// 2.选择流
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(dest)) ;
//3.操作(写出)
String msg = "IO is so easy ,BufferedOutputStream";
//字符串-->字节数组(编码)
byte[] datas = msg.getBytes();
os.write(datas,0,datas.length);
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != os) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.字符缓冲流
- 2.1 字符缓冲输入流 BufferedReader
public static void main(String[] args) {
// 1.创建源
File src = new File("D:/workspace/stsworkspace/IO_study02/abc.txt");
// 2.选择流
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(src)) ;
// 3.操作
String line = null;
//readLine():BufferedReader新方法,所以第20行不能使用多态
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(null!=reader) {
reader.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
- 2.2 字符缓冲输出流 BufferedWriter
public static void main(String[] args) {
// 1.创建源
File dest = new File("dest.txt");
// 2.选择流
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(dest)) ;
//3.操作(写出)
String msg = " 文件字符输出流";
writer.append("IO is so easy");
writer.newLine();
writer.append("测试新方法newLine()");
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != writer) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.转换流
转换流特点:以字符流的形式操作字节流(纯文本),可以指定字符集;
- 3.1输入流 InputStreamReader
- 3.2输出流 OutputStreamWriter
public static void main(String[] args) {
//操作System.in和System.out
try(
//括号中可以写多行语句,会自动关闭括号中的资源
//将字节流(System.in)转换为字符流
//"UTF-8"指定字符集
BufferedReader reader = new BufferedReader (new InputStreamReader(System.in,"UTF-8"));
//将字节流(System.out)转换为字符流
BufferedWriter writer = new BufferedWriter (new OutputStreamWriter(System.out));
){
//循环获取键盘的输入(exit退出),输出此内容
String msg = "";
while(!msg.equals("exit")) {
msg = reader.readLine();
writer.write(msg);
writer.newLine();
writer.flush();//强制刷新
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
4.数据流 DataOutputStream DataInputStream
特点:保留了数据类型
要求:1.写出后读取;2.读取的顺序与写出保持一致
public static void main(String[] args) throws IOException {
//写出
//声明字节流对象,以便使用其新增方法
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
//操作数据类型 + 数据
dos.writeUTF("编码心酸泪,谁解其中味");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
//任何数据都可以转换为字节数组
byte[] datas = baos.toByteArray();
//读取
DataInputStream dis = new DataInputStream(
new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dis.readUTF();
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);
}
5.对象流 ObjectOutputStream ObjectInputStream
- 5.1对象流特点
1.写出后读取;2.读取的顺序与写出保持一致;3.不是所有的对象都可以序列化,必须实现Serializable接口或Externalizable接口; - 5.2序列化
对象(Object)序列化是指将对象转换为字节序列的过程;
反序列化则是根据字节序列恢复对象的过程; - 5.3序列化一般用于以下场景
①永久性保存对象,保存对象的字节序列到本地文件中;
②通过序列化对象在网络中传递对象;
③通过序列化在进程间传递对象;
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写出
//声明字节流对象,以便使用其新增方法
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(baos));
//操作对象
oos.writeObject("编码心酸泪,谁解其中味");
oos.writeObject(new Date());
Emlpoyee emp = new Emlpoyee("马云",400);
oos.writeObject(emp);
oos.flush();
//任何数据都可以转换为字节数组
byte[] datas = baos.toByteArray();
//读取
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
Object str = ois.readObject();
Object date = ois.readObject();
Object emlpoyee = ois.readObject();
if(str instanceof String){
String strObj = (String)str;
System.out.println(strObj);
}
if(date instanceof Date){
Date dateObj = (Date)date;
System.out.println(dateObj);
}
if(emlpoyee instanceof Emlpoyee){
Emlpoyee empObj = ((Emlpoyee) emlpoyee);
System.out.println(empObj.getName());
System.out.println(empObj.getSalary());
}
}
被transient修饰的属性不会被序列化
class Emlpoyee implements java.io.Serializable{
//transient指该数据不需要序列化
private transient String name;
private double salary;
public Emlpoyee() {
super();
}
public Emlpoyee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
6.打印流
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = System.out;
ps.println("打印流");
ps.println(true);
ps = new PrintStream(new BufferedOutputStream(new FileOutputStream("print.txt")),true);
ps.println("打印流");
ps.println(true);
ps.flush();
ps.close();
//重定向输出端
System.setOut(ps);
System.out.println("change");
//重定向回控制台
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true));
System.out.println("I am backing");
}