Java中的IO操作

2021-06-08 12:04

阅读:419

标签:tin   data   缓冲流   return   sed   直接   不同   ack   cti   

Java中的IO操作

文件流复制文件

使用RandomAccessFile对象进行文件复制比较麻烦,java中IO提供了功能更强大的类型来进行操作。

1 直接复制

直接复制的思路和RandomAccessFile类的思路相似,代码如下:

package cn.tedu.vip.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 使用io完成文件复制
 * @author Tedu
 *
 */
public class CopyDemo1 {

	public static void main(String[] args) throws IOException {
		/*
		 * 1创建文件输入流,读取源文件
		 * 2创建文件输出流,复制出新文件
		 * 3循环从源文件中读取信息写到新文件中
		 * 4写完记住关闭操作
		 */
		FileInputStream fis=new FileInputStream("齐晨 - 咱们结婚吧.m4a");
		FileOutputStream fos=new FileOutputStream("齐晨 - 咱们结婚吧_cp.m4a");
		
		//创建一个10k的缓存
		byte[] data=new byte[1024*10];
		int len;
		long s=System.currentTimeMillis();
		while((len=fis.read(data))!=-1) {
			fos.write(data, 0, len);
		}
		long e=System.currentTimeMillis();
		System.out.println("over"+(e-s));
		fis.close();
		fos.close();
	}
}
2 使用缓冲流

IO提供了缓冲流来提高复制文件的效率:

package cn.tedu.vip.io;

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.PrintStream;
/**
 * 使用换成流复制文件
 * java.io.BufferedOutputStream
 * java.io.BufferedInputSteram
 * 缓冲流是一组高级流,提高文件流连接的速写速度
 * 内部以块读写的方式条运行效率
 * @author Tedu
 *
 */
public class CopyDemo2 {

	public static void main(String[] args) throws IOException {
		//高级流不能直接指向文件,它创建时需要低级流对象
		FileInputStream fis=new FileInputStream("齐晨 - 咱们结婚吧.m4a");
		BufferedInputStream bis=new BufferedInputStream(fis);
		
		FileOutputStream fos=new FileOutputStream("齐晨 - 咱们结婚吧_cp.m4a");
		BufferedOutputStream bos=new BufferedOutputStream(fos);
		
		int d;
		long s=System.currentTimeMillis();
		while((d=bis.read())!=-1) {
			bos.write(d);
		}
		long e=System.currentTimeMillis();
		System.out.println("over"+(e-s));
		bis.close();
		bos.close();
	}
}
3 缓冲流的flush方法

void flush()

强制将当前缓冲区已经缓存的字节一次性写出调用flush方法会立即写出已缓存数据提高数据写出的即时性,但是同样增加了实际写出的次数,从而降低写出效率

package cn.tedu.vip.io;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 缓冲输出流写出数据 缓冲区
 * @author Tedu
 *
 */
public class BOSFlushDemo {

	public static void main(String[] args) throws IOException {
		FileOutputStream fos=new FileOutputStream("box.txt");
		BufferedOutputStream bos=new BufferedOutputStream(fos);
		String str="右边划一道彩虹!";
		byte[] data=str.getBytes("gbk");
		
		bos.write(data);
		/*
		 * void flush();
		 * 强制将当前缓冲区的字节一次性写出
		 * 同时清空缓冲区,是即时的写出
		 * 实际上也会增加写出的次数,降低写出效率
		 */
		bos.flush();
		System.out.println("over");
		
		//bos.close内部也会调用flush方法
		bos.close();		

	}
}

序列化与反序列化

Java还有一组功能强大的流类型,对象流:

java.io.ObjectOutStream

java.io.ObjectputStream

对象流是一对高级流,可以读写Java中任何对象

对象输出流负责在写出对象的过程中,将对象按照其结果转换为一组字节(对象序列化)

对象输入流负责在读取对象的过程中将字节还原为对象(对象反序列化)

1 序列化目标Person类

要想序列化对象,需要使用对象流的void writeObject()方法

该方法在写出一个对象时有一个前提条件要求该对象所属的类必须实现序列化接口(Serializable)否则会抛出异常

序列化目标类Person必须实现Serializable接口

package cn.tedu.vip.io;

import java.io.Serializable;
import java.util.Arrays;

/**
 * 用于测试对象流(序列化)内容的实体类
 * 如果这个类想被序列化,那么必须实现一个接口
 * java.io.Serializable
 * @author hp
 *
 */

