Java-IO-3

版权声明:本文为博主原创小文章,转载请联系我,邮箱[email protected] https://blog.csdn.net/qq_39210208/article/details/86574244

File类:

	用于将文件和文件夹封装成对象。
	
	1,创建。
		boolean createNewFile():如果该文件不存在,会创建,如果已存在,则不创建。不会像输出流一样会覆盖。		
		boolean mkdir();
		boolean mkdirs();

	2,删除。
		boolean delete();
		void deleteOnExit();
		
	3,获取:
		String getAbsolutePath();
		String getPath();
		String getParent();
		String getName();
		long length();
		long lastModified();
			
	4,判断:
		boolean exists();
		boolean isFile();
		boolean isDirectory();

1、需求:对指定目录进行所有内容的列出(包含子目录中的内容)也可以理解为 深度遍历。

public class FileTest {
	public static void main(String[] args) {
		File dir = new File("e:\\demodir");		
		listAll(dir,0);
	}
	public static void listAll(File dir,int level) {
		System.out.println(getSpace(level)+dir.getName());
		//获取指定目录下当前的所有文件夹或者文件对象		
		level++;
		File[] files = dir.listFiles();		
		for(int x=0; x<files.length; x++){			
			if(files[x].isDirectory()){
				listAll(files[x],level);
			}
			else
				System.out.println(getSpace(level)+files[x].getName());
		}	
	}

	private static String getSpace(int level) {		
		StringBuilder sb = new StringBuilder();		
		sb.append("|--");
		for(int x=0; x<level; x++){
			sb.insert(0,"|  ");
		}		
		return sb.toString();
	}
}

2、删除一个带内容的目录。
原理:必须从最里面往外删,需要进行深度遍历。

public class RemoveDirTest {
	public static void main(String[] args) {
		File dir  = new File("e:\\demodir");
		removeDir(dir);
	}

	public static void removeDir(File dir) {		
		File[] files = dir.listFiles();		
		for(File file : files){		
			if(file.isDirectory()){
				removeDir(file);
			}else{
				System.out.println(file+":"+file.delete());
			}
		}
		System.out.println(dir+":"+dir.delete());
	}
}

Properties

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		/*
		 * Map
		 * 	|--Hashtable
		 * 		|--Properties:
		 * 
		 * Properties集合:
		 * 特点:
		 * 1,该集合中的键和值都是字符串类型。
		 * 2,集合中的数据可以保存到流中,或者从流获取。
		 * 
		 * 通常该集合用于操作以键值对形式存在的配置文件。 
		 */		
