处理流
引入1_模拟方法器对人的声音的放大
package com.sxt.IO_01;
public class Decorate {
/**
*@描述:
* @param args
*/
public static void main(String[] args) {
Person p = new Person();
p.say();
Amplify amplify = new Amplify(p);
amplify.say();
}
}
/**
*
* @描述:定义接口
*/
interface Say{
void say();
}
/**
*
* @描述:定义人并实现承接口
*/
class Person implements Say{
int voice = 10;
@Override
public void say() {
System.out.println("原来声音大小为:"+this.voice);
}
}
/**
*
* @描述:定义放大器并继承接口对声音进行放大
*/
class Amplify implements Say{
private Person p;
public Amplify(Person p) {
this.p = p;
}
@Override
public void say() {
System.out.println("放大后的声音为:"+p.voice * 1000);
}
}
引入2_模拟咖啡加料
package com.sxt.IO_01;
/**
* 1、抽象组件(饮料):需要装饰的抽象对象(是接口或抽象父类)
* 2、具体组件(咖啡):需要装饰的对象
* 3、抽象装饰类:包含了对抽象组件的引用以及装饰类所共有的方法
* 4、具体装饰类:被装饰的对象
* @描述:模拟咖啡
*/
public class Decorate_Coffe {
public static void main(String[] args) {
Drink coffee = new Coffee();
System.out.println("价格:"+coffee.cost());
System.out.println("信息:"+coffee.info());
Drink milk = new Milk(coffee);
System.out.println("---------------");
System.out.println("价格:"+milk.cost());
System.out.println("信息:"+milk.info());
System.out.println("------------------");
Drink suger = new Suger(coffee);
System.out.println("---------------");
System.out.println("价格:"+suger.cost());
System.out.println("信息:"+suger.info());
}
}
//1、抽象组件
interface Drink{
//费用
double cost();
//说明
String info();
}
//2、具体组件
class Coffee implements Drink{
double price = 1;
String name ="原味咖啡";
@Override
public double cost() {
return price;
}
@Override
public String info() {
return name;
}
}
//3、抽象装饰类
abstract class Decorate implements Drink{
//对抽象组件的引用
Drink drink;
protected Decorate(Drink drink) {
this.drink = drink;
}
@Override
public double cost() {
return this.drink.cost();
}
@Override
public String info() {
return this.drink.info();
}
}
//4、具体装饰类
//4_1装饰类1
class Milk extends Decorate{
Milk(Drink drink) {
super(drink);
}
@Override
public double cost() {
return super.cost()*4;
}
@Override
public String info() {
return super.info()+"加入了牛奶";
}
}
//4_2、装饰类2
class Suger extends Decorate{
Suger(Drink drink) {
super(drink);
}
@Override
public double cost() {
return super.cost()*2;
}
@Override
public String info() {
return super.info()+"加入了糖";
}
}
装饰流
引入:由于Io的操作直接影响着程序性能高低。
- 一件一件的搬家(蚂蚁搬家)
- 一卡车一卡车的搬家(搬家公司搬家)
- 将物品打包(多个包)然后直接一次性的搬走(打包,不需要频繁的对硬盘进行操作)
字节缓冲流
作用:
- 提高了字节数据读写的性能。
- 任何的处理流最底层的都是节点流
- 流的释放只需要释放最外层的处理流(因为它的内部会自动释放内部的节点流)
区别:在节点流的外面套上字节缓冲流即可,其他操作不变
利用字节缓冲输入流来读取数据
package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class bufferInputStrea {
public static void main(String[] args) {
//1.创建源
File file = new File("des.txt");
//2.选择流
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
//3.操作(读取数据)
byte[] flush = new byte[1024];
//接收长度
int len = -1;
try {
while((len = in.read(flush)) != -1){
//字节数组-->字符串(解码)
String str = new String(flush,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符缓冲流
注意:
- 在使用字符缓冲流的时候尽量不使用多态,因为相对于它的父类它自己本身新增的方法更为常用
- 在节点流的外面套上字符缓冲流就可以
利用字符缓冲输入流来读取数据
package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class bufferReader {
public static void main(String[] args) {
//创建源
File file = new File("hello.txt");
//选择流
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
//读取数据(操作):当读取的数据不存在时返回null,读取的数据存放在line中
String line;
while((line = reader.readLine())!= null){
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭资源
try {
if(reader != null){
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
利用字符缓冲输出流来写入数据
注意:这里使用到了BufferedWriter特有的换行方法
package com.sxt.IO_03;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class bufferWriter {
/**
*@描述:
* @param args
*/
public static void main(String[] args) {
//1.准备源
File des = new File("src2/com/sxt/IO_03/des1.txt");
//2.选择字符输出流
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(des));
} catch (IOException e) {
e.printStackTrace();
}
//3.读取操作
//3.1准备要写出的数据
String data = "我能行!加油!";
//3.2准备小车
char[] flush = new char[1024];
//3.3将数据放进小车中
flush = data.toCharArray();
try {
//3.3读取操作
writer.write(flush);
//BufferedWriter特有的换行方法
writer.newLine();
writer.append("嗯,是的就是这样的!");
//3.4flush操作
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(writer != null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
利用字符缓冲流来进行文件之间的复制
注意:
- 逐行读取数据
- 将数据逐行写出
- 换行输出
package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class bufferReader_Writer_copy {
public static void main(String[] args) {
//1.准备源
File src = new File("src.txt");
File des = new File("src2/com/sxt/IO_03/des3.txt");
//2.选择流
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(src));
writer = new BufferedWriter(new FileWriter(des));
//3.逐行读取数据
String line;
while((line = reader.readLine())!= null){
//将数据逐行写出
writer.write(line);
//换行输出
writer.newLine();
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//4.关闭
close(reader,writer);
}
}
public static void close(Closeable ... clos){
for(Closeable clo : clos){
if(clo != null){
try {
clo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
转换流
InputStreamReader和OutputStreamWriter是字节流和字符流之间的桥梁,可以将字节流转换为字符流,并可以为字节流指定字符集,可以处理一个一个的字符
作用:
- 作为字节流和字符流的桥梁,以字符流的形式操作字节流(纯文本)
- 分别具有解码和编码的作用
- InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的
charset
将其解码为字符(解码) - OutputStreamWriter是字符流到字节流的桥梁:向其写入的字符编码成使用指定的字节
charset
(编码)
作用1:以字符流的形式操作字节流(纯文本)
注意:
- 涉及到字符数据的操作,可以加一个字符缓冲流来提高效率
- 在对数据进行写入完成要记得强制刷新,否则控制台可能不会显示输入的数据
package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Convert {
public static void main(String[] args) {
// //操作System.in(字节输入流)和System.out(字节输出流)
// InputStreamReader in = new InputStreamReader(System.in);
// OutputStreamWriter out = new OutputStreamWriter(System.out);
//由于这里读取和写出操作的都是字符,因此加了一个缓冲来提高效率
//字节输入流--字符输入流--修饰缓冲
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//字节输出流--字符输出流--修饰缓冲
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
//2、循环获取键盘的输入(遇到exit退出循环),打印此内容
String mes = "";
while(!mes.equals("exit")){
try {
//逐行读取数据
mes = reader.readLine();
//逐行对数据进行写人
writer.write(mes);
writer.newLine();
//对缓冲区进行强制刷新
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
作用2:指定字符集
package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class Convert1 {
/**
* 作用2:指定字符集编码
*@描述:转换流
* @param args
*/
public static void main(String[] args) {
//操作网络流(字节节点流),下载百度源码
try {BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new URL("http://www.baidu.com").openStream(),"UTF-8"));
//对数据进行读取操作
String mes = "";
while((mes = reader.readLine())!= null){
System.out.print(mes);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据流
dataOutputStream()
dataInputStream()
注意:
- 先写出后读取
- 读取的数据类型要和写入的数据类型一致
package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class dataIO {
/**
*@描述:
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.数据的写入
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(bos));
dos.writeUTF("张三");
dos.writeInt(24);
dos.writeChar('男');
//注意数据在写入之后要记得flush,否则会出现异常
dos.flush();
//2.数据的读取
byte[] datas = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(datas);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(bis));
String name = dis.readUTF();
int age = dis.readInt();
char sex = dis.readChar();
System.out.println(name + age + sex);
}
}
对象流
注意:
- 先写出后读取
- 读取的顺序和写出的顺序一致
- 不是所有的对象都可以序列化(必须实现一个接口Serializable)
序列化:ObjectOutputStream:只有支持serializable接口的对象才能写入流中。(编写的原始数据和对象。)
反序列化:ObjectInputStream:只能从流中读取支持java.io.serializable或java.io.externalizable接口的对象
package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Date;
public class objectIO {
/**
*@描述:对象流
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.数据的写入
OutputStream os = new FileOutputStream("src2/com/sxt/IO_03/des.txt");
ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(os));
oos.writeObject("哈哈,每天都是那么的美好!");
oos.writeObject(new Person("张三",19));
oos.writeObject(new Date());
oos.flush();
oos.close();
//2.数据的读取
InputStream is = new FileInputStream("src2/com/sxt/IO_03/des.txt");
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(is));
Object info = ois.readObject();
Object personInfo = ois.readObject();
Object date = ois.readObject();
if(info instanceof String){
String info1 = (String)info;
System.out.println(info1);
}
if(personInfo instanceof Person){
Person personStrInfo1 = (Person)personInfo;
System.out.println(personStrInfo1);
}
if(date instanceof Date){
Date date1 = (Date)date;
System.out.println(date1);
}
}
}
class Person implements Serializable{
//表示该数据不需要被序列化
transient String name;
int age;
Person(String name, int age){
this.name = name;
this.age = age;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return name+":" +age;
}
}
打印流
要知道的:System类
System
类包含几个有用的类字段和方法。 它不能被实例化。System
类提供的System
包括标准输入,标准输出和错误输出流;
-
-
返回类型 方法和描述 static PrintStream
err
“标准”错误输出流。static InputStream
in
“标准”输入流。static PrintStream
out
“标准”输出流。
printStream练习
-
package com.sxt.IO_03;
import java.io.BufferedOutputStream;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
public class printStream_demon {
/**
*@描述:打印流PrintStream
* @param args
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
PrintStream ps = System.out;
ps.println("第一次被打印(在控制台中显示打印内容)");
//PrintStream(OutputStream out, boolean autoFlush) 将内容打印到文件中
//(注意要"自动刷新,否则打印的内容可能会不显示")
ps = new PrintStream(
new BufferedOutputStream(
new FileOutputStream("src2/com/sxt/IO_03/printText.txt")),true);
ps.println("第二次被打印了(在指定文件中被显示打印内容)");
//重定向到输出端
//static void setOut(PrintStream out) 重新分配“标准”输出流。
System.setOut(ps);
System.out.println("第三次被打印(打印内容给指定的输出端)");
//重定向到控制台(注意要"自动刷新,否则打印的内容可能会不显示")
System.setOut(
new PrintStream(
new BufferedOutputStream(
new FileOutputStream(FileDescriptor.out)),true));
System.out.println("第四被打印(打印的东西给控制台显示)");
ps.close();
}
}
printStream练习
package com.sxt.IO_03;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class printWriter_demon {
/**
*@描述:PrinrWriter
* @param args
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
PrintWriter pw = new PrintWriter(
new BufferedOutputStream(
new FileOutputStream("src2/com/sxt/IO_03/printText01.txt")),true);
pw.println("被打印在指定文件中了");
}
}
随机访问
RandomAccessFile
package com.sxt.IO_03;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class randomAccessFile_Demon {
/**
*@描述:
*void seek(long pos) 设置文件指针偏移,从该文件的开头测量,
*发生下一次读取或写入。
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.指定要分隔的文件
File file = new File("src2/com/sxt/IO_03/RandomText.txt");
//确定文件的长度
long len = file.length();
System.out.println(len);
//确定每块的大小
int blockSize = 100;
//一共分隔的块数
int blockNum = (int)(Math.ceil((len*1.0)/blockSize));
System.out.println(blockNum);
//每次读取的起始位置
int beginPos = 0;
//每次分配块的实际大小
int actualSize = (int)(blockSize > len ? len:blockSize);
for(int i = 1; i <= blockNum; i++){
beginPos = i * blockSize;
if(i == blockNum){//最后一块(可能装不满)
actualSize = (int) len;
}else{
actualSize = blockSize;
len -= actualSize;
}
System.out.println(i +"块---> 起始位置:"
+ beginPos + "----> 实际读取块的大小:"
+actualSize);
}
}
/**
*
*@描述:按照分块的形式对数据进行读取
* @throws IOException
*/
public static void RandomRead1() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
new File("src2/com/sxt/IO_03/RandomText.txt"),"r");
//分块读取数据:
//起始位置
int beginPos = 4;
//实际需要读取数据的大小
int actualSize = 106;
//开始读取数据
int len = -1;
byte[] flush = new byte[1024];
raf.seek(beginPos);
while((len = raf.read(flush)) != -1){
if(len < actualSize){//获取本次读取的所有内容
raf.read(flush);
actualSize -= len;
System.out.println(new String(flush));
}else{
raf.read(flush,0,actualSize);
System.out.println(new String(flush,0,actualSize));
}
}
raf.close();
}
/**
*
*@描述:指定起始读取位置,读取剩余所有内容;
* @throws IOException
*/
public static void RandomRead() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
new File("src2/com/sxt/IO_03/RandomText.txt"),"r");
//开始读取数据
byte[] flush = new byte[1024];
int len= -1;
raf.seek(2);
while((len = raf.read(flush))!= -1){
System.out.println(new String(flush,0,len));
}
raf.close();
}
}