目录
1.1 BufferedInputStream(字节缓冲输入流)
1.2 BufferedOutputStream (字节缓冲输出流)
2.1 InputStreamReader(字节输入转换流)
2.2 OutputStreamReader (字节输出转换流)
2.3 案例1:使用上述两种流实现在控制台输入数据即时打印功能
4.2 ObjectOutputStream (对象输出流)
一.缓冲流
1.字节缓冲流
1.1 BufferedInputStream(字节缓冲输入流)
案例:读取文件中的数据打印到控制台
/**
* 四个步骤: 分段读取 文件字节输入流 加入缓冲流
* 1、创建源
* 2、选择流
* 3、操作
* 4、释放资源
*/
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 (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
1.2 BufferedOutputStream (字节缓冲输出流)
/**
* 文件字节输出流 加入缓冲流
*1、创建源
*2、选择流
*3、操作(写出内容)
*4、释放资源
*
*/
//1、创建源
File dest = new File("dest.txt");
//2、选择流
OutputStream os =null;
try {
os =new BufferedOutputStream( new FileOutputStream(dest));
//3、操作(写出)
String msg ="IO is so easy\r\n";
byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码)
os.write(datas,0,datas.length);
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
1.3 利用字节缓冲流实现文件拷贝
/**
* 文件拷贝:文件字节输入、输出流
*
*/
public static void copy(String srcPath,String destPath) {
//1、创建源
File src = new File(srcPath); //源头
File dest = new File(destPath);//目的地
//2、选择流
try( InputStream is=new BufferedInputStream(new FileInputStream(src));
OutputStream os =new BufferedOutputStream( new FileOutputStream(dest)); ) {
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
2.字符缓冲流
2.1 BufferedReader (字符缓冲输入流)
案例:使用字符缓冲输入流读取文件中的数据并打印到控制台
/**
* 四个步骤: 分段读取 文件字符输入流 加入缓冲流
* 1、创建源
* 2、选择流
* 3、操作
* 4、释放资源
*
*
*/
public static void main(String[] args) {
//1、创建源
File src = new File("abc.txt");
//2、选择流
BufferedReader reader =null;
try {
reader =new BufferedReader(new FileReader(src));
//3、操作 (分段读取)
String line =null;
while((line=reader.readLine())!=null) {
//字符数组-->字符串
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 BufferedWriter (字符缓冲输出流)
案例:使用字符缓冲输出流将字符串输出到文件中
/**
* 文件字符输出流 加入缓冲流
*1、创建源
*2、选择流
*3、操作(写出内容)
*4、释放资源
*
*/
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、操作(写出)
writer.append("IO is so easy");
writer.newLine();
writer.append("北京欢迎你");
writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
}
二.字节转换流
2.1 InputStreamReader(字节输入转换流)
2.2 OutputStreamReader (字节输出转换流)
2.3 案例1:使用上述两种流实现在控制台输入数据即时打印功能
/**
* 转换流: InputStreamReader OutputStreamWriter
* 1、以字符流的形式操作字节流(纯文本的)
* 2、指定字符集
*
*/
public class ConvertTest {
public static void main(String[] args) {
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
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) {
System.out.println("操作异常");
}
}
2.4 案例2:下载百度首页html代码
/**
* 转换流: InputStreamReader OutputStreamWriter
* 1、以字符流的形式操作字节流(纯文本的)
* 2、指定字符集
*
*/
public static void main(String[] args) {
try(BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new URL("http://www.baidu.com").openStream(),"UTF-8"));
BufferedWriter writer =
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("baidu.html"),"UTF-8"));){
//3、操作 (读取)
String msg ;
while((msg=reader.readLine())!=null) {
//System.out.println(msg);
writer.write(msg); //字符集不统一不够出现乱码
writer.newLine();
}
writer.flush();
}catch(IOException e) {
System.out.println("操作异常");
}
}
三.数据流
3.1 DataInputStream (数据输入流)
3.2 DataOutputStream(数据输出流)
3.3 案例
/**
* 数据流:
* 1、写出后读取
* 2、读取的顺序与写出保持一致
*
* DataOutputStream
* DataInputStream
* @author TW
*
*/
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();
System.out.println(datas.length);
//读取
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);
}
四.对象流
4.1 ObjectInputStream (对象输入流)
4.2 ObjectOutputStream (对象输出流)
4.3 案例:序列化与反序列化
/**
* 对象流:
* 1、写出后读取
* 2、读取的顺序与写出保持一致
* 3、不是所有的对象都可以序列化Serializable
*
* ObjectOutputStream
* ObjectInputStream
*
*/
//javabean 封装数据
class Employee implements java.io.Serializable{
private transient String name; //该数据不需要序列化
private double salary;
public Employee() {
}
public Employee(String name, double salary) {
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;
}
}
//与数组的交互
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写出 -->序列化
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos =new ObjectOutputStream(new BufferedOutputStream(baos));
//操作数据类型 +数据
oos.writeUTF("编码辛酸泪");
oos.writeInt(18);
oos.writeBoolean(false);
oos.writeChar('a');
//对象
oos.writeObject("谁解其中味");
oos.writeObject(new Date());
Employee emp =new Employee("马云",400);
oos.writeObject(emp);
oos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//读取 -->反序列化
ObjectInputStream ois =new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = ois.readUTF();
int age = ois.readInt();
boolean flag = ois.readBoolean();
char ch = ois.readChar();
System.out.println(flag);
//对象的数据还原
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = 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(employee instanceof Employee) {
Employee empObj = (Employee) employee;
System.out.println(empObj.getName()+"-->"+empObj.getSalary());
}
}
//与文件的交互
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 写出 -->序列化
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("obj.ser")));
// 操作数据类型 +数据
oos.writeUTF("编码辛酸泪");
oos.writeInt(18);
oos.writeBoolean(false);
oos.writeChar('a');
// 对象
oos.writeObject("谁解其中味");
oos.writeObject(new Date());
Employee emp = new Employee("马云", 400);
oos.writeObject(emp);
oos.flush();
oos.close();
// 读取 -->反序列化
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("obj.ser")));
// 顺序与写出一致
String msg = ois.readUTF();
int age = ois.readInt();
boolean flag = ois.readBoolean();
char ch = ois.readChar();
System.out.println(flag);
// 对象的数据还原
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = 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 (employee instanceof Employee) {
Employee empObj = (Employee) employee;
System.out.println(empObj.getName() + "-->" + empObj.getSalary());
}
ois.close();
}
五.打印流
功能:
打印流
添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.- 字符打印流 PrintWriter
- void print(String str): 输出任意类型的数据,
- void println(String str): 输出任意类型的数据,自动写入换行操作
5.1 案例1
/*
* 打印流:
* PrintStream
* PrintWriter
* 可以自动换行,println()
* 不能输出字节,但是可以输出其他任意类型
* 通过某些配置,可以实现自动刷新(只有在调用 println、printf 或 format才有用)
* 也是包装流,不具备写出功能
* 可以把字节输出流转换成字符输出流
*
* 注意:只能输出不能输入
*
*
*/
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
//创建打印流对象
PrintWriter pw = new PrintWriter("b.txt");
//写出数据
pw.write("hello");
pw.write("world");
pw.write("java");
//释放资源
pw.close();
}
}
5.2 案例2
/*
* 打印流的特有功能:
* 自动换行 使用方法println()实现自动换行
* 自动刷新 创建PrintWriter对象时启动自动刷新开关,并且使用println等3个方法可以实现自动刷新
*
* 注意:创建FileWriter对象时boolean参数是是否追加,
* 而创建打印流对象的boolean类型参数是是否自动刷新
*/
public class PrintWriterDemo2 {
public static void main(String[] args) throws IOException {
//创建打印流对象
PrintWriter pw = new PrintWriter(new FileWriter("d.txt"),true);
pw.println("hello");
pw.println("world");
pw.println("java");
//释放资源
pw.close();
}
}
5.3 案例3
- 利用打印流将根目录下的SystemInOutDemo.java复制到d:\\SystemInOutDemo.java下
/*
* 使用打印流复制文本文件
*
* 数据源 SystemInOutDemo.java BufferedReader
* 目的地 d:\\SystemInOutDemo.java PrintWriter
*
*/
public class PrintWriterDemo3 {
public static void main(String[] args) throws IOException {
//创建输入流对象
BufferedReader br = new BufferedReader(new FileReader("SystemInOutDemo.java"));
//创建打印流对象
PrintWriter pw = new PrintWriter(new FileWriter("d:\\SystemInOutDemo.java"),true);
String line;//用于存储读取到的每行数据
while((line = br.readLine()) != null) {
pw.println(line);
}
//释放资源
pw.close();
br.close();
}
}
六.随机流(了解)
6.1 案例1
/**
* 随机读取和写入流 RandomAccessFile
*
*/
public class RandTest01 {
public static void main(String[] args) throws IOException {
//分多少块
File src = new File("src/com/sxt/io/Copy.java");
//总长度
long len = src.length();
//每块大小
int blockSize =1024;
//块数: 多少块
int size =(int) Math.ceil(len*1.0/blockSize);
System.out.println(size);
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
System.out.println(i+"-->"+beginPos +"-->"+actualSize);
split(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
* @param i
* @param beginPos
* @param actualSize
* @throws IOException
*/
public static void split(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/sxt/io/Copy.java"),"r");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
System.out.println(new String(flush,0,len));
actualSize -=len;
}else {
System.out.println(new String(flush,0,actualSize));
break;
}
}
raf.close();
}
//分开思想: 起始、实际大小
public static void test2() throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/sxt/io/Copy.java"),"r");
//起始位置
int beginPos =2+1026;
//实际大小
int actualSize = 1026;
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
System.out.println(new String(flush,0,len));
actualSize -=len;
}else {
System.out.println(new String(flush,0,actualSize));
break;
}
}
raf.close();
}
//指定起始位置,读取剩余所有内容
public static void test1() throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/sxt/io/Copy.java"),"r");
//随机读取
raf.seek(2);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
System.out.println(new String(flush,0,len));
}
raf.close();
}
}
6.2 案例2
/**
* 随机读取和写入流 RandomAccessFile
* 分割文件演示
*
*/
public class RandTest02 {
public static void main(String[] args) throws IOException {
//分多少块
File src = new File("p.png");
//总长度
long len = src.length();
//每块大小
int blockSize =1024;
//块数: 多少块
int size =(int) Math.ceil(len*1.0/blockSize);
System.out.println(size);
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
System.out.println(i+"-->"+beginPos +"-->"+actualSize);
split(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
* @param i
* @param beginPos
* @param actualSize
* @throws IOException
*/
public static void split(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("p.png"),"r");
RandomAccessFile raf2 =new RandomAccessFile(new File("dest/"+i+"p.png"),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
}
6.3 案例3
/**
* 面向对象思想封装 分割
* @author 裴新
*
*/
public class SplitFile {
//源头
private File src;
//目的地(文件夹)
private String destDir;
//所有分割后的文件存储路径
private List<String> destPaths;
//每块大小
private int blockSize;
//块数: 多少块
private int size;
public SplitFile(String srcPath,String destDir) {
this(srcPath,destDir,1024);
}
public SplitFile(String srcPath,String destDir,int blockSize) {
this.src =new File(srcPath);
this.destDir =destDir;
this.blockSize =blockSize;
this.destPaths =new ArrayList<String>();
//初始化
init();
}
//初始化
private void init() {
//总长度
long len = this.src.length();
//块数: 多少块
this.size =(int) Math.ceil(len*1.0/blockSize);
//路径
for(int i=0;i<size;i++) {
this.destPaths.add(this.destDir +"/"+i+"-"+this.src.getName());
}
}
/**
* 分割
* 1、计算每一块的起始位置及大小
* 2、分割
* @throws IOException
*/
public void split() throws IOException {
//总长度
long len = src.length();
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
splitDetail(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
* @param i
* @param beginPos
* @param actualSize
* @throws IOException
*/
private void splitDetail(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(this.src,"r");
RandomAccessFile raf2 =new RandomAccessFile(this.destPaths.get(i),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
/**
* 文件的合并
* @throws IOException
*/
public void merge(String destPath) throws IOException {
//输出流
OutputStream os =new BufferedOutputStream( new FileOutputStream(destPath,true));
Vector<InputStream> vi=new Vector<InputStream>();
SequenceInputStream sis =null;
//输入流
for(int i=0;i<destPaths.size();i++) {
vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
}
sis =new SequenceInputStream(vi.elements());
//拷贝
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=sis.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
sis.close();
os.close();
}
public static void main(String[] args) throws IOException {
SplitFile sf = new SplitFile("src/com/sxt/io/SplitFile.java","dest") ;
sf.split();
sf.merge("aaa.java");
}
}