您的位置:首页 > 编程语言 > Java开发

Java基础——IO流(字节流、字符流、文件与文件夹的拷贝、缓冲流、转换流、基本数据类型流、序列化和反序列化)

2019-06-13 08:27 671 查看

一. IO 流
1.流的概念

流是一个抽象、动态的概念,是一连串连续动态的数据集合。
对于输入流而言,数据源就像水箱,流(stream)就像水管中流动着的水流,程序就是我们最终的用户。我们通过流(A Stream)将数据源(Source)中的数据(information)输送到程序(Program)中。
对于输出流而言,目标数据源就是目的地(dest),我们通过流(A Stream)将程序(Program)中的数据(information)输送到目的数据源(dest)中。

2.流的分类
按流的方向分类

  1. 输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。
  2. 输出流:数据流向是程序到目的地(以OutPutStream、Writer结尾的流)。

按操作单元分类

  1. 字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,如FileInputStream、FileOutputStream。
    2. 字符流:以字符为单位获取数据,命名上以Reader/Writer结尾的流一般是字符流,如FileReader、FileWriter。

按处理对象不同(功能)分类
1.节点流:可以直接从数据源或目的地读写数据,如FileInputStream、FileReader、DataInputStream等。
2.处理流(功能流):不直接连接到数据源或目的地,是”处理流的流”。通过对其他流的处理提高程序的性能,如BufferedInputStream、BufferedReader等。处理流也叫包装流。
节点流处于IO操作的第一线,所有操作必须通过它们进行;处理流可以对节点流进行包装,提高性能或提高程序的灵活性。

3.四大IO抽象类
· InputStream
此抽象类是表示字节输入流的所有类的父类。InputSteam是一个抽象类,它不可以实例化。 数据的读取需要由它的子类来实现。根据节点的不同,它派生了不同的节点流子类 。
继承自InputSteam的流都是用于向程序中输入数据,且数据的单位为字节(8 bit)。
常用方法:
int read():读取一个字节的数据,并将字节的值作为int类型返回(0-255之间的一个值)。如果未读出字节则返回-1(返回值为-1表示读取结束)。
void close():关闭输入流对象,释放相关系统资源。
· OutputStream
此抽象类是表示字节输出流的所有类的父类。输出流接收输出字节并将这些字节发送到某个目的地。
常用方法:
void write(int n):向目的地中写入一个字节。
void close():关闭输出流对象,释放相关系统资源。
· Reader
Reader用于读取的字符流抽象类,数据单位为字符。
int read(): 读取一个字符的数据,并将字符的值作为int类型返回(0-65535之间的一个值,即Unicode值)。如果未读出字符则返回-1(返回值为-1表示读取结束)。
void close() : 关闭流对象,释放相关系统资源。
· Writer
Writer用于写入的字符流抽象类,数据单位为字符。
void write(int n): 向输出流中写入一个字符。
void close() : 关闭输出流对象,释放相关系统资源。

4.字节流(万能流)***
字节输入流
InputStream 流向:输入流 操作单元:字节流 功能:节点流
此抽象类是表示字节输入流的所有类的超类。 不能实例化

FileInputStream 从文件系统中的某个文件中获得输入字节

read() 每次从输入流中读入一个字节的内容,想要读入多个,只能手动一个字节一个字节读入