//		methodDemo_4();
//		myLoad();		
		test();
	}
	
	//对已有的配置文件中的信息进行修改。 
	/*
	 * 读取这个文件。
	 * 并将这个文件中的键值数据存储到集合中。
	 * 在通过集合对数据进行修改。
	 * 在通过流将修改后的数据存储到文件中。 
	 */
	public static void test() throws IOException{
		//读取这个文件。
		File file = new File("info.txt");
		if(!file.exists()){
			file.createNewFile();
		}
		FileReader fr = new FileReader(file);
			
		//创建集合存储配置信息。
		Properties prop = new Properties();
		
		//将流中信息存储到集合中。
		prop.load(fr);		
		
		prop.setProperty("wangwu", "16");					
		FileWriter fw = new FileWriter(file);		
		prop.store(fw,"");	
		fw.close();
		fr.close();		
	}
	
	
	
	//模拟一下load方法。
	public static void myLoad() throws IOException{
		
		Properties prop  = new Properties();
		
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
		
		String line = null;
		
		while((line=bufr.readLine())!=null){
			
			if(line.startsWith("#"))
				continue;
			
			String[] arr = line.split("=");
			
//			System.out.println(arr[0]+"::"+arr[1]);
			prop.setProperty(arr[0], arr[1]);
		}
		
		prop.list(System.out);
		
		bufr.close();
		
	}
	
	public static void methodDemo_4() throws IOException {	
		
		Properties prop  = new Properties();
		
		//集合中的数据来自于一个文件。 
		//注意;必须要保证该文件中的数据是键值对。
		//需要使用到读取流。 
		FileInputStream fis = new FileInputStream("info.txt");
		
		//使用load方法。 
		prop.load(fis);
		
		prop.list(System.out);
		
		
		
	}

	public static void methodDemo_3() throws IOException {
		Properties prop  = new Properties();
		
		//存储元素。 
		prop.setProperty("zhangsan","30");
		prop.setProperty("lisi","31");
		prop.setProperty("wangwu","36");
		prop.setProperty("zhaoliu","20");
		
		//想要将这些集合中的字符串键值信息持久化存储到文件中。
		//需要关联输出流。
		FileOutputStream fos = new FileOutputStream("info.txt");
		
		//将集合中数据存储到文件中,使用store方法。
		prop.store(fos, "info");
		
		fos.close();
		
	}

	/**
	 * 演示Properties集合和流对象相结合的功能。
	 */
	
	public static void methodDemo_2(){
		Properties prop  = new Properties();
		
		//存储元素。 
//		prop.setProperty("zhangsan","30");
//		prop.setProperty("lisi","31");
//		prop.setProperty("wangwu","36");
//		prop.setProperty("zhaoliu","20");
	
		prop = System.getProperties();
		prop.list(System.out);
	}
	
	/*
	 * Properties集合的存和取。
	 */
	
	public static void propertiesDemo(){
		//创建一个Properties集合。
		
		Properties prop  = new Properties();
		
		//存储元素。 
		prop.setProperty("zhangsan","30");
		prop.setProperty("lisi","31");
		prop.setProperty("wangwu","36");
		prop.setProperty("zhaoliu","20");
		
		//修改元素。 
		prop.setProperty("wangwu","26");
		
		//取出所有元素。
		Set<String> names = prop.stringPropertyNames();
		
		for(String name : names){
			String value = prop.getProperty(name);
			System.out.println(name+":"+value);
		}
	}
}
/*
 * 定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示。并不要在运行程序。
 * 
 * 思路:
 * 1,应该有计数器。 
 * 每次程序启动都需要计数一次,并且是在原有的次数上进行计数。
 * 
 * 2,计数器就是一个变量。 突然冒出一想法,程序启动时候进行计数,计数器必须存在于内存并进行运算。
 * 可是程序一结束,计数器消失了。那么再次启动该程序,计数器又重新被初始化了。
 * 而我们需要多次启动同一个应用程序,使用的是同一个计数器。 
 * 这就需要计数器的生命周期变长,从内存存储到硬盘文件中。
 * 
 * 3,如何使用这个计数器呢?
 * 	首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件。
 *  获取上一次计数器次数。 并进行试用次数的判断。
 *  其次,对该次数进行自增,并自增后的次数重新存储到配置文件中。 
 *  
 * 4,文件中的信息该如何进行存储并体现。
 * 	直接存储次数值可以,但是不明确该数据的含义。 所以起名字就变得很重要。
 * 	这就有了名字和值的对应,所以可以使用键值对。
 * 	可是映射关系map集合搞定,又需要读取硬盘上的数据,所以map+io = Properties.
 */

.
.

public class PropertiesTest {
	/**
	 * @param args
	 * @throws IOException 
	 * @throws Exception 
	 */
	public static void main(String[] args) throws IOException  {	
		getAppCount();		
	}
	
	public static void getAppCount() throws IOException{		
		//将配置文件封装成File对象。
		File confile = new File("count.properties");		
		if(!confile.exists()){
			confile.createNewFile();
		}
		
		FileInputStream fis = new FileInputStream(confile);
		
		Properties prop = new Properties();
		
		prop.load(fis);
			
		//从集合中通过键获取次数。		
		String value = prop.getProperty("time");
		//定义计数器。记录获取到的次数。
		int count =0;
		if(value!=null){
			count = Integer.parseInt(value);
			if(count>=5){
//				System.out.println("使用次数已到,请注册,给钱!");
//				return;
				throw new RuntimeException("使用次数已到,请注册,给钱!");
			}
		}
		count++;
		
		//将改变后的次数重新存储到集合中。
		prop.setProperty("time", count+"");
				
		FileOutputStream fos = new FileOutputStream(confile);	
		prop.store(fos, "");		
		fos.close();
		fis.close();		
	}
}
/*
 * 获取指定目录下,指定扩展名的文件(包含子目录中的)
 * 这些文件的绝对路径写入到一个文本文件中。
 * 简单说,就是建立一个指定扩展名的文件的列表。 
 * 
 * 思路:
 * 1,必须进行深度遍历。
 * 2,要在遍历的过程中进行过滤。将符合条件的内容都存储到容器中。
 * 3,对容器中的内容进行遍历并将绝对路径写入到文件中。 
 */
public class Test {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {			
		File dir = new File("e:\\java0331");		
		FilenameFilter filter = new FilenameFilter(){
			@Override
			public boolean accept(File dir, String name) {				
				return name.endsWith(".java");
			}			
		};
		List<File> list = new ArrayList<File>();
		
		getFiles(dir,filter,list);
		
		File destFile = new File(dir,"javalist.txt");
		
