JAVA基础中的IO流

目录

关键知识点及补充

IO流-节点流

IO流--功能流

例题

File类的使用

复制文件 

 复制文件夹(文件夹内有文件和文件夹)---利用了拷贝文件类

 字符流输入

字符流输出 

增强字节流的使用

增强字符流的使用 

数据处理流

对象处理流(序列化):ObjectOutputStream

对象处理流(反序列化):ObjectInputStream

 数据流:

对象流 :


 



关键知识点及补充

  • 一定要结合API看
  • File提供的功能都是操作文件外部的能力,没有办法操作文件内部的内容,要操作内部的东西要用IO流
  • 流是管道,用来连接俩个节点,一个是输入流,向内存中输入东西,一个是输出流,内存将东西输入到磁盘上
  • 节点流包括字节流和字符流 ,用来传输内容 功能流|增强流是依托于节点流,用来加强的,提升效率
  • 节点流中的字节流是万能流,可以传递任何数据,字符流只可以传递文本
  • 字节流:InputStream,OutputStream 是抽象类只能被继承,运用多态,实际运用他的子类:FileInputStream,FileOutputStream
  • 字符流:Reader,Writer  是抽象类,只能被继承,实际运用它的子类:FileReader,FileWriter 
  • 上述俩种都有read()方法,但是基本上都用read(声明);来一段一段读    都有write()方法,但是基本上结合前面说的用write(arr,0,len)       上述俩种在FileOutputStream os=new FileOutputStream("D:/hehe.txt",true); true表示追加,默认为覆盖
  • 基本步骤:1.选择流  2.输入内存输出目的地数据 3.将数据刷出:flush()方法 4.关闭用close()方法
  • 对于关闭:  先关闭后打开的 
  • 数据流处理的是基本数据类型+String,对象流处理的是Object类
  • 数据流和对象流都要先Output再input,因为数据流和对象流在你Output到磁盘中的内容是不可以再另存为或着Ctrl+c,Ctrl+v换地方的,不然会有错误(EOFException 文件有,内容读入不到,必须读入的是写出的源文件),因为存储的是有格式的内容,并且文件也会有点不一样(文件的开头啊啥的,你看不出来的表面上),他们俩的读出和读入的顺序要一致,因为是按照顺序读出和读入的
  • 使用数据流和对象流时候要用数据流|对象流 包裹缓冲流,缓冲流包裹字节流
  • 对于对象流而言,要先序列化,再反序列化  ,就是先Output再input
  • 看下面的数据流和对象流的区别

IO流-节点流

 *     流: 一连串流动的数据,以先入先出的方式进行流动,管道
 *     以程序为中心  程序与 网络|文件|服务器|数组..
 * 
 *    分类:
 *        操作单元分:
 *            字节流 ***:万能流:任何内容都可以转为字节,可以传输文本,图片,音频...   是一个节点流
 *            字符流 :只能操作 纯文本数据                                是一个节点流
 *        按照功能:
 *            节点流 : 包裹源头,实现基本功能              包括  字符流和字节流
 *            功能流 : 对节点流增强性能,提高效率
 *        分类之间是相辅相成的
 *
 * 字节流: 是节点流
 * 字节输入流 : InputStream 此抽象类是表示字节输入流的所有类的超类。 抽象类不可以创建对象,只可以用来继承,所以寻找子类
 * 利用 FileInputStream 从文件系统中的某个文件中获得输入字节。
 * 字节输出流 : OutputStream (同字节输入流)

IO流--功能流

* 功能流(对节点流的增强): 增强功能,提高性能,加快读写效率..
缓冲流(用缓冲流包裹字节流):

*      没有要使用的新增方法,可以发生多态使用
 *     BufferedInputStream 字节输入流缓冲流
 *     BufferedOutputStream 字节输出流缓冲流
 *   

* 有要使用的新增方法,不要使用
 *     BufferedReader  字符输入流缓冲流    
 *         新增方法:String readLine() 读取一个文本行。 
 *     BufferedWriter  字符输出流缓冲流
 *         新增方法:void newLine()  写入一个行分隔符。 

数据流(用数据流包裹缓冲流,缓冲流包裹字节流):