int read(byte[] b) 一个字节数组一个字节数组读入

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/*
*  int read(byte[] b)  一个字节数组一个字节数组读入
*/
public class ByteDemo02 {
public static void main(String[] args) {
//1.选择流
InputStream is=null;
try {
is=new FileInputStream("D:/test.txt");
//2.准备卡车
byte[] car=new byte[1024];//一般使用1024或1024的整数倍
//3.操作  读入   read(byte[]) 读到字节数组中多少个数的数据返回值为多少,没有读到返回-1
//			int len=is.read(car);

//读取  重读读入  通过字节数组
int len=-1;
while((len=is.read(car))!=-1){
//4.处理数据
System.out.println(len); //11
System.out.println(new String(car, 0, len));
}

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//5.关闭
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

字节输出流
OutputStream 此抽象类是表示输出字节流的所有类的超类。

FileOutputStream 文件输出流是用于将数据写入 File的输出流。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

//字节输出流  OutputStream
public class ByteDemo03 {
public static void main(String[] args) throws IOException {
//1.选择流  如果目的地的文件不存在系统会自动创建指定文件,文件夹不会自动创建
////boolean append  true追加 false不追加(默认)
OutputStream os=new FileOutputStream("D:/hehe.txt",true);
//2.准备数据
int num=97;
String str="周杰伦-晴天";
byte[] car=str.getBytes();
//3.写出
os.write(num);
os.write(98);
os.write(car);
//4.强制刷出
os.flush();
//5.关闭
os.close();
}
}
文件的拷贝
//文件拷贝:   数据源-->程序-->目的地

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

//文件拷贝:   数据源-->程序-->目的地
public class CopyFile04 {
public static void main(String[] args) {
//1.选择流
InputStream is=null;
java.io.OutputStream os=null;
try {
is=new FileInputStream("D:/IMG_0024.JPG");
os=new FileOutputStream("D:/IMG_024.JPG");
//2.准备卡车
byte[] car=new byte[1024];
//3.读入写出
int len=-1; //读入到小卡车中数据的个数
while((len=is.read(car))!=-1){
os.write(car, 0, len);
}
//4.刷出--刷新此输出流并强制写出所有缓冲的输出字节。
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(os!=null){
os.close();
}
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

文件夹的拷贝

import java.io.File;
import java.io.IOException;

/*
* 文件夹的拷贝
*/
public class CopyDir {
public static void main(String[] args) throws IOException {
copyDir("D:/A", "C:");
}
/*
* 1.不能把文件拷贝到文件所在路径下
*/
public static void copyDir(String src,String dest) throws IOException {
// 判断/最后一次出现的位置索引
int index=src.lastIndexOf("/");
String str=src.substring(0, index);
if(src.equals(dest) || (src+"/").equals(dest)){
throw new IOException("目标路径不能为源文件路径的子路径");
}
copyDir(new File(src),new File(dest));
}
/*
* 2.目标路径不能为源文件路径的子路径下
*/
private static void copyDir(File src,File dest) throws IOException {
if(dest.getAbsolutePath().contains(src.getAbsolutePath())){
throw new IOException("目标路径不能为源文件路径的子路径下");
}
//目标路径:完整路径
copyDirDetils(src, new File(dest,src.getName()));
}
private static void copyDirDetils(File src,File dest){
if(src.isFile()){
//如果目标文件所在路径文件存在不存在的情况,就创建多个不存在的文件夹
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdirs();
}
//调用拷贝文件类
CopyUtil.copyFile(src, dest);
}else if(src.isDirectory()){
//创建目标路径所有不存在的文件夹
dest.mkdirs();
File[] file=src.listFiles();
for(File srcFile:file){
copyDirDetils(srcFile, new File(dest,srcFile.getName()));
}
}
}
}

5.字符流
字符流 :只能操作纯文本的内容 .txt .html 节点流 字符流

字符输入流
Reader 字符输入流 抽象类 FileReader 输入流
主要方法:read() | read(char[]) + close()

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

//字符输入流
public class CharDemo01 {
public static void main(String[] args) throws IOException {
//1.选择流
Reader reader=new FileReader("D:/test.txt");
//2.卡车
char[] car=new char[1024];
//3.读入
//逐个打印
//System.out.println((char)(reader.read()));
int len=-1;
while((len=reader.read(car))!=-1){
System.out.println(new String(car,0,len));
}
reader.close();
}
}

字符输出流
Writer 字符输出流 抽象类 FileWriter 输出流
FileWriter write() | write(char[]) | append() +flush() + close()

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
//字符输出流
public class CharDemo02 {
public static void main(String[] args) {
//1.选择流
Writer writer=null;
try {
writer=new FileWriter("D:/haha.txt");
//2.准备数据
String str="伤心的人别听慢歌";
char[] arr={'-','五','月','天'};
//3.写出
writer.append(str);
writer.write(arr);
//4.刷出
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

字符流实现文件拷贝
1.文件–>程序 输入
2.程序–>文件 写出

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

/*字符流实现文件拷贝:
1.文件-->程序  输入
2.程序-->文件 写出*/
public class CopyFile03 {
public static void main(String[] args) {
//1.选择流
Reader reader=null;
Writer writer=null;
try {
reader=new FileReader(new File("D:/test.txt"));
writer=new FileWriter(new File("D:/dest.txt"));
//2.小卡车
char[] car=new char[1024];
//3.读写
int len=-1;
while((len=reader.read(car))!=-1){
writer.write(car, 0, len);
}
//4.刷出
writer.flush();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

6.缓冲流
功能流的一种:
缓冲流:增强功能,提高性能
使用:功能流(节点流)
字节缓冲流
字节输入缓冲流 BufferedInputStream
字节输出缓冲流 BufferedOutputStream
无新增方法,可以发生多态

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

//字节缓冲流
public class BufferedInputStreamDemo {
public static void main(String[] args) {
//1.选择流
InputStream  is=null;
OutputStream os=null;
try {
is=new BufferedInputStream(new FileInputStream("D:/test.txt"));
os=new BufferedOutputStream(new FileOutputStream("D:/hehe.txt"));
//准备卡车
byte[] car=new byte[1024];
//3.读入写入
int len=-1;
while((len=is.read(car))!=-1){
os.write(car, 0, len);
}
//刷出
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if(os!=null){
os.close();
}
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

字符缓冲流
BufferedReader 新增方法 readLine() 读取一行
BufferedWriter 新增方法 newLine() 写出换行符
不能发生多态,因为父类引用对子类新增方法不可见

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

//字符缓冲流
public class BufferedReaderDemo {
public static void main(String[] args) {
//1.选择流
BufferedReader reader=null;
BufferedWriter writer=null;
try {
reader=new BufferedReader(new FileReader("D:/haha.txt"));
writer=new BufferedWriter(new FileWriter("D:/heihei.txt"));
//2.读入写出
String msg=null;
while((msg=reader.readLine())!=null){
writer.write(msg);
writer.newLine();
}
//3.刷出
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
//关闭
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

7.转换流(了解)
可以把字节流转为字符流使用
InputStreamReader(InputStream,String charset)
OutputSteamWriter(OutputSteam,String charset)

可能出现乱码的情况:
1.字符编码格式不统一
2.缺少字节个数
不同编码格式汉字所占字节大小:
ISO-8859-1 1个字节
GBK 2个字节
GB2312 2个字节
UTF-8 3个字节

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
//转换流----可以把字节流转为字符流使用
public class ConvertDemo {
public static void main(String[] args) throws IOException {
System.out.println("火".getBytes("ISO-8859-1").length);//1
System.out.println("火".getBytes("GBK").length);//2
System.out.println("火".getBytes("GB2312").length);//2
System.out.println("火".getBytes("UTF-8").length);//3

BufferedReader reader=new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream("D:/haha.txt")),"gbk"));
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("D:/hengheng.txt")), "gbk"));
String string=null;
while((string=reader.readLine())!=null){
writer.write(string);
writer.newLine();
}
writer.flush();
writer.close();
reader.close();
}
}

8.基本数据类型流
读写带有基本数据类型的数据+String
基本数据类型流(字节节点流)
DataInputStream(InputStream): 新增方法: readXXX()
DataOutputStream(OutputStream): 新增方法: writeXXX()

EOFException:文件存在,但是内部无法读取,不是源文件

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataDemo {
public static void main(String[] args) throws IOException {
readd("D:/haha.txt");
writee("D:/hhhh.txt");
}
//读取带有基本数据类型+字符串的数据
public static void readd(String pathname) throws IOException {
//1.输入流
DataInputStream inputStream=new DataInputStream(new BufferedInputStream(new FileInputStream(pathname)));
//2.读入   读入和写出顺序要保持一致
int i=inputStream.read();
double d=inputStream.readDouble();
boolean b=inputStream.readBoolean();
String s=inputStream.readUTF();
System.out.println(i+"-->"+d+"-->"+b+"-->"+s);
//3.关闭
inputStream.close();
}

//写出带有基本数据类型的数据
public static void writee(String pathname) throws IOException{
//1.输出流  可以写出基本数据类型的数据
DataOutputStream outputStream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(pathname)));
//2.准备数据
int i=23;
double d=20.19;
boolean b=true;
String s="老詹";
//3.写出
outputStream.writeInt(i);
outputStream.writeDouble(d);
outputStream.writeBoolean(b);
outputStream.writeUTF(s);
//4.刷出
outputStream.flush();
//5.关闭
outputStream.close();
}
}

9.序列化和反序列化
序列化:将对象信息转为可存储或者可传输的信息格式
对象流:
序列化输出流 ObjectOutputStream
反序列化输入流 ObjectInputStream
新增方法 readXxx() writeXxx()

先序列化后反序列化
不是所有的类都能序列化 实现一个空接口 java.io.Serializable
不是所有的属性都需要序列化 transient
静态的内容不能被序列化 默认值
如果父类实现了Serializable,子类中所有的内容都可以序列化
如果子类实现Serializable,父类中的内容没有序列化能力,只有子类的内容有

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;

//序列化:将对象信息转为可存储或者可传输的信息格式
public class ObjectDemo {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
write("D:/lala.txt");
read("D:/lala.txt");
}
//反序列化输入流
public static void read(String pathname) throws ClassNotFoundException, IOException {
//1.对象输入流
ObjectInputStream inputStream=new ObjectInputStream(new BufferedInputStream(new FileInputStream(pathname)));
//2.读
Person person=(Person) (inputStream.readObject());
int[] o=(int[]) inputStream.readObject();
System.out.println(person);
System.out.println(Arrays.toString(o));
inputStream.close();
}
//序列化输出流
public static void write(String pathname) throws FileNotFoundException, IOException{
//1.对象输出流
ObjectOutputStream outputStream=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(pathname)));
//2.准备数据
Person person1=new Person("halo",18,1000);
int[] arr={1,2,3,4};
//3,写出
outputStream.writeObject(person1);
outputStream.writeObject(arr);
//4.刷出
outputStream.flush();
outputStream.close();
}
}
class Person implements Serializable{
private String name;
private int age;
// 不是所有的属性都需要序列化   transient
private transient double money;

public Person() {
// TODO Auto-generated constructor stub
}

public Person(String name, int age, double money) {
super();
this.name = name;
this.age = age;
this.money = money;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public double getMoney() {
return money;
}

public void setMoney(double money) {
this.money = money;
}

@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