public class Person implements Serializable {
	/*
	 * serialVersionUID是表示当前Person类版本的
	 * 序列化时会将这个版本信息也写入到硬盘
	 * 反序列化时会对比版本的数值是否相同,相同可转,不相同不可转
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String gender;
	private  transient String[] hobby;//不进入序列化内容中
	public Person(String name, int age, String gender, String[] hobby) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.hobby = hobby;
	}
	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 String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String[] getHobby() {
		return hobby;
	}
	public void setHobby(String[] hobby) {
		this.hobby = hobby;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ","+Arrays.toString(hobby)+"]";
	}
}
2 序列化操作

这里流连接的操作分别为:

  1. 先将给定对象通过对象流写出,此时对象流会将该对象转换为一组字节,这个过程称为对象序列化
  2. 序列化后的字节再通过文件流写入文件,即:写入磁盘中,这个过程称为数据持久化
package cn.tedu.vip.io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
 * 对象流,用于对象的序列化和反序列化
 * java.io.ObjectOutputStream
 * Java.io.ObjectInputStream
 * 对象流也是高级流
 * 对象输出流就是序列化操作,将一个对象写到硬盘上
 * 对象输入流,就是反序列化操作,将一个对象从硬盘上恢复成内存中对象
 * @author Tedu
 *
 */
public class OOSDemo {

	public static void main(String[] args) throws IOException {
		Person p=new Person("苍老师",18,"男",new String[] {"吃饭","睡觉","打豆豆","演戏"});
		//创建低级流
		FileOutputStream fos=new FileOutputStream("person.obj");
		ObjectOutputStream oos=new ObjectOutputStream(fos);
		/*
		 * 要序列化的对象必须实现可序列化的接口
		 * 否则在进行序列化时会报错
		 * 1,对象流会将指定的对象转换
		 * 这个过程称为序列化
		 * 2,将序列化后的这组字节写到流对象指定的硬盘路径上
		 * 这个过程称为数据持久化
		 */
		oos.writeObject(p);
		System.out.println("over");
		oos.close();
	}
}
3 反序列化操作

序列化后的文件可以反序列化为对象,代码:

package cn.tedu.vip.io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
 * 使用对象流反序列化操作
 * @author hp
 *
 */
public class OISDemo {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		FileInputStream fis=new FileInputStream("person.obj");
		ObjectInputStream ois=new ObjectInputStream(fis);
		
		Person p=(Person)ois.readObject();
		System.out.println(p);
		ois.close();
	}
}

字符流

Java IO将流按照读写单位划分为了两类:

  1. 字节流:InputStream,OutputStream读写单位为字节
  2. 字符流:Reader,Writer读写单位为字符

字符流读取单位为字符(char)所以针对文字传输,字符流有更好的适应性

1 字节流转换字符流输出

使用转换流将字节流转换为字符流是常见操作

转换流是字符流的一对实现类,是一对高级流

转换流不会作为终端流使用,对于读写文本数据时在流连接中是非常重要的一环。

package cn.tedu.vip.io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
/**
 * 字符流
 * java IO提供了两类流,按读写信息的内容分
 * 字节流:InputStream  OutputStream
 * 读写的内容以字节为单位
 * 
 * 字符流:reader  writer
 * 读写的内容以字符为单位
 * 
 * 转换流
 * 是一组高级流
 * 能够将字节流转换为字符流
 * 
 * @author Tedu
 *
 */
public class OSWDemo {
	public static void main(String[] args) throws IOException {
		FileOutputStream fos=new FileOutputStream("osw.txt");
		
		OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
 		String str="啊~五环~你比四环多一环";
 		/*
 		 * osw写出字符的方法中
 		 * 会按照实例化对象时指定的字符集
 		 * 转换成字节再输出
 		 */
 		
 		osw.write(str);
 		System.out.println("over");
 		osw.close();
	}
}
2 字节流转换字符流输入
package cn.tedu.vip.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
 * 使用转换流将输入字节流转换成字符流
 * @author Tedu
 *
 */
public class ISRDemo {

	public static void main(String[] args) throws IOException {
		FileInputStream fis=new FileInputStream("osw.txt");
		
		InputStreamReader isr=new InputStreamReader(fis,"utf-8");
		
		int d;
		while((d=isr.read())!=-1) {
			System.out.print((char)d);
		}
		System.out.println("over");
		isr.close();
	}
}

缓冲字符流

在字符流的基础上加上缓冲机制,能在字符流对字符处理适用性好的基础上,再增加运行效率

1 直接使用缓冲字符流

字符缓冲流可以直接实例化对象,需要参数为文件路径和字符集

package cn.tedu.vip.io;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
/**
 * 缓冲字符流
 * java.io.BufferedWriter
 * java.io.BufferedReader
 * 使用缓存对文件的内容进行块读写,提高读写效率
 * 
 * java.io.PrintWriter
 * 是BufferedWriter基础上的又一次加工
 * 具有了自动刷新换行的功能
 * @author Tedu
 *
 */
public class PwDemo {