*Data流(字节节点流)
 *    读写基本数据类型+String类型数据
 *    是字节流功能流的一种
 *    DataInputStream 新增方法: readXxx()
 *    DataOutputStream  新增方法: writeXxx()
 *    存在要使用的                                   新增方法不能发生多态
 *    先写出再写入
 *    EOFException 文件有,内容读入不到,必须读入的是写出的源文件

对象流同数据流

 *  数据流和对象流都是得先输出在输入,也就是你先把 内容输入到磁盘再去读取 
 * 
 *     对象流: Object 保存数据类型+数据
 *         字节的功能流:当想要传输|读写对象类型数据的时候,可以使用一个对象流
 *     序列化: 把对象类型的数据转化为可存储|可传输的状态的过程
 *     ObjectInputStream()    反序列化输入流   新增方法: readObject() 
 *     ObjectOutputStream()   序列化输出流       新增方法: writeObject()
 * 
 * 注意:
 *    1.先序列化后反序列化 //序列化和反序列化只是这个类的属性,方法完全可以等到反序列化后利用对象去调用方法
 *    2.序列化反序列读写顺序一致
 *    3.不是所有的类都能序列化             java.io.Serializable 空接口 只需要实现就行,里面是空的
 *    4.不是所有的属性都需要序列化      transient 用来不让这个属性序列化
 *    5.static内容不会被序列化,但是可以访问到数据,因为它是静态的,只有一份,如果你写完了,改变数据,再去读,会是改变的数据,证实了,不然你写了就写了,再改变也不会变
 *    6.如果父类实现Serializable   接口,子类中可以序列化所有内容
 *    7.如果子类实现Serializable   接口,但是父类没有实现,子类只能序列化子类独有的内容

例题

File类的使用

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/*
 * io: 上传下载,写入写出...
 * File 类  文件和目录路径名的抽象表示形式。                                                只能够找到路径,不能操作具体内容,具体的要用io流
 * 	能够定义真实存在的路径|文件,不在的也可以定义,所以抽象表现形式
 * 作用
 * 构造器
 * 方法
 */

/*
 * File 和  字符串的转换:
 * file.toString          new File(string)
 */

public class FileDemo01 {
	public static void main(String[] args) throws IOException {
		//File(String pathname) 
		File file =new File("D:/test.txt");  //转义字符从\开始  所以在表示路径字符串中使用\\或者/表示
		System.out.println(file);
		
		//File(String parent, String child) 
		File file1 =new File("D:/AAA/haha.txt");  
		File file2 =new File("D:/AAA/","haha.txt");  
		System.out.println(file1);
		System.out.println(file2);
		File file3 =new File("D:/");  
		File file4 =new File(file3,"test.txt");  
		System.out.println(file3);
		System.out.println(file4);
		
		// boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。 
		System.out.println("canWrite()"+file.canWrite());
		//setReadOnly()
		System.out.println("setReadOnly()"+file.setReadOnly());
		System.out.println("canWrite()"+file.canWrite());
		
		/*
		 * boolean mkdir() 
		          创建此抽象路径名指定的目录。 
		   boolean mkdirs() 
		          创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 
		 */
		/*
		 * String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。 
 		   File getParentFile()  
		 */
		System.out.println("mkdir()"+file1.getParentFile().mkdir());
		//boolean createNewFile()  
		System.out.println("createNewFile()"+file1.createNewFile());
		// boolean delete() 删除此抽象路径名表示的文件或目录。 
		System.out.println("delete()"+file1.delete());
		// boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 
		System.out.println("exists()"+file1.exists());
		/*
		 * File getAbsoluteFile() 
		          返回此抽象路径名的绝对路径名形式。 
		   String getAbsolutePath() 
		          返回此抽象路径名的绝对路径名字符串。 
		 */
		System.out.println("getAbsolutePath()"+file1.getAbsolutePath());
		
		//long getFreeSpace()  返回此抽象路径名指定的分区中未分配的字节数。 
		System.out.println("getFreeSpace()"+file3.getFreeSpace());
		
		// String getName()  返回由此抽象路径名表示的文件或目录的名称。 
		System.out.println("getName()"+file1.getName());
		/*
		 *  boolean isAbsolute()  测试此抽象路径名是否为绝对路径名。 
		 	boolean isDirectory()    测试此抽象路径名表示的文件是否是一个目录。 
		 	boolean isFile() 	
		 */
		System.out.println("isAbsolute()"+file1.isAbsolute());
		file1.createNewFile();
		System.out.println("isFile()"+file1.isFile()); //找路径下真实文件判断
		//long lastModified()  
		System.out.println("lastModified()"+new SimpleDateFormat().format(new Date(file.lastModified())));
	
		//File[] listFiles()  
		// String[] list() 
		System.out.println(Arrays.toString(new File("D:/code").listFiles()));
		
		/*
		 *  boolean renameTo(File dest)   重新命名 
		 *  	不能做跨盘符的文件重新命名
		 */
		File src=new File("D:/AAA");
		System.out.println("renameTo()"+src.renameTo(new File("D:/BBB")));
	}
}