		write2File(list,destFile);		
	}
	/**
	 * 对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤,
	 * 将过滤后的内容存储到指定容器List中。
	 * @param dir
	 * @param filter
	 * @param list
	 */
	public static void getFiles(File dir,FilenameFilter filter,List<File> list){		
		File[] files = dir.listFiles();	
		for(File file : files){
			if(file.isDirectory()){
				//递归啦!
				getFiles(file,filter,list);
			}else{
				//对遍历到的文件进行过滤器的过滤。将符合条件File对象,存储到List集合中。 
				if(filter.accept(dir, file.getName())){
					list.add(file);
				}
			}
		}	
	}
	
	public static void write2File(List<File> list,File destFile)throws IOException{	
		BufferedWriter bufw = null;
		try {
			bufw = new BufferedWriter(new FileWriter(destFile));
			for(File file : list){
				bufw.write(file.getAbsolutePath());
				bufw.newLine();
				bufw.flush();
			}		
		} /*catch(IOException e){		
			throw new RuntimeException("写入失败");
		}*/finally{
			if(bufw!=null)
				try {
					bufw.close();
				} catch (IOException e) {					
					throw new RuntimeException("关闭失败");
				}
		}
	}
}

PrintStream

	/* 1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。 
	 * 2,它不抛IOException.
	 * 
	 * 构造函数,接收三种类型的值:
	 * 1,字符串路径。
	 * 2,File对象。
	 * 3,字节输出流。
	 */
public class PrintStreamDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		PrintStream out = new PrintStream("print.txt");
		
//		int by = read();
//		write(by);
		
//		out.write(610);//只写最低8位,
		
//		out.print(97);//将97先变成字符保持原样将数据打印到目的地。 	
		out.close();	
	}
}
	/*
	 * PrintWriter:字符打印流。
	 * 构造函数参数:
	 * 1,字符串路径。
	 * 2,File对象。
	 * 3,字节输出流。
	 * 4,字符输出流。
	 */
public class PrintWriterDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));		
		PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);		
		String line =  null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			out.println(line.toUpperCase());
	//		out.flush();
		}		
			out.close();
			bufr.close();
		}
	}

总结:

IO中的其他功能流对象:

1,打印流:
	PrintStream:字节打印流。
		特点:
		1,构造函数接收File对象,字符串路径,字节输出流。意味着打印目的可以有很多。
		2,该对象具备特有的方法 打印方法 print println,可以打印任何类型的数据。
		3,特有的print方法可以保持任意类型数据表现形式的原样性,将数据输出到目的地。
			对于OutputStream父类中的write,是将数据的最低字节写出去。
			
	PrintWriter:字符打印流。
		特点:
		1,当操作的数据是字符时,可以选择PrintWriter,比PrintStream要方便。
		2,它的构造函数可以接收 File对象,字符串路径,字节输出流,字符输出流。
		3,构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该true对println方法有效。

什么时候用?
当需要保证数据表现的原样性时,就可以使用打印流的打印方法来完成,这样更为方便。
保证原样性的原理:其实就是将数据变成字符串,在进行写入操作。

SequenceInputStream

public static void main(String[] args) throws IOException {	
		/*
		 * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
		 */		
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int x=1; x<=3; x++){
			al.add(new FileInputStream(x+".txt"));
		}		
		Enumeration<FileInputStream> en = Collections.enumeration(al);		
		SequenceInputStream sis = new SequenceInputStream(en);		
		FileOutputStream fos = new FileOutputStream("1234.txt");	
		byte[] buf = new byte[1024];		
		int len = 0;		
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}		
		fos.close();
		sis.close();		
	}

SequenceInputStream:
特点:
1,将多个字节读取流和并成一个读取流,将多个源合并成一个源,操作起来方便。
2,需要的枚举接口可以通过Collections.enumeration(collection);

ObjectStream