	public static void main(String[] args) throws IOException, UnsupportedEncodingException {
		//PrintWriter
		PrintWriter pw=new PrintWriter("pwd.txt","utf-8");
		
		pw.println("像我这样优秀的人");
		pw.println("本该灿烂过一生");
		System.out.println("over");
		
		pw.close();
	}
}
2 低级流转换成字符缓冲流
package cn.tedu.vip.io;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
/**
 * 使用字节流转换到PW
 * @author hp
 *
 */
public class PwDemo02 {

	public static void main(String[] args) throws IOException {
		FileOutputStream fos=new FileOutputStream("pw.txt");
		OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
		BufferedWriter bw=new BufferedWriter(osw);
		PrintWriter pw=new PrintWriter(bw);
		
		pw.println("怎么会爱上她");
		pw.println("我心爱的颖姑娘");
		
		System.out.println("over");
		
		pw.close();
	}
}
3 简易记事本

需求如下:

  1. 程序启动后,要求用户输入文件名,然后对文件进行操作
  2. 在控制台输出的每行字符串都按行写入到该文件中
  3. 当用户单独输入exit时,程序退出
package cn.tedu.vip.io;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;

/**
 * 简易记事本,使用流连接创建
 * 程序启动后,由用户输入记事本的文件名
 * 用户循环向记事本输入内容
 * 输入exit时循环退出,程序结束
 * @author Tedu
 *
 */

public class Note {

	public static void main(String[] args) throws IOException {
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入文件名:");
        String fileName=Scanner.nextLine();
        
        FileOutputStream fos
            =new FileOutputStream(fileName);
        OutputStreamWriter osw
            =new OutputStreamWriter(fos,"utf-8");
        BufferedWriter bw
            =new BufferedWriter(osw);
        /*
         *在流连接中使用pw时可以打开自动行刷新功能
         *这样每当我们调用println方法时会自动flush
         *注意:print方法写出数据是不会刷新的
         */
        PrintWriter pw
            =new PrintWriter(bw,true);
        while(true){
            System.out.println("请进行记事");
            String line=scanner.nextLine().trim();
            if("exit".equals(line)){
                break;
            }
            pw.println(line);
        }
        System.out.println("再见!")
            pw.close();
    }
}
4 缓冲字符输出流

可以在字符输入流的基础上加上缓冲:

package cn.tedu.vip.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
 * java.io.BUfferedReader
 *  缓冲字符输入流
 * @author Tedu
 *
 */
public class BrDemo {

	public static void main(String[] args) throws IOException {
		FileInputStream fis=new FileInputStream("a.txt");
		InputStreamReader isr=new InputStreamReader(fis,"utf-8");
		BufferedReader br=new BufferedReader(isr);
		/*
		 * BufferedReader可以读取一行字符串信息,直接使用String类型接收
		 */
		String msg=null;
		while((msg=br.readLine())!=null) {
			System.out.println(msg);
		}
		System.out.println("YangYing");
		br.close();
	}
}

IO小结

低级流:FileInputStream FileOutputStream

负责从文件中读取字节、将字节写入文件中

高级流:BufferedInputStream ObjectInputStream

块读字节加快读取效率、对象反序列化

BufferedOutputStream ObjectOutputStream

块写字节加快写出效率、对象序列化

InputStreamReader BufferedReader

衔接字符流与字节流字节转字符、块读文本数据取字符串

OutputStreamWriter BufferedWriter PrintWriter

将字符转字节、块写文本数据,按行写出字符串,自动行刷新

异常基础

异常概述

1 什么是异常

异常就是在程序运行过程中发生了无法继续执行代码的情况

异常就是程序的运行不同于正常情况

2 什么是异常处理

就是在程序发生异常后的补救措施,就是发生异常后要执行的代码

3 为什么需要异常处理

一旦发生异常,如果不处理程序就会终止

处理异常后程序能继续运行,保证了程序的健壮性

4 如何处理异常

使用try-catch语句:

try{
    //程序代码
}catch(XXXException e){
    //try中出现XXXException的处理代码
}
5 异常处理实例

出现异常类型越多,catch块可以写越多,处理不同类型的异常

package exception;
/**
 * try-catch的使用
 * Exception类是所有异常类的父类
 * @author Tedu
 *
 */
public class TryCatchDemo {
	public static void main(String[] args) {
		System.out.println("程序开始");
		
		try {
			/*
			 * try块中发生异常会匹配catch块中指定的异常类型
			 * 如果匹配进入catch运行
			 */
			String str=null;
			String str1="";
			//String str="abc";
			System.out.println(str.length());
			System.out.println(str1.charAt(1));
			//System.out.println(Integer.parseInt(str));将字符串转换为int类型
			/*
			 * try语块中的代码一旦发生异常,就不会执行try块中剩余的语句了
			 */
		} catch (NullPointerException e) {//空指针异常
			System.out.println("发生了空指针异常");
		}catch(StringIndexOutOfBoundsException e) {
			System.out.println("发生了字符串索引越界异常");
		}catch(Exception e) {
			System.out.println("反正是出了错误");
		}
		
		System.out.println("程序结束");
	}
}
6 finally块