复制文件 

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

class CopyFile{
	public static void copy2(File f1,File f2){
		copy1(f1.toString(), f2.toString());
	}

	public static void copy1(String string1,String string2) {
		// 1.选择流
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(string1);    //流只是一个通道程序输入,能不能联通上就是会不会找到异常
			os = new FileOutputStream(string2);		
			// 读入,写入
			byte[] car = new byte[1024];
			int len = -1;
			while ((len = is.read(car)) != -1) {
				os.write(car, 0, len); // 不能直接写car,不然会有很多空格,因为是1024为一组,
			}
			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) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}

	}

}

 复制文件夹(文件夹内有文件和文件夹)---利用了拷贝文件类

import java.io.File;

class CopyDir{
	
	public void copydir(String src,String dest){
		//复制过去的一定是目的地,不会给你创建一些子目录,
		//比如src:D:/AAA/DDD(里面还有:/BBB/test.txt和/CCC/)  dest:D:
		//拷贝文件夹一定是将AAA拷贝给D:所以要补全信息
		File srcFile = new File(src);
		File destFile = new File(dest,srcFile.getName());//获取的是前面的一级,注释中的DDD
		details(srcFile, destFile);
		
	}
	public void details(File src,File dest){
		//如果是文件,直接用copyFileTest里面的Copy类的copy2方法
		if (src.isFile()) {
			//注意有种情况:万一目标路径不存在,要创建路径
			if (!dest.getParentFile().exists()) {
				//创建文件的路径,创建完了再去拷贝
				dest.getParentFile().mkdirs();
			}
			CopyFile.copy2(src, dest);
		}else {
			//就是是文件夹的情况
			//目的地先创建文件夹,按理说一级就够了
			dest.mkdir();
			
			//遍历文件夹中剩余的内容,如果是文件拷贝,文件夹创建,再遍历文件夹下的内容
			File[] files = src.listFiles();
			for (File file : files) {
				details(file,new File(dest,file.getName()));
			}
		}
	}

}

 字符流输入

