IO 流
流: 一连串流动的数据 管道
数据源 目的地
以谁为中心==>程序(大脑)
流的分类:
流向:
输入流
输出流
操作单元:
字节流
字符流
功能:
节点流:直接从数据源到目的地
功能流:经过包装
一、节点流
(1)字节流:万能流
字节输入流
InputStream 流向:输入流 操作单元:字节流 功能:节点流
此抽象类是表示字节输入流的所有类的超类。 不能实例化
public class FileInputStream
extends InputStream
从文件系统中的某个文件中获得输入字节
read() 每次从输入流中读入一个字节的内容,想要读入多个 手动一个字节一个字节读入
int read(byte[] b) 一个字节数组一个字节数组读入
操作代码:
1.输入流
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoInputStreamTest {
public static void main(String[] args) throws IOException {
File src=new File("D:/test.txt");
src.createNewFile();
System.out.println(src.createNewFile());//检测文件是否创建成功
InputStream is=new FileInputStream(src);
/*1.单个字节读取
is.read(); //返回int类型,如果返回-1则文件内容读取完毕
System.out.println((char)is.read()); //一次只能读一个字节*/
/*2.单个字节循环读取
int num=-1; //定义一个num接受每次读入的字节,因为每次读取会进入下一个字节,再输出则是下一次读取的字节内容
while((num=is.read())!=-1){ //判断如果返回-1则训话结束
System.out.print((char)num);
}
is.close();*/
//3.利用byte数组进行一个数组一个数组的读取
byte[] car=new byte[1024];
int len=-1;
while((len=is.read(car))!=-1){
System.out.print(new String(car,0,len));
}
}
}
2.输出流:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IoOutPutStreamTest {
public static void main(String[] args) throws IOException {
//选择流,如果目的地文件不存在则会自动创建文件,但文件夹不会
OutputStream os=new FileOutputStream("E:/xixi.txt",true);//appand true追加否则覆盖
//准备数据
int i=99;
String str="halo-可爱女人";
byte[] car=str.getBytes();
//输出到指定文件夹中
os.write(i);
os.write(97);
os.write(car);
os.flush();
os.close();
}
}
下面实现利用写入写出实现copy功能:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyFile1 {
public static void copyFilemode(String src,String dest) {
copyFilemethod(new File(src),new File(dest));
}
public static void copyFilemethod(File src,File dest) {
//选择流
InputStream is=null;
OutputStream os=null;
//File file=new File("D:/text.txt");
try {
//System.out.println(file.createNewFile());
is=new FileInputStream(src);
os=new FileOutputStream(dest);
//准备数组
byte[] car=new byte[1024];
//copy
int len=-1;
while((len=is.read(car))!=-1){
os.write(car,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
if(os!=null&&is!=null){
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(2)字符流 :
只能操作纯文本的内容 .txt .html 节点流 字符流
Reader 字符输入流 抽象类 FileReader 输入流
read()| read(char[]) + close()
Writer 字符输出流 抽象类 FileWriter 输出流
代码演示:
输入流:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class CharReader {
public static void main(String[] args) {
Reader reader=null;
try {
//选择流
reader=new FileReader("D:/text.txt");
//准备数组
char[] car=new char[1024];
//读取char
/*1.单个读取
try {
System.out.println((char)(reader.read()));
} catch (IOException e) {
e.printStackTrace();
}*/
//2.循环数组读取
int len=-1;
while((len=reader.read(car))!=-1){
System.out.println(new String(car,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
输出流:
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class CharWrite {
public static void main(String[] args) {
//选择流
Writer writer=null;
try {
writer=new FileWriter("D:text.txt",true);
//准备内容
String str="农夫山泉有点甜";
char[] arr={'小','龙','人','奶','糖'};
char c='a';
writer.write(c);
writer.append(str);
writer.write(arr);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
实现copy功能:
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class CopyFile2 {
public static void main(String[] args) {
//创建一个文件
File file=new File("D:/test.txt");
try {
System.out.println(file.createNewFile());
} catch (IOException e1) {
e1.printStackTrace();
}
//选择流
Reader reader=null;
Writer writer=null;
try {
reader=new FileReader("D:/test.txt");
writer=new FileWriter("D:/dest.txt");
//准备内容
char[] car=new char[1024];
int len=-1;
while((len=reader.read(car))!=-1){
System.out.println(len);
writer.write(car,0,len);
}
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader!=null&&writer!=null){
try {
writer.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二、功能流
(1)转换流(了解)
可以把字节流转为字符流使用
InputStreamReader(InputStream,String charset)
OutputSteamWriter(OutputSteam,String charset)
可能出现乱码的情况:
1.字符编码格式不统一
2.缺少字节个数
不同编码格式汉字所占字节大小:
ISO-8859-1 1个字节
GBK 2个字节
GB2312 2个字节
UTF-8 3个字节
代码演示:
public class ConvertLiu {
public static void main(String[] args) throws IOException {
File file=new File("D:/text.txt");
boolean b=file.createNewFile();
/*Reader read=new InputStreamReader(new FileInputStream("D:/text.txt"));//多态,InputStreamReader继承自Reader
Writer wirt=new OutputStreamWriter(new FileOutputStream("D:/dext.txt"));*/
//缓冲类
BufferedReader read=new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream("D:/text.txt"))));
BufferedWriter writ=new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("D:/dext.txt"))));
String msg=null;
while((msg=read.readLine())!=null){
writ.write(msg);
writ.newLine();
}
writ.flush();
writ.close();
read.close();
}
}
(2)缓冲流:
缓冲流:增强功能,提高性能
使用:功能流(节点流)
字节输入缓冲流 BufferedInputStream
字节输出缓冲流 BufferedOutputStream
无新增方法,可以发生多态
代码实例:
字节缓冲流
public class Bufferedbyteliu {
public static void main(String[] args) {
InputStream is=null;
OutputStream os=null;
try {
is=new BufferedInputStream(new FileInputStream("D:/text.txt")) ;
os=new BufferedOutputStream(new FileOutputStream("D:/dext.txt"));
byte[] car=new byte[1024];
int len=-1;
try {
while((len=is.read(car))!=-1){
System.out.println(new String(car,0,len));
os.write(car,0,len);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(is!=null){
try {
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符缓冲流
public class Bufferedcharliu {
public static void main(String[] args) throws IOException {
//字符缓冲流有新增方法readLine和newLine,因此不能使用多态
//选择流
BufferedReader read;
BufferedWriter writ;
read=new BufferedReader(new FileReader("D:/text.txt"));
writ=new BufferedWriter(new FileWriter("D:/dext.txt"));
//准备卡车
/*char[] car=new char[1024];
int len=-1;
while((len=read.read(car))!=-1){
writ.write(car,0,len);
}*/
//用Buffered缓冲流新增的方法读入写出
String msg=null;
while((msg=read.readLine())!=null){
writ.write(msg);
writ.newLine();
}
writ.flush();
read.close();
writ.close();
}
}
(3)基本数据类型流 :
读写带有基本数据类型的数据+String
基本数据类型流(字节节点流)
DataInputStream(InputStream): 新增方法: readXXX()
DataOutputStream(OutputStream): 新增方法: writeXXX()
EOFException:文件存在,但是内部无法读取,不是源文件
代码实例:
public class DataLiuTest {
public static void main(String[] args) throws IOException {
write("D:/text.txt");
read("D:/text.txt");
//copy
copy();
}
public static void write(String str) throws IOException {
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(str)));
int i=1314;
double d=5.20;
boolean b=false;
String s="华尔兹剑舞";
dos.writeInt(i);;
dos.writeDouble(d);
dos.writeBoolean(b);
dos.writeUTF(s);
dos.flush();
dos.close();
}
public static void read(String dest) throws IOException {
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(dest) ));
int i=dis.readInt();
Double d=dis.readDouble();
Boolean b=dis.readBoolean();
String s=dis.readUTF();
System.out.println(i+"-->"+d+"-->"+b+"-->"+s);
dis.close();
}
public static void copy() throws IOException{
BufferedReader rea=new BufferedReader(new FileReader("D:/text.txt"));
BufferedWriter wri=new BufferedWriter(new FileWriter("D:/dext.txt"));
String msg=null;
while((msg=rea.readLine())!=null){
wri.write(msg);
}
wri.flush();
wri.close();
rea.close();
}
}
(4)对象流:
序列化:将对象信息转为可存储或者可传输的信息格式
序列化输出流 ObjectOutputStream
反序列化输入流 ObjectInputStream
新增方法 readXxx() writeXxx()
先序列化后反序列化
不是所有的类都能序列化 实现一个空接口 java.io.Serializable
不是所有的属性都需要序列化 transient
静态的内容不能被序列化 默认值
如果父类实现了Serializable,子类中所有的内容都可以序列化
如果子类实现Serializable,父类中的内容没有序列化能力,只有子类的内容有
代码实例:
public class Objecttest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
write("D:/text.txt");
read("D:/text.txt");
}
public static void write(String pathname) throws FileNotFoundException, IOException {
ObjectOutputStream ops=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(pathname)));
Dog dog=new Dog("kitty","白色",3,"二哈",40.2);
char[] arr={'s','h','s','x','t'};
ops.writeObject(dog);
ops.writeObject(arr);
ops.flush();
ops.close();
}
public static void read(String pathname) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ips=new ObjectInputStream(new BufferedInputStream(new FileInputStream(pathname)));
Dog dog1 =(Dog)(ips.readObject());
char[] arr1=(char[])(ips.readObject());
System.out.println(dog1);
System.out.println(arr1);
ips.close();
}
}
class Dog implements Serializable{
private String name;
private String color;
private int age;
private String type;
private double weight;
public Dog() {
// TODO Auto-generated constructor stub
}
public Dog(String name, String color, int age, String type, double weight) {
super();
this.name = name;
this.color = color;
this.age = age;
this.type = type;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Dog [name=" + name + ", color=" + color + ", age=" + age + ", type=" + type + ", weight=" + weight
+ "]";
}
}
难点:利用流和文件实现文件目录的copy
实现代码:
import java.io.File;
import java.io.IOException;
import javax.print.attribute.standard.Destination;
import com.shsxt.iobyteliu.CopyFile1;
public class Copydir {
public static void main(String[] args) throws IOException {
copyDir("D:/Textcopydir","E:/");//src是源文件绝对路径,dest是将复制文件放置的路径
}
//"D:/AAA/BBB" "E/AAA:|E:/AAA/"
public static void copyDir(String src,String dest) throws IOException {
//判断不能复制与源文件同目录下
int i=src.lastIndexOf("/");
String str=src.substring(0,i);
String str1=src.substring(0,i+1);
if(str==dest|str1==dest){
throw new IOException("不能复制与源文件同目录下");
}
copyDir(new File(src), new File(dest));
}
public static void copyDir(File src,File dest) throws IOException {
//判断不能复制在源路径子路径下
if(dest.getAbsolutePath().contains(src.getAbsolutePath())){
//如果是子文件夹,则子文件夹的路径会包括源文件夹路径,可以尝试打开本地文件看看
throw new IOException("不能复制在源路径子路径下");
} //过滤以上两个条件时,则要复制文件了,得知道复制文件的具体路径
copyDirDetails(src, new File(dest,src.getName() ));
}
public static void copyDirDetails(File src,File dest) {
//声明文件时文件可以不存在,如果是文件则系统自动创建,但是文件夹则不会,所以需要判断复制的文件或者文件夹是否存在
if(!dest.getParentFile().exists()){//判断文件放置的位置有没有,没有则创建
dest.getParentFile().mkdirs();
}
if(src.isFile()){
CopyFile1.copyFilemethod(src, dest);//copy文件的工具类
}
if(src.isDirectory()){
dest.mkdirs();//经过前面的步骤可以保证放置的位置,此时则创建要复制的文件夹
File[] files=src.listFiles();//遍历源文件内部的文件
for(File srcFiles:files){
copyDirDetails(srcFiles,new File(dest,srcFiles.getName()));
}
}
}
}