1.输入输出流的分类
Java.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类
- 按照流的方向不同可以分为输出和输入流
- 按照单位分类可以分为字节流跟字符流
- 按照功能分类可以分为节点流跟处理流
概念:
输入 :inputStream(字节输入流),Reader(字符输入流)
输出:outputSteamm(字节输出流),Writer(字符输出流)
这四个类都是抽象类,可以把这四个类想象成四根不一样的管道,一端是数据源,一端是程序,可以通过这跟管道读取或者写入数据。
字节流:
最原始的一个流,读出来的数据就是010101这种最底层的数据表示形式,只不过它是按 照字节来读的,一个字节(Byte)是8位(bit)读的时候不是一个位一个位的来读,而是一个字节 一个字节来读。
字符流:
字符流是一个字符一个字符地往外读取数据。一个字符是2个字节
节点流:节点流可以从一个特定的数据源(字节)上读写数据(文件,内存)
处理流:处理流是“连接”在己存在的流之上,通过对数据的处理程序提供强大的读写功能(BufferedReader/BufferedWriter ...等)。
节点流类型
类型 | 字符流 | 字节流 |
File(文件) | FileReader,FileWriter | FileInputStream,FileOutputStream |
Memory Array(内存数组) | CharArrayReader CharArrayWriter | ByteArrayInputStream ByteArrayOutputStream |
Memory String(内存字符串) | StringReader StringWriter | - |
Pipe(管 道) | PipedReader PipedWriter | PipedInputStream PipedOutputStream |
处理流类型
字节流 | 字符流 | 处理类型 |
BufferedInputStream BufferedOutputStream | BufferedReader BufferedWriter | Buffering |
FilerInputStream FilerOutputStream | FlierReader FilerWriter | FIlering |
- | InputStreamReader OutputStreamWriter | Converting between bytes and chaacter |
ObjectInoutStream ObjectOutputStream | - | Object Serialization |
DateInputStream DataOutputStream | - | Data conversion |
LineNumberInputStream | LineNumberReader | Counting |
PushbackInputStream | PusbackReader | Peeking ahead |
PrintStream | PrintWriter | Printing |
InputStream(输入流)
1.1InputStream中的方法
//读取一个字节并以整数的形式返回(0~255),如果返回-1就说明已经到了输入流的末尾
public abstract int read() throws IOException;
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//一次读取length个字节
//去读到的数据存储到buffer数组,offset指定buffer数组开始存储下标
//列如:offset是1,那么值从buffest数组小下标为1开始存储
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
1.2单个字节读取
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("E:\\javadoc\\javase\\FileInputStream.txt");
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到对应文件");
fileNotFoundException.printStackTrace();
System.exit(-1);//系统正常退出
}
int num = 0;
int charValue=0;
try{
while((charValue = fileInputStream.read()) != -1){
System.out.print((char) charValue);
num++;
}
fileInputStream.close();//关闭流
System.out.println("执行完毕一共是:"+num+"字节");
}catch (IOException ioException){
System.out.println("文件读取错误!");
}
}
}
1.3一次读取多个字节
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("E:\\javadoc\\javase\\FileInputStream.txt");
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到对应文件");
fileNotFoundException.printStackTrace();
System.exit(-1);//系统正常退出
}
int count=0;
//打印个数
byte [] bytes = new byte[1024];
try{
while((count = fileInputStream.read(bytes)) != -1){
/*
调用string的有参构造String(byte bytes[], int offset, int length)
bytes:要解码为字符的字节
offset:要解码的第一个字节的索引
length:要解码的字节数
异常:IndexOutOfBoundsException下标越界异常
*/
System.out.println(new String(bytes,0,count));
}
fileInputStream.close();//关闭流
}catch (IOException ioException){
System.out.println("文件读取错误!");
}
}
}
OutputStream(输出流)
1.1OutputStream中的方法
//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
1.2 案例
public class Test {
public static void main(String[] args) {
FileOutputStream fileOutputStream = null;
try {
//FileOutputStream(String name, boolean append)
/*
FileOutputStream的有参构造、
param
name:文件地址
append:值为false时替代掉文件中的值,true在源文件后面追加值,默认false
*/
fileOutputStream = new FileOutputStream("E:\\javadoc\\javase\\FileOutputStream.txt",true);
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到对应文件");
fileNotFoundException.printStackTrace();
System.exit(-1);//系统正常退出
}
String str = "holle";
try{
fileOutputStream.write(97);
fileOutputStream.write('a');
//调用String类中的方法转换为byte类型的数组
fileOutputStream.write(str.getBytes());
}catch (IOException ioException){
System.out.println("文件出现异常");
System.exit(-1);
}
}
}
3.1案例文件的复制
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("E:\\javadoc\\javase\\1.jpg");
fileOutputStream = new FileOutputStream("E:\\javadoc\\javase\\2.jpg");
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到对应文件");
fileNotFoundException.printStackTrace();
System.exit(-1);//系统正常退出
}
byte[] bytes = new byte[1024];
int cout = 0;
try {
while ((cout = fileInputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,cout);
}
fileInputStream.close();
fileOutputStream.close();
}catch (IOException ioException){
System.out.println("文件出现异常");
System.exit(-1);
}
}
}
Reader流
Reader流跟inputStream一模一样只是它们的是计算单位不一样
继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit)
1.1Reader中的基本方法
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//读取length个字节
//并存储到一个字节数组buffer,从length位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
Writer流中的基本方法
//向输出流中写入一个字节数据,该字节数据为参数b的低16位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
文件字符流
FileReader 文件字符输出流
public class Test {
public static void main(String[] args) throws Exception{
//创建FileReader 字符输出流
//1单个字符读取
FileReader fileReader= new FileReader("E:\\javadoc\\javase\\fileReader.txt");
int count=0;
while((count = fileReader.read())!=-1){//读取一个字节
System.out.println((char) count);
}
//2.创建字符缓冲区,读取数据
char[] c = new char[1];
int data= 0;
while ((data = fileReader.read(c)) != -1){
System.out.println(new String(c,0,data));
}
//关闭连接
fileReader.close();
}
}
FileWriter文件字符输入流
public class Test {
public static void main(String[] args) throws Exception{
//创建FileWriter对象
FileWriter fileWriter = new FileWriter("E:\\javadoc\\javase\\fileReader.txt");
for (int i = 0; i < 5; i++) {
fileWriter.write("从入门到放弃1.0\n");
//刷新
fileWriter.flush();
}
fileWriter.close();
}
}
使用FileReader和FileWriter复制文本,不能复制图片或者二进制文件。
public class Test {
public static void main(String[] args) {
FileWriter fileWriter = null;
FileReader fileReader = null;
try{
fileWriter = new FileWriter("E:\\javadoc\\javase\\FileWirter.txt",true);
fileReader = new FileReader("E:\\javadoc\\javase\\FileReader.txt");
}catch (IOException ioException){
System.out.println("找不到指定文件");
System.exit(-1);
}
int data = 0;
char[] b= new char[3];
try{
while ((data = fileReader.read(b))!= -1){
fileWriter.write(b,0,data);
}
fileReader.close();
fileWriter.close();
}catch (IOException ioException){
System.out.println("文件复制失败");
System.exit(-1);
}
}
}
处理流
1.1缓冲流 BufferedInputStream/BufferedOutputStream
缓冲流要”套接“在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加 了一些新的方法。
缓冲区(Buffer)就是内存里面的一小块区域,读写数据时都是先把数据放到这块缓冲区 域里面,减少io对硬盘的访问次数,保护我们的硬盘。
1.bufferedInputStream
bufferedInputStream中的基本属性
//默认缓冲大小8k
private static int DEFAULT_BUFFER_SIZE = 8192;
//最大缓冲大小 Integer最大值 -8
MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
//存储数据的缓冲区
protected volatile byte buf[];
bufferedInputStream实例
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
BufferedInputStream bufferedInputStream = null;
try{
fileInputStream = new FileInputStream("E:\\javadoc\\javase\\fileInputStream.txt");
bufferedInputStream = new BufferedInputStream(fileInputStream);
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到指定文件");
System.exit(-1);
}
int count = 0;
byte[] b = new byte[1024];
try{
while((count = bufferedInputStream.read(b)) != -1){
System.out.println(new String(b,0,count));
}
bufferedInputStream.close();
}catch (IOException ioException){
System.out.println("文件异常");
System.exit(-1);
}
}
}
2.BufferedOutputStream
BufferedOutputStream中的基本属性
//缓冲区
protected byte buf[];
//缓冲区中的有效字节数
protected int count;
BufferedOutputStream演示
public class Test {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try{
fileInputStream = new FileInputStream("E:\\javadoc\\javase\\fileInputStream.txt");
fileOutputStream = new FileOutputStream("E:\\javadoc\\javase\\fileOutputStream.txt");
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到指定文件");
System.exit(-1);
}
int count = 0;
byte[] b = new byte[1024];
try{
while((count = bufferedInputStream.read(b)) != -1){
bufferedOutputStream.write(b,0,count);
bufferedOutputStream.flush();
}
bufferedOutputStream.close();
bufferedInputStream.close();
}catch (IOException ioException){
System.out.println("文件异常");
System.exit(-1);
}
}
}
对象流——Object
直接将Object 写入或读出
- transient关键字:透明的,用它来修饰的成员变量在序列化的时候不予考虑
- serializable接口:序列化接口
- externaliazble接口:可外部化
对象流ObjectOutputStream/ObjectInputStream
- 增强了缓冲区功能
- 增强了八种基本数据类型和字符串功能
- 增强了对对象的功能
案例
这里是写入多个对象,将对象添加到list中将list写入这样就可以添加多个对象。
public class Test {
public static void main(String[] args) {
ObjectOutputStream objectOutputStream = null;
ObjectInputStream objectIutputStream = null;
try{
objectOutputStream = new ObjectOutputStream(new FileOutputStream("E:\\javadoc\\javase\\ObjectOutputStream.but"));
objectIutputStream = new ObjectInputStream(new FileInputStream("E:\\javadoc\\javase\\ObjectOutputStream.but"));
}catch (FileNotFoundException fileNotFoundException){
System.out.println("找不到指定文件");
System.exit(-1);
}catch (IOException ioException){
System.out.println("创建ObjectOutputStream文件异常");
System.exit(-1);
}
try{
List<Dog> list = new ArrayList<Dog>();
Dog dog1 = new Dog("小白",5);
Dog dog2 = new Dog("小黑",7);
list.add(dog1);
list.add(dog2);
objectOutputStream.writeObject(list);
List<Dog> l = (List<Dog>) objectIutputStream.readObject();
Iterator<Dog> iterator = l.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
objectOutputStream.close();
objectIutputStream.close();
}catch (IOException ioException){
System.out.println("文件异常");
System.exit(-1);
}catch (ClassNotFoundException classNotFoundException){
System.out.println("找不到对应类");
System.exit(-1);
}
}
}
@Data
@AllArgsConstructor
@ToString
@NoArgsConstructor
class Dog implements Serializable{
private transient String name;
private Integer stuID;
public static String county="中国";
}
注意:
- 类需要实现Serializable接口否则会出现异常
- 类中的属性如果是引用类则这个类型也需要使用Serializable接口
- 可以在类中 添加版本号ID保证序列化对象是一致的
- 类中的某一个属性不想被序列化可以在属性添加修饰符transient
- 静态属性不能被序列化
- 序列多个对象可以借用集合实现
转换流InputStreamReader/OutputStreamWriter
转换流主要是用于字节数据到字符数据之间的转换,可以在转换的过程中自定义转换编码格式
演示
public class Test {
public static void main(String[] args) {
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\javadoc\\javase\\char.txt"));
osw.write("MircosoftsunIBMOracleApplet");// 把字符串写入到指定的文件中去
System.out.println(osw.getEncoding());// 使用getEncoding()方法取得当前系统的默认字符编码
osw.close();
osw = new OutputStreamWriter(new FileOutputStream("E:\\javadoc\\javase\\char.txt", true), "ISO8859_1");
// 如果在调用FileOutputStream的构造方法时没有加入true,那么新加入的字符串就会替换掉原来写入的字符串,在调用构造方法时指定了字符的编码
osw.write("MircosoftsunIBMOracleApplet");// 再次向指定的文件写入字符串,新写入的字符串加入到原来字符串的后面
System.out.println(osw.getEncoding());
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
try{
File file = new File("E:\\javadoc\\javase\\char.txt");
//判断有没有当前这个文件
if (file.isFile()){
//删除文件
file.delete();
}
//System.in这里的in是一个标准的输入流,用来接收从键盘输入的数据
InputStreamReader isr = new InputStreamReader(System.in,"ISO8859_1");
BufferedReader br = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\javadoc\\javase\\char.txt",true),"UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
String s = null;
//使用readLine()方法把读取到的一行字符串保存到字符串变量s中去
s = br.readLine();
while(s != null){
if(s.equalsIgnoreCase("exit")){
//只要输入exit循环就结束,就会退出
System.out.println("程序结束");
System.exit(-1);
//return;
//break;
}
bw.write(s);//将控制台输入的数据写入到bufferedWriter中
bw.newLine();//换行
System.out.println(s.toUpperCase());//把保存在内存s中的字符串打印出来,并且转换为大写
s = br.readLine();//在循环体内继续接收从键盘的输入
bw.flush();//刷新
}
bw.close();
br.close();
isr.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
数据流DataInputStream/DataOutputStream
- DataInputStream 和 DataOutputStream 分别继承自InputStream 和 OutputStream , 它属于处 理流,需要分别“套接”在InputStream 和 OutputStream类型的节点流上。
- DataInputStream 和 DataOutputStream 提供了可以存取与机器无关的Java原始类型数据(int, double等)的方法。
DataInputStream/DataOutputStream构造器
public DataInputStream(InputStream in) {
super(in);
}
public DataOutputStream(OutputStream out) {
super(out);
}
public class Test {
public static void main(String[] args) {
try{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("E:\\javadoc\\javase\\char.txt"));
dos.writeByte(100);
dos.writeShort(200);
dos.writeInt(300);
dos.writeLong(400L);
dos.writeFloat(456F);
dos.writeDouble(99.99);
DataInputStream dis=new DataInputStream(new FileInputStream("E:\\javadoc\\javase\\char.txt"));
System.out.println(dis.readByte());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
System.out.println(dis.readShort());
System.out.println(dis.readLong());
System.out.println(dis.readDouble());
dis.close();
dos.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
打印流Print
PrintWriter 和 PrintWriter都属于输出流,分别针对与字符(PrintWriter)和字节(PrintWriter)
PrintWriter 和 PrintStream 提供了重载的print Println方法用于多种数据类型的输出
PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
PrintWriter 和 PrintStream有自动flush功能
try{
PrintWriter pw = new PrintWriter("E:\\javadoc\\javase\\char.txt");
pw.println(97);
pw.println(true);
pw.println(4.12321);
pw.println('a');
pw.close();
}catch(Exception e){
e.printStackTrace();
}
//将数据打印到指定的文件里面