public class ObjectStreamDemo {
	/**
	 * @param args
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {		
//		writeObj();
		readObj();
	}

	public static void readObj() throws IOException, ClassNotFoundException {		
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
		//对象的反序列化。 
		Person p = (Person)ois.readObject();		
		System.out.println(p.getName()+":"+p.getAge());		
		ois.close();		
	}

	public static void writeObj() throws IOException, IOException {		
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
		//对象序列化。  被序列化的对象必须实现Serializable接口。 
		oos.writeObject(new Person("小强",30));	
		oos.close();	
	}
}

ObjectInputStream 和 ObjectOutputStream

对象的序列化和反序列化。

writeObject readObject

Serializable标记接口
关键字:transient

RandomAccessFile

public class RandomAccessFileDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		/*
		 * RandomAccessFile
		 * 一看这个类名字,纠结。不是io体系中的子类。
		 * 
		 * 特点:
		 * 1,该对象即能读,又能写。
		 * 2,该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素,
		 * 3,可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置。
		 * 4,其实该对象就是将字节输入流和输出流进行了封装。 
		 * 5,该对象的源或者目的只能是文件。通过构造函数就可以看出。 
	     */		
//		writeFile();
//		readFile();
		randomWrite();
	}
	
	public static void randomWrite() throws IOException{
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw");		
		//往指定位置写入数据。
		raf.seek(3*8);		
		raf.write("哈哈".getBytes());
		raf.writeInt(108);		
		raf.close();
	}
		
	public static void readFile() throws IOException {		
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r");		
		//通过seek设置指针的位置。
		raf.seek(1*8);//随机的读取。只要指定指针的位置即可。 		
		byte[] buf = new byte[4];
		raf.read(buf);		
		String name = new String(buf);		
		int age = raf.readInt();		
		System.out.println("name="+name);
		System.out.println("age="+age);	
		System.out.println("pos:"+raf.getFilePointer());		
		raf.close();	
	}

	//使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄。
	public static void writeFile() throws IOException{
		/*
		 * 如果文件不存在,则创建,如果文件存在,不创建
		 */
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt","rw");	
		raf.write("张三".getBytes());
		raf.writeInt(97);
		raf.write("小强".getBytes());
		raf.writeInt(99);
		raf.close();
	}
}
RandomAccessFile:
	特点:
	1,即可读取,又可以写入。
	2,内部维护了一个大型的byte数组,通过对数组的操作完成读取和写入。
	3,通过getFilePointer方法获取指针的位置,还可以通过seek方法设置指针的位置。
	4,该对象的内容应该封装了字节输入流和字节输出流。
	5,该对象只能操作文件。
	
	通过seek方法操作指针,可以从这个数组中的任意位置上进行读和写
	可以完成对数据的修改。
	但是要注意:数据必须有规律。

PipedStream

public class PipedStream {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		PipedInputStream input = new PipedInputStream();
		PipedOutputStream output = new PipedOutputStream();		
		input.connect(output);		
		new Thread(new Input(input)).start();
		new Thread(new Output(output)).start();		
	}
}

class Input implements Runnable{	
	private PipedInputStream in;
	Input(PipedInputStream in){
		this.in = in;
	}
	public void run(){		
		try {
			byte[] buf = new byte[1024];
			int len = in.read(buf);			
			String s = new String(buf,0,len);		
			System.out.println("s="+s);
			in.close();
		} catch (Exception e) {
			// TODO: handle exception
		}		
	}
}

class Output implements Runnable{
	private PipedOutputStream out;
	Output(PipedOutputStream out){
		this.out = out;
	}
	public void run(){		
		try {
			Thread.sleep(5000);
			out.write("hi,管道来了!".getBytes());
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}
管道流:需要和多线程技术相结合的流对象。 
PipedOutputStream
PipedInputStream 

DataSteam

public class DataSteamDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {		
//		writeData();
		readData();		
	}

	public static void readData() throws IOException {		
		DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));		
		String str = dis.readUTF();		
		System.out.println(str);
	}

	public static void writeData() throws IOException {		
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));	
		dos.writeUTF("你好");		
		dos.close();		
	}
}
用操作基本数据类型值的对象。
	DataInputStream
	DataOutputStream

ByteArrayStream

public class ByteArrayStreamDemo {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) {
		ByteArrayInputStream bis = new ByteArrayInputStream("abcedf".getBytes());		
		ByteArrayOutputStream bos = new ByteArrayOutputStream();		
		int ch = 0;		
		while((ch=bis.read())!=-1){
			bos.write(ch);
		}		
		System.out.println(bos.toString());
	}
}
设备是内存的流对象。
ByteArrayInputStream ByteArrayOutputStream
CharArrayReader  CharArrayWriter

.
.
.
.

IO流体系:

字符流:
Reader
	|--BufferedReader:
		|--LineNumberReader
	|--CharArrayReader
	|--StringReader
	|--InputStreamReaer
		|--FileReader


Writer
	|--BufferedWriter
	|--CharArrayWriter
	|--StringWriter
	|--OutputStreamWriter
		|--FileWriter
	|--PrintWriter



字节流:
InputStream
	|--FileInputStream:
	|--FilterInputStream
		|--BufferedInputStream
		|--DataInputStream
	|--ByteArrayInputStream
	|--ObjectInputStream
	|--SequenceInputStream
	|--PipedInputStream


OutputStream
	|--FileOutputStream
	|--FilterOutputStream
		|--BufferedOutputStream
		|--DataOutputStream
	|--ByteArrayOutputStream
	|--ObjectOutputStream
	|--PipedOutputStream
	|--PrintStream

RandomAccessFile:

猜你喜欢

转载自blog.csdn.net/qq_39210208/article/details/86574244