finally块是异常处理机制的最后一块,可以直接跟在try之后或者最后一个catch之后,finally确保只要程序执行到了try中,无论try语句块中的代码是否出错,finally语句块都必定会执行

try{
    //程序代码
}catch(XXXException e){
    //try中出现XXXException的处理代码
}finally{
    //无论try语句块中的代码是否出错都执行的代码
}
7 finally处理实例
package exception;
/**
 * 只要进入了try块运行
 * 那么就会执行finally块
 * 无论出不出异常。无论异常是否被捕获,都会运行finally
 * 
 * 常用于释放类似IO操作时的资源
 * @author Tedu
 *
 */
public class FinallyDemo1 {

	public static void main(String[] args) {
		System.out.println("程序开始了");
		
		try {
			String str=null;
			//String str="abc";//3
			System.out.println(str.length());
			//return;//finally也照样执行
			//System.exit(0);终止finally
		} catch (Exception e) {
			System.out.println("出错了");
		}finally {
			System.out.println("finally执行了");
		}
		System.out.println("程序结束了");
	}
}
8 IO异常处理
package exception;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * IO程序结合异常机制的编写
 * @author Tedu
 *
 */
public class FinallyDemo2 {

	public static void main(String[] args) {
		System.out.println("程序开始");

		FileOutputStream fos=null;//先赋值为null
		try {
			fos = new FileOutputStream("e:/abc/aaa.txt");
			fos.write(1);
		} catch (Exception e) {
			System.out.println("出错了");
		}finally {
			try {
				if(fos!=null) {
					fos.close();
				}
			}catch(IOException e) {
				System.out.println("关闭时出错了");
			}
		}
		System.out.println("程序结束");
	}
}
9 自动关闭
package exception;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
 * JDK1.7之后开启的新特性:自动关闭
 * 在异常处理结构中可以使用更简单的代码实现资源的关闭
 * IO对象的close就可以自动关闭
 * @author Tedu
 *
 */
public class AutoClosedDemo {

	public static void main(String[] args) {
		try (
				/*
				 * 必须是实现了Autocloseable接口的类才能自动调用close
				 * 咱们学习的IO相关类包括RandomAccessFile都实现了该接口
				 * 
				 * 本质是编译器在编译代码时,将try()里的资源进行自动的
				 * 编辑关闭,并在finally的位置执行
				 */
				FileOutputStream fos=new FileOutputStream("e:/abc/aaa.txt");
				OutputStreamWriter osw=new OutputStreamWriter(fos);
				){
			osw.write(1);
			
		}catch(IOException e) {
			System.out.println("出错了");
		}
		System.out.println("程序结束");
	}
}
10 异常综合练习

需要了解运行过程和执行结果

package exception;
/**
 * 请描述final,finally,finalize
 * 
 * 异常结构综合习题
 * @author Tedu
 *
 */
public class finallyDemo3 {

	public static void main(String[] args) {
		System.out.println(test(null));//空指针
		System.out.println("over");
		System.out.println(test(""));//字符越界
		System.out.println(test("")+","+test(null)+","+test("a"));//2.1.97


	}
	public static int test(String str) {

		try {
			System.out.println("调用了test:"+str);
			return str.charAt(0);
		}catch (NullPointerException e) {
			System.out.println("出现了空指针");
			return 1;
		}catch(StringIndexOutOfBoundsException e) {
			System.out.println("出现了字符越界");
			return 2;
		}catch(Exception e) {
			System.out.println("未知错误");
			return 3;
		}finally {
			System.out.println("finally执行");
			//return 10;不这么使用
		}
	}
}
11 Exception类的常见方法

Exception类是所有异常的父类,其中定义的公有方法所有子类均可以使用

package exception;
/**
 * Exception对象的常用方法
 * @author Tedu
 *
 */
public class ExceptionApiDemo {

	public static void main(String[] args) {
		System.out.println("程序开始");
		try {
			String str="A";
			System.out.println(str.charAt(3));
		}catch (Exception e) {
			System.out.println("出错了");
			/*
			 * 输出异常的堆栈信息
			 */
		 //e.printStackTrace();//异常堆栈
			System.out.println(e.getMessage());//异常信息
			      //err.println
		}
		System.out.println("程序结束");
	}
}

Java中的IO操作

标签:tin   data   缓冲流   return   sed   直接   不同   ack   cti   

原文地址:https://www.cnblogs.com/xiongchenglong/p/14530360.html

上一篇:Spring-MVC-01

下一篇:python中的openpyxl


评论


亲,登录后才可以留言!