public class CharDemo01 {
	public static void main(String[] args) {
		//FileReader(String fileName) 
		Reader rd=null;
		try {
			//1.选择流
			rd=new FileReader("D:/hehe.txt");
			//2.读入
			//int read() 读取单个字符。 
			/*System.out.println((char)rd.read());
			System.out.println((char)rd.read());*/
			int len=-1;  //存储读到的数据  如果为-1,证明已达到末尾
			/*while(-1!=(len=rd.read())){
				System.out.println((char)len);
			}*/
			// int read(char[] cbuf)  将字符读入数组。
			char[] car=new char[1024];
			while((len=rd.read(car))!=-1){
				System.out.println(new String(car,0,len));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			if(rd!=null){
				try {
					rd.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

字符流输出 

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

/*
 * 		字符输出流: Writer 写入字符流的抽象类
 * 			FileWriter用来写入字符文件的便捷类。
 */
public class CharDemo02 {
	public static void main(String[] args) {
		//FileWriter(File file)    //默认不追加
		//FileWriter(File file, boolean append)  
		//FileWriter(String file)  
		//FileWriter(String file, boolean append)  
		Writer rt=null;
		try {
			//1.选择流
			rt=new FileWriter("D:/houhou.txt",true);
			//2.写出
			/*
			 *   void write(char[] cbuf) 
				          写入字符数组。 
				 abstract  void write(char[] cbuf, int off, int len) 
				          写入字符数组的某一部分。 
				 void write(int c) 
				          写入单个字符。 
				 void write(String str) 
				          写入字符串。 
				 void write(String str, int off, int len) 
				          写入字符串的某一部分。 
			 */
			rt.write(97);
			rt.write("\r\n");  //换行
			rt.write("你真好看!!!!");
			rt.write("\r\n");
			rt.write("你真好看!!!!",2,2);
			rt.write("\r\n");
			char[] ch={'上','海','尚','学','堂'};
			rt.write(ch);
			rt.write("\r\n");
			rt.write(ch,2,3);
			//3.刷出
			rt.flush();		
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			//4.关闭
			if(null!=rt){
				try {
					rt.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

增强字节流的使用

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;

/*
 * 功能流(对节点流的增强),缓冲流: 增强功能,提高性能,加快读写效率..
 * 
 * 字节流:
 * 	BufferedInputStream 字节输入流缓冲流
 * 	BufferedOutputStream 字节输出流缓冲流
 * 		没有新增方法,可以发生多态使用
 * 
 * 字符流:
 * 	BufferedReader  字符输入流缓冲流
 * 	BufferedWriter  字符输出流缓冲流
 */
public class BufferedInputStream01 {
	public static void main(String[] args) throws IOException {
		//1.选择流
		//BufferedInputStream(InputStream in) 
		InputStream is=new BufferedInputStream(new FileInputStream("D:/hehe.txt"));
		OutputStream os=new BufferedOutputStream(new FileOutputStream("E:/hengheng.txt") );
		//2.读写
		byte[] car=new byte[1024];
		int len=-1;
		while((len=is.read(car))!=-1){
			os.write(car,0,len);
		}
		//3.刷出
		os.flush();
		//4.关闭
		os.close();
		is.close();
	}
}

增强字符流的使用 

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

/*
 * 字符流:
 * 	BufferedReader  字符输入流缓冲流	
 * 		新增方法:String readLine() 读取一个文本行。 
 * 	BufferedWriter  字符输出流缓冲流
 * 		新增方法:void newLine()  写入一个行分隔符。 
 * 		
 */
public class BufferedReader02 {
	public static void main(String[] args) throws IOException {
		//1.选择流  导包快捷键: ctrl+shift+o
		BufferedReader br=new BufferedReader(new FileReader("D:/hehe.txt"));
		BufferedWriter bw=new BufferedWriter(new FileWriter("D:/ccc.txt"));
		//2.读写
		String msg=null;
		while((msg=br.readLine())!=null){
			bw.write(msg);
			bw.newLine();
		}
		//3.刷出
		bw.flush();
		//4.关闭
		bw.close();
		br.close();
	}
}

数据处理流

/**
	 * 数据+类型	输出到文件
	 * @param destPath
	 * @throws IOException 
	 */
	public static void write(String destPath) throws IOException{
		int point=2;
		long num=100L;
		String str="数据类型";
		//创建源
		File dest=new File(destPath);
		//选择流
		DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
		//操作	写出的顺序 		为读取作准备 顺序一定要一致
		dos.writeInt(point);
		dos.writeLong(num);
		dos.writeUTF(str);
		dos.flush();
		//释放资源
		dos.close();
	}

对象处理流(序列化):ObjectOutputStream

//创建源
File dest=new File(destPath);
//选择流	OjbectOutputStream
ObjectOutputStream dos   =  new ObjectOutputStream(new BufferedOutputStream(
new FileOutputStream(dest)));
//操作	读取的顺序与写出的顺序一致		必须存在才能读取
		Employee obj=new Employee (“yinwei”,1500);
        dos.writeObject(obj);
//刷出
        dos.flush();
//释放资源
		dos.close();

对象处理流(反序列化):ObjectInputStream

/**
	 * 反序列化:
	 * 1、先写入再读取
	 * 2、读取对象需要知道具体类型,依次读取
	 * 注意:
	 * 1)不是所有的对象都可以序列化	Serializable
	 * 2)不是所有的属性都需要序列化	transient	
	 */	
public static void read(String srcPath) throws FileNotFoundException, IOException, ClassNotFoundException{
		//创建源
		File src=new File(srcPath);
		//选择流	OjbectInputStream
		ObjectInputStream dis=new ObjectInputStream(
				new BufferedInputStream(
						new FileInputStream(src)
						)
				);
		//操作	读取的顺序与写出的顺序一致		必须存在才能读取
		Object obj=dis.readObject();
		if(obj instanceof Employee){
			Employee emp=(Employee)obj;
			System.out.println(emp.getName());
			System.out.println(emp.getSalary());
		}
		obj=dis.readObject();
		int[]arr=(int[])obj;
		System.out.println(Arrays.toString(arr));
		//释放资源
		dis.close();
	}

 数据流:

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

/*
 *Data流(字节节点流)
 *	读写基本数据类型+String类型数据
 *	是字节流功能流的一种
 *	DataInputStream 新增方法: readXxx()
 *	DataOutputStream  新增方法: writeXxx()
 *	存在要使用的                                   新增方法不能发生多态
 *	先写出再写入
 *
 *	EOFException 文件有,内容读入不到,必须读入的是写出的源文件
 */
public class DataDemo01 {
	public static void main(String[] args) throws IOException {
		//write("D:/data.txt");
		read("D:/data1.txt");
	}
	//读入
	public static void read(String path) throws IOException{
		//1.输入流 数据类型+数据
		DataInputStream in=new DataInputStream(new  BufferedInputStream(new FileInputStream(path)));
		//2.读入
		int i=in.readInt();
		boolean b=in.readBoolean();
		String s=in.readUTF();
		System.out.println(i+"-->"+b+"-->"+s);
		//3.关闭
		in.close();
		
	}
	
	
	//写出
	public static void write(String path) throws IOException{
		//1.输出流
		DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
		//2.准备数据
		int i=101;
		boolean f=false;
		String s="哈哈";
		//3.写出  写出和读入的顺序要保持一致
		out.writeInt(i);
		out.writeBoolean(f);
		out.writeUTF(s);
		//4.刷出
		out.flush();
		//5.关闭
		out.close();
	}
}

对象流 :

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

/**
 *  数据流和对象流都是得先输出在输入,也就是你先把 内容输入到磁盘再去读取 
 * 
 * 	对象流: Object 保存数据类型+数据
 * 		字节的功能流:当想要传输|读写对象类型数据的时候,可以使用一个对象流
 * 	序列化: 把对象类型的数据转化为可存储|可传输的状态的过程
 * 	ObjectInputStream()    反序列化输入流   新增方法: readObject() 
 * 	ObjectOutputStream()   序列化输出流       新增方法: writeObject()
 * 
 * 注意:
 * 	1.先序列化后反序列化                                             //序列化和反序列化只是这个类的属性,方法完全可以等到反序列化后利用对象去调用方法
 *  2.序列化反序列读写顺序一致
 *	3.不是所有的类都能序列化 			java.io.Serializable 空接口 只需要实现就行,里面是空的
 *	4.不是所有的属性都需要序列化 		    transient 用来不让这个属性序列化
 *	5.static内容不会被序列化,但是可以访问到数据,因为它是静态的,只有一份,如果你写完了,改变数据,再去读,会是改变的数据,证实了,不然你写了就写了,再改变也不会变
 *	6.如果父类实现Serializable   接口,子类中可以序列化所有内容
 *	      如果子类实现Serializable   接口,但是父类没有实现,子类只能序列化子类独有的内容
 */
public class ObjectDemo02 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		//write("G:/object.txt");
		read("F:/object.txt");
	}
	
	//反序列化输入
	public static void read(String path) throws IOException, ClassNotFoundException{
		//1.输入流
		ObjectInputStream is=new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
		//2.读入
		Object p= is.readObject();
		int[] arr= (int[]) is.readObject();
		if(p instanceof Person){
			Person person=(Person)p;
			System.out.println(person.getName());
		}
		System.out.println(p);
		System.out.println(Arrays.toString(arr));
		//3,关闭
		is.close();
	}
	//序列化输出
	public static void write(String path) throws IOException{
		//1.输出对象信息
		ObjectOutputStream os=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
		//2.准备数据
		Person p=new Person("冬冬",18);
		int[] arr={1,2,3,4};
		//3.输出
		os.writeObject(p);
		os.writeObject(arr);
		//4.刷出
		os.flush();
		//5.关闭
		os.close();
		
		p.setAge(100);
	}
}

class Person implements Serializable{
	private  String name;
	private static int age;
	
	public Person() {
		// TODO Auto-generated constructor stub
	}

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

	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;
	}

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

 

  • 14
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值