java-I/O

IO

IO(Input/Output)是计算机输入/输出的接口。java的核心库java.io提供了全方面的IO接口,包括:文件系统的操作,文件读写,标准设备输出等等

File类及使用 

File对象封装了文件或路径属性,但不包含对文件读写数据的方法

部分File类常用方法 

public String getName() 获取文件或目录的名字

public String getParent() 获取父目录的路径字符串

public File getParentFile() 获取父目录路径的File对象

public String getAbsolutePath() 获取文件或目录的绝对路径

public boolean exists() 判断文件或目录是否存在

Public File[] listFiles() 获得目录里的文件和目录封装成File对象放到File数组里

public boolean isDirectory() 判断是不是文件夹或者目录

public boolean isFile() 判断是不是文件

public long length() 获取文件的大小

boolean delete() 删除文件或文件夹

boolean mkdir() 创建文件夹

	package my;
	
	import java.io.*;
	
	public class IO {
		public static void main(String[] args)
		{
		File file1 = new File("c:\\test");
		System.out.println(file1.getAbsolutePath());
		System.out.println(file1.getParent());    //test的父目录
		System.out.println(file1.isDirectory());   //是否存在test文件夹
		System.out.println(file1.isFile());        //是否存在test文件
		System.out.println(file1.exists());        //是否存在
		System.out.println(file1.length());
		System.out.println(file1.delete());//存在直接删除test文件夹
        //只能删除空文件夹,若里面有文件则需要递归删除
		File file2 = new File("c:\\apple");
		System.out.println("apple " + file2.mkdir());
		 //创建成功返回true,若原来有此文件夹则返回false
		File file3 = new File("c:\\apple\\1.txt");
		try {
			System.out.println("1.txt " + file3.createNewFile());
		     //创建文件,成功true,原来有返回false
		    //使用creatNewFile的时候会抛出异常,需要捕获
		}
		catch(IOException e){
			e.printStackTrace();
		}
		
		String[] files1 = file2.list();
		for(String f:files1) {
			System.out.println("files1 " + f);
		}
		//获取一个文件里面的所有文件名和目录名
		//返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录
		
		String[] files2 = file2.list(new FilenameFilter() {
			public boolean accept(File dir, String name) { 
				//dir : 被找到的文件所在的目录
				//name:文件的名称
				return name.endsWith(".txt");
			}
		});
		for(String f:files2) {
			System.out.println("files2 " + f);
		}
		//返回文件里面指定值的文件名和目录名
		//返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录
		
		
		File[] files3 = file2.listFiles();
		for(File f:files3) {
			System.out.println("files3 " + f.getName() + "--" + f.length());
		}
		//返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
		//包括一些文件属性:文件大小等
		
		File[] files4 = file2.listFiles(new FilenameFilter() {
			public boolean accept(File dir, String name) {
				return name.endsWith(".txt");
				}
		});
		for(File f:files4) {
			System.out.println("files4 " + f.getName() + "--" + f.length());
		}
		//返回一个抽象路径名数组,这些路径名表示此抽象路径名满足指定过滤器的文件和目录
		//包括一些文件属性:文件大小等
		
		File[] files5 = file2.listFiles(new FileFilter() {
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".txt");
			}
		});
		for(File f:files5) {
			System.out.println("files5: " + f.getName() + "--" + f.length());
		}
		//返回一个抽象路径名数组,这些路径名表示此抽象路径名满足指定过滤器的文件和目录
		//包括一些文件属性:文件大小等
		}
	}

Console:
//c:\test
//c:\
//false
//false
//false
//0
//false
//apple false
//1.txt false
//files1 1.doc
//files1 1.mpp
//files1 1.txt
//files1 2.txt
//files2 1.txt
//files2 2.txt
//files3 1.doc--9216
//files3 1.mpp--178688
//files3 1.txt--0
//files3 2.txt--0
//files4 1.txt--0
//files4 2.txt--0
//files5: 1.txt--0
//files5: 2.txt--0

FileInputStream和FileOutputStream

FileInputStream类和FileOutputStream类用于从文件读取/写入字节,他们所有的方法都是从InputTream类和OutputStream类中继承的,没有引进新方法

I/O类中几乎所有的方法都会抛出异常IOExecption,所以必须在方法中声明抛出IOException异常,或者将代码放到tyr-catch块这种

对文件的读写操作使用缓冲区会大大提高文件读写效率

FileInputStream能从文件读取字节的InputStream类

FileOutputStream表示能向文件写入字节的OutputStream类

package my;

import java.io.*;
public class FileInputStreamOutputStream {
	public static void main(String[] args) {
		try {
			FileCopyUtil.copyFile(new File("c:\\picture\\1.png"), new File("c:\\test\\1.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class FileCopyUtil{ 
	public static void copyFile(File src, File dst) throws IOException{
		FileInputStream fis = new FileInputStream(src); //从原文件读取文件
		FileOutputStream fos = new FileOutputStream(dst);  //写到指定文件当中
	 	//直接从输入流中读到输出流中
		long time1 = System.currentTimeMillis();
		int data = -1;
		while((data = fis.read()) != -1){
			fos.write(data);
		}
		fis.close();
		fos.close();
		long time2 = System.currentTimeMillis();
		
		//将输入流中的数据存到缓冲区中最后一起读到输出流
		byte [] buf = new byte[1024*1024];//创建一个1M大小的缓冲区,用来存放输入流中的字节数
		int len = 0;
		long time1 = System.currentTimeMillis();
		while((fis.read(buf)) != -1) {
			fos.write(buf,0,len);
		}
		fis.close();
	    fos.close();
    	long time2 = System.currentTimeMillis();
		System.out.println("finished : " + (time2 - time1));
	}
}

ByteArrayInput/OutputStream

ByteArrayInputStream是把字节数组当成源的输入流

ByteArrayOutputStream是把字节数组当做目标的输出流

package my;

import java.io.*;

public class ByteArrayInputStreamByteArrayOutputStream {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
        //把字符串转换成字节数组,再从这个字节数组里读出来一个个打印输出
		String str = "hello,world";
		ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
		int data = -1;
		while((data = bis.read()) != -1) {
			System.out.print((char)data);
		}
		bis.close();
		
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write(97);
		bos.write(65);
		bos.write("hello".getBytes());
		byte[] buff = bos.toByteArray();
		for(byte data : buff) {
			System.out.print((char)data);
		}
		FileOutputStream fos = new FileOutputStream("c:\\test\\1.txt", true);
        //只会追加不会覆盖源文件内容
		bos.writeTo(fos);
        //把ByteArrayOutputStream内部缓冲区的数据写到对应的文件输出流中
		fos.close();
	}

}

FilterInputStream和FilterOutputStream(过滤流)

是为某种目的过滤字节的数据流,基本字节输入流提供的读取方法只能用来读取字节,如果要读取整数值、双精度值或字符串,需要一个过滤器类来包装字节输入流

常用的过滤流 BufferedInputStream和BufferedOutputStream, DataInputStream和DataOutputStream

DataInputStream从数据流中读取字节并转化为适当的基本类型值或字符串,DataOutputStream将基本类型的值或字符串转化为字节,并输出到输出数据流

BufferedInputStream和BufferedOutputStream可以通过减少读写次数来提高输入输出速度,BufferedOutputStream类为存储字节在流中添加一个缓冲区,以提高处理效率

BufferedInputStream类和BufferedOutputStream类

import java.io.*;
public class BufferedInputStreamOutputStream {
	public static void main(String[] args) {
		try {
			FileUtil.copyFile(new File("c:\\picture\\1.png"), new File("c:\\test\\1.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class FileUtil{ 
	public static void copyFile(File src, File dst) throws IOException{
		FileInputStream fis = new FileInputStream(src); //从原文件读取文件
		FileOutputStream fos = new FileOutputStream(dst);  //写到指定文件当中
		BufferedInputStream bis = new BufferedInputStream(fis);
        //对fis这个文件增加缓冲区的功能
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		int data = 0;
		long time1 = System.currentTimeMillis();
		while((data = bis.read()) != -1) {
			bos.write(data);
		}
		//关闭包装类就可以
		bis.close();
		bos.close();
		long time2 = System.currentTimeMillis();
		System.out.println("finished : " + (time2 - time1) + "毫秒");
	}
}

DataInputStream类和DataOuputStream类

package my;

import java.io.*;

public class DataInputStreamOutputStream {
	public static void main(String[] args) throws IOException {
		String name = "zhangsan";
		int age = 10;
		boolean flag = true;
		char sex = 'm';
		double money = 100.2;
		
        //写入文件操作
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("c:\\test\\b.txt"));
		//创建一个文件并将它实例化
		dos.writeUTF(name);
		dos.writeInt(age);
		dos.writeBoolean(flag);
		dos.writeChar(sex);
		dos.writeDouble(money);
		dos.close(); //关闭文件
		
        //将文件信息读取出来
        DataInputStream dis = new DataInputStream(new FileInputStream("c:\\test\\b.txt"));
		//读的必须和写的顺序一致
		System.out.println(dis.readUTF());
		System.out.println(dis.readInt());
		System.out.println(dis.readBoolean());
		System.out.println(dis.readChar());
		System.out.println(dis.readDouble());
		dis.close();
	}
}

BufferedInputStream和BufferedOutputStream:需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率

DataInputStream和DataOutputStream:数据输入输出流允许应用程序读写基本java数据类型。应用程序可以使用数据输出流写入稍后有数据输入流读取。读写顺序要保持与一致

装饰模式

装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展

装饰模式中的角色有

抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象

具体构件(ConcreteComponent)角色:定义一个将要接受附加责任的类

装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件方法一致的方法

具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任

Component为统一接口,也是装饰类和被装饰类的基本类型。

ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。

Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。

ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰

public interface Component {    //接口
	public void doThingA();
}


public class Decorator implements Component {
	private Component component = null;
	
	public Decorator(Component component) {
		this.component = component;
	}
	@Override
	public void doThingA() {
		// TODO Auto-generated method stub
		component.doThingA();//调用被装饰对象的方法
	}

}


public class ConcreteDecorator extends Decorator {

	public ConcreteDecorator(Component component) {
		super(component);
		// TODO Auto-generated constructor stub
	}
	@Override
	public void doThingA() {
		// TODO Auto-generated method stub
		super.doThingA();//调用被包装类的方法
		doThingB();
	}
	//扩展的功能
	private void doThingB() {
		System.out.println("do B thing");
	}
}


public class ConcreteDecorator2 extends Decorator {

	public ConcreteDecorator2(Component component) {
		super(component);
		// TODO Auto-generated constructor stub
	}
	@Override
	public void doThingA() {
		// TODO Auto-generated method stub
		super.doThingA();//调用被包装类的方法
		doThingC();
	}
	//扩展的功能
	private void doThingC() {
		System.out.println("do C thing");
	}
}


public class Test {
	public static void main(String[] args) {
		ConcreteComponent component = new ConcreteComponent();
		//component.doThingA();
		ConcreteDecorator decorator1 = new ConcreteDecorator(component);
		//decorator1.doThingA();
		ConcreteDecorator2 decorator2 = new ConcreteDecorator2(decorator1);
		decorator2.doThingA();
	}
}

字符流

字节流提供处理任何类型输入/输出操作的足够功能,但不能直接操作Unicode字符,因而需要字符流

字符流层次结构额顶层是Reader和Writer抽象类

Reader是定义java的流式字符输入模式的抽象类

Writer是定义流式字符输出的抽象类,该类方法都返回void值并在出错条件下抛IOException

FileReader和FileWriter

FileReader类表示可以读取文件内容的Reader类

FileWriter表示可以写文件的Writer类

import java.io.*;

public class FileReaderWriter {
	public static void main(String[] args) throws IOException {
        //将一个文件的字符读取出来写到另一个文件里去
		FileReader fr = new FileReader("c:\\test\\1.txt");
		FileWriter fw = new FileWriter("c:\\test\\4.txt");
		 char [] buff = new char[100];
		int len = 0; //实际读到的字符个数
		while((len = fr.read(buff)) != -1) {
			fw.write(buff, 0, len);
		}
		fr.close();
		fw.close();
	}
}

BufferedReader和BufferedWriter

BufferedReader通过缓冲输入提高性能

BufferedWriter通过缓冲输出提高性能

其他流

ObjectInputStream/OutputStream

InputStreamReader/OutputStreamWriter

RandomAccessFile

ObjectInputStream/OutputStream

ObjectInputStream和ObjectOutputStream分别与FileOutputStream和FileInputStream一起使用时,可以为应用程序提供对对象的持久存储。我们把对象以某种特定的编码格式写入称之为“序列化”。把写入的编码格式内容还原成对象称之为“反序列化”

被序列化的对象必须实现Serializable接口

ObjectOutputStream将java对象的基本数据类型和图形写入OutputStream

writeObject(Object obj):将指定的对象写入ObjectOutputStream

ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化

readObject():从ObjectInputStream读取对象

package otherio;

import java.io.*;

public class ObjectInputOutStream {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		//向文件里输入对象,序列化
		Student stu = new Student("zhangsan", 30);
		//FileOutputStream fos = new FileOutputStream("c:\\test\\10.txt");
		//ObjectOutputStream oos = new ObjectOutputStream(fos);
		//与上面的等价
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c:\\test\\10.txt"));
		oos.writeObject(stu);//把对象序列化到指定的文件输出流中
		oos.close();//释放资源
		
		//反序列化
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c:\\test\\10.txt"));
		try {
			Student stu = (Student)ois.readObject();
			System.out.println(stu);
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
	
	}

}

class Student implements Serializable{
	private String name;
	private int age;
	public Student(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;
	}
	public String toString() {    //覆盖原有类里的toString方法
		return "Student [name = " + name + ", age =" + age + "]";
	}
	
}

eg:Student [name = zhangsan, age =30]

InputStreamReader/OutputStreamWriter

转换流是指将字节流与字符流之间的转换

转换流的出现方便了对文件的读写, 它在字符流与字节流之间架起了一座桥梁,使原本毫无关联的两种流操作能够进行转化,提高了程序的灵活性

字节流中的数据都是字符时,转成字符流操作更高效

如果使用非默认编码保存文件或者读取文件时,需要用到转换流,因为字节流的重载构造方法中有指定编码格式的参数,而FileReader与FileWriter是默认编码的文本文件

常见的编码表

ASCII:美国标准信息交换码,用一个字节的7位可以表示

ISO8859-1:拉丁码表,欧洲码,表示用一个字节的8位表示

GB2312:中国的中文编码表

GBK:中国的中文编码表升级

Unicode:国际标准码,融合了多种文字,所有文字都用两个字节来表示

UTF-8:最多用三个字节来表示一个字符

InputStreamReader是字节流通向字符流的桥梁

OutputSteamWriter是字符流通向字节流的桥梁

package otherio;

import java.io.*;

public class InputStreamWriterReader {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
        //写入文件操作
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:\\test\\10a.txt"), "utf-8");
		BufferedWriter bw = new BufferedWriter(osw);//加了缓冲区
		bw.write("你好");
		bw.close();
		
        //从文件读取操作,运用缓冲区
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("c:\\test\\10a.txt"),"utf-8"));
		String line = null;
		while((line = br.readLine())!= null) {
			System.out.println(line);
		}
	}

}

eg:你好

RandomAccesFile(随机访问文件)

支持对随机访问文件的读取和写入

随机访问文件的行为类似存储在文件系统中的一个大型byte数组存在指向该隐含数组的光标或索引,称为文件指针

输入操作从文件指针开始读取字节,随着对字节的读取而迁移此文件指针

如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,随着对字节的写入而前移此文件指针

写入隐含数组末尾之后的输出操作导致该数组扩展

该文件指针可以通过getFilePointer方法读取,通过seek方法设置

package otherio;

import java.io.*;
import java.util.Scanner;

public class RandomAccessFileio {
	public static void main(String[] args) throws IOException{
		Person[] persons = {new Person("lisi",90), new Person("justin",24), new Person("zhangsan",18), new Person("wangwu", 39)};
        //初始化对象
		java.io.RandomAccessFile raf = new java.io.RandomAccessFile("c:\\test\\io.txt", "rw");
		//写入数据到RandomAccessFile对象中去
		for(int i = 0; i < persons.length; i++) {
			raf.writeChars(persons[i].getName());
			raf.writeInt(persons[i].getAge());
		}
		//读取指定位置上的的Person对象
		Scanner scanner = new Scanner(System.in);
		int num = scanner.nextInt();    //输入一个数,取第num个人的姓名和年龄
		//使用seek方法来操作存取位置,从第0个开始,所以要seek-1
		raf.seek((num-1) * Person.size());
		Person person = new Person();
		person.setName(readName(raf));
		person.setAge(raf.readInt());
		System.out.println("姓名" + person.getName());
		System.out.println("年龄" + person.getAge());
		raf.close();
	}
	private static String readName(RandomAccessFile raf) throws IOException {
		char[] name = new char[15];
		for(int i = 0; i < name.length; i++) {
			name[i] = raf.readChar();
		}
		return new String(name).replace('\u0000', ' ');
	}
}
class Person{
	private String name;    //2个字节,unicode编码,将名字长度固定为15个字符
	private int age; //4个字节
	//person一共有34个字节
    public Person() {
		
	}
	public Person(String name, int age) {
		StringBuilder builder = null;    
        //动态字符串,Stringbuilder默认大小:传进去字符串+16
		if(name != null) {
			builder = new StringBuilder(name);    //传过来名字不为空,就等于其名字
		}else {
			builder = new StringBuilder(15);    //为空就等于15
		}
		builder.setLength(15);//设置固定长度为15个,空字符'\u0000'
		this.name = builder.toString() ;
		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;
	}
	//每个对象所占的字节数
	public static int size() {
		return 34;
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

窗外藏深海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值