IO


  IO基础知识:
1.System :类中的方法和属性都是静态的。

out:标准输出,默认是控制台。

In:标准输入,默认是键盘

获取系统属性信息:Properties getProperties()

System中常用字段、方法:

字段:

static InputStream in  “标准”输入流 对应的是键盘

static PrintStream out “标准”输出流,对应的是控制台

方法:

static Properties getProperties(); 确定当前的系统属性

static String getProperty (String key) 获取指定键指示的系统属性

static String setProperty(String key,String value)设置指定键指示的系统属性

举例:

<span style="font-size:14px;">package day08;

import java.util.Properties;
import java.util.Set;

public class SystemDemo {

	
	public static void main(String[] args) {
		 //获得系统属性,系统属性石以键值对存在
		Properties pro =System.getProperties();
		//获得键视图
		Set set = pro.keySet();
		 //用高级for循环,根据键取值。
		for(Object obj:set)
		{
			System.out.println(obj+"::"+pro.getProperty((String) obj));
		}
		// 自定义设置系统属性
		pro.setProperty("lisi", "hshss");
		//取出指定键值的属性值
		System.out.println(pro.getProperty("os.name"));
		System.out.println(pro.getProperty("lisi"));
		
		
	}

}
</span>

Runtime: 每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行环境相连接。可以通过getRuntime方法获取当前运行时。

该类并没有提供构造函数说明不可以new对象那么会直接想到该类中的方法都是静态的发现该类中没有非静态方法说明该类肯定会提供了方法获取本类对象而且该方法是静态的并且返回值类型是本类类型由这个特点可以看出该类使用了单例设计模式

方法:

static Runtime getRuntime() 返回与当前Java程序相关联的运行时

Process exec(String command) 在单独的进程中执行指定的字符串命令

举例:

       //获取运行时
        Runtime rt = Runtime.getRuntime();
        //执行window程序
        rt.exec("D:\\PPTV\\PPLive.exe");


Date表示特定的瞬间,精确到毫秒

构造函数 Date()分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)

SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期--->文本)、解析(文本---->日期)和规范化。

常用构造函数:SimpleDateFormat(String pattern)用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat

常用方法:

String format(Date Date) 将一个Date格式化为日期/时间字符串。

举例:

<span style="font-size:14px;">package day08;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo {

	
	public static void main(String[] args) {
	
		Date d = new Date();
		System.out.println(d);
		//将模式封装到SimpleDateFormat对象中
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
		//调用format方法让模式格式化指定Date对象
		String time = sdf.format(d);
		System.out.println(time);

	}

}
</span>
结果:

Sat Nov 29 19:05:32 CST 2014
2014年11月29日

Calender

常用方法:

abstract void add(int Field, int amount)根据日历的规则,为给定的日历字段添加或减去指定的时间量

static Calender getInstance() 使用默认的时区和语言环境获得一个日历

int get(int field) 返回给定字段的值

void set(int year,int month,int date)设置日历字段YEAR、MONTH、和DAY_OF_MONTH的值

举例:
<span style="font-size:14px;">package day08;

import java.awt.print.Printable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateDemo {

	
	public static void main(String[] args) {

		//获得一个实例
		Calendar cal= Calendar.getInstance();
		
		// 设置3天之后的日期的偏移量
		cal.add(Calendar.DAY_OF_MONTH, 3);
		//打印日期
		Print(cal);
	}

	private static void Print(Calendar cal) {
		String[] str ={"1月","2月","3月","4月",
				"5月","6月","7月","8月",
				"9月","10月","11月","12月"};
		String[] str1={"","星期日","星期一","星期二","星期三","星期四",
				"星期五","星期六"};
		//计算机获取month是从o月开始算的,
		int month = cal.get(Calendar.MONTH);
		int week = cal.get(Calendar.DAY_OF_WEEK);
		System.out.println(cal.get(Calendar.YEAR)+"年"+str[month]  
                +cal.get(Calendar.DAY_OF_MONTH)+"日"  
                +str1[week]);
		
	}

}
</span>
Math

包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。该类全为静态方法。

 方法:

doubleceil(double d);//返回大于指定数据的最小整数

doublefloor(double d);//返回小于指定数据的最大整数

double pow(doublea,double b);//返回ab次方

long round(doubleb);//返回b四舍五入的值 

doublerandom();//返回正号的double值,是一个大于等于0.0且小于1.0的随机数


IO重点解析:

基础掌握

1.IO是inputoutput的缩写。

流概念:

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。


2.特点:

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流与字符流

流按流向分为:输入流,输出流

字符流是为了处理文字数据 可以指定编码表

3.IO的常用基类,这里体现多态的应用,常用父类的引用指向子类对象


字节流的抽象基类:InputStream OutputStream

字符流的抽象基类:Reader Writer

字符流的重点掌握:

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

· 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

· 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据


1.close()flush()区别:

flush()刷新后,流可以继续使用;

close()刷新后,将会关闭流,不可再写入字符流。

2.创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件。且该目录下如果已有同名文件,则同名文件将被覆盖。其实该步就是在明确数据要存放的目的地。

3.读取方式两种

第一种:read()一个字符一个字符读

第二种:建立字符数组,再读取,效率稍高

注意:

1).定义文件路径时,可以用“/”或者“\\”。

2).在创建一个文件时,如果目录下有同名文件将被覆盖。

3).在读取文件时,必须保证该文件已存在,否则出异常。

4).文件数据的续写通过构造函数 FileWriter(Strings,boolean append)

4.缓冲区技术可以提供效率
举例:文件的copy
<span style="font-size:14px;">package day08;

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

public class CopyDemo {
	public static void main(String[] args)
	{
		BufferedWriter bufw=null;
		BufferedReader bufr=null;
		try {
			//创建写缓冲对象
			bufw= new BufferedWriter(new FileWriter("E://lianxi//1.txt"));
			 //创建读缓冲对象 
			bufr= new BufferedReader(new FileReader("E://lianxi//b.txt"));
			
			int len=0;
			char[] buf=new char[1024];
			while((len=bufr.read(buf))!=-1)
			{
				//把数组的有效部分写入文件中
				bufw.write(buf,0,len);
			}
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		finally {
			if(bufw!=null)
			try {
				bufw.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}
			if(bufr!=null)
			try {
				bufr.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}
		}

	}

}
</span>

4.readline工作原理

readLine方法原理:

        无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。



5.自定义缓冲区

(1)自定义的字符流读取缓冲区。其实就是内部封装了一个数组,把数组读满,在一个一个取出,其实就是模拟一个BufferedReader.

分析:
 缓冲区中无非就是封装了一个数组
 并对外提供了更多的方法对数组进行访问。
 其实这些方法最终操作的都是数组的角标。

缓冲技术原理:此对象内部封装了数组,将数据存入,再一次性取出。
在此次取完后,在从源中继续取一批数据进缓冲区。
当源中的数据取光时,用-1作为结束标记。


记住,只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次)

举例:

<span style="font-size:14px;">import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class MyBufferReader{
	//想要Filereader的方法readline就要把Filereader对象传进来
	private FileReader r;

	//初始化时拥有一个Filereader对象
	MyBufferReader(FileReader r){
		this.r=r;	
	}

	 //自定义一个readline方法,一次可以读一行;
	public String myReadLine() throws IOException{
		//读一个存起来,可以用数组,但是我们用stringbuilder来模拟
		//定义一个临时容器,原BufferReader封装的是字符数组,为了
		//演示方便,定义Stringbuilder容器,因为最终还是要将
		StringBuilder sb = new StringBuilder();
		
		int ch=0;
		while((ch=r.read())!=-1)
		{
			//当读到换行符时,返回缓冲区的数据
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			else
				//将读到的数据加入sb中
				sb.append((char)ch);
		}
		return null;
		
	}

	public void myclose() throws IOException
	{
	r.close();	
	}
 
	
	
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("c:1.txt");
		
		MyBufferReader mybuf = new MyBufferReader(fr);
		
		String line = null;
		while((line=mybuf.myReadLine())!=null)
		{
			System.out.println(line);
			
		}
				
		mybuf.myclose();
		

	}

}


</span>

(2)自定义字节流读取缓冲区

是内部封装了一个数组,把数组读满,在一个一个取出

package Impro;
import java.io.*;
//装饰类
class MyBufferedInputStream
{
	//定义一个字节读取流,它是被装饰对象
InputStream in;
//定义字节数组
byte[] buf = new byte[1024];
//定义一个角标,一个计数器
int pos=0,count=0;
//初始化
MyBufferedInputStream(InputStream in)
{
this.in=in;	
}

public int myRead() throws IOException
{
	
	if(count==0)
	{
		//当计数器为0,就向数组读数据,用count记住数组长度,
		count=in.read(buf);	
		pos=0;
		//从数组中一个个取;
		byte b=buf[pos];
		pos++;
		count--;
		//&255,避免和结束标志重复,而提前复制结束。read方法将字节提升为32位INt型,我们只去低八位
		return b&255;
		
	}
	else if(count>0)
	{
		byte b = buf[pos];
		pos++;
		count--;
		return b&255;
	}
	
	return -1;
	
}
//关闭流,
public void myClose() throws IOException
{
in.close();	
}

}

public class MyBufferedInputStreamDemo {

	
	public static void main(String[] args) throws IOException {
		//建立自定义缓冲区读取流的对象
		MyBufferedInputStream mis = 
				new MyBufferedInputStream(new FileInputStream("E://a.mp3"));
		//建立写入流对象,并关联文件
		BufferedOutputStream bos = 
				new BufferedOutputStream(new FileOutputStream("E://a1.mp3"));
		int ch =0;
		//读一个字节,写入文件中
		while((ch=mis.myRead())!=-1)
		{
			
			bos.write(ch);
		}
		//关闭流
		mis.myClose();
		bos.close();
		

	}

}


6.装饰设计模式

1.  当想对已有对象进行功能增强时,可定义类:将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。

2、特点

        装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

3装饰和继承的区别:

        1)装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。

        2)装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰的类通常都是属于一个体系。

        3)从继承结构转为组合结构

注:在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。

举例:

<span style="font-size:14px;">public class PersonDemo {

	
	public static void main(String[] args) {
		
		Person p =new Person();
		SuperPerson p1= new SuperPerson(p);
		p1.chifan();
		
	}

}

class Person
{
public void chifan()
{
System.out.println("吃饭");	
}
}

//没有继承,自定义一个装饰类;
class SuperPerson
{
private Person p;

public SuperPerson(Person p) {
	this.p=p;
}

public void chifan(){
	System.out.println("开胃酒");
	p.chifan();
	System.out.println("甜点");
	System.out.println("来一根");
	
	
}

}
</span>

注意:自定义的缓冲区也是应用了装饰类。

二、字节流重点掌握

1.字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。

2由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。

3、读写字节流:InputStream   输入流(读)

                             OutputStream  输出流(写)

4、为何不用进行刷流动作:

        因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。

三、流操作规律

1.明确源和目的

源:输入流 InputStream Reader

目的: 输出流 OutputStream Writer

2.操作的数据是否是纯文本文档

是: 字符流

不是: 字节流

3.当体系明确后,再明确要使用哪个具体的对象

通过设备来进行区分:

源设备: 内存,硬盘,键盘。

目的设备: 内存,硬盘,控制台。

示例:

1.将一个文本文件中的数据存储到另一个文件中,复制文件。

源:因为是源,所以使用读取流:InputStream Reader

是不是操作文本文件

是 这时就可以选择Reader

这样体系就明确了

接下来明确要使用该体系中的哪个对象

明确设备: 硬盘

Reader体系统可以操作文件的对象时FileReader

是否要提高效率:是! 加入Reader体系中缓冲区:BufferedReader

FileReader fr = new FileReader(“a.txt”);

BufferedReader bufr = new BufferedReader(fr);

目的:OutputStream Writer

是否是纯文本

是Writer

设备:硬盘 一个文件

Writer体系中可以操作文件的对象FileWriter

是否需要提高效率,是。加入Writer中缓冲区BufferedWriter

FileWriter fw = new FileWriter(“b.txt”);

BufferedWriter bufw = new BufferedWriter(fw);

2.需求:将键盘录入的数据保存到一个文件中

这个需求中有源和目的的存在。

那么分别分析

源: InputStream Reader

是不是纯文本 是 Reader

设备: 键盘 对应的对象时System.in

不是选择Reader吗?System.in对应的不是字节流吗?

为了操作键盘的文本数据方便,转换成字符流按照字符串操作是最方便的

所以既然明确了Reader,那么就将System.in转换成Reader

用了Reader体系中转换流InputStreamReader

InputStreamReaderisr = new InputStreamReader(System.in);

需要提高效率吗?

需要 BufferedReader

BufferedReaderbufr  = new BufferedReader(isr);

目的:OutputStream Writer

是否是纯文本?是  Writer

设备:硬盘  Filewriter

需要提高效率吗? 需要 BufferedWriter

BufferedWriterbufw = new BufferedWriter(

newFileWriter(“d:\\a.txt”));

扩展一下,想要把录入的数据按照指定的编码表(UTF-8),将数据保存在文件中,

目的: OutputStream Writer

是否是纯文本,是 Writer

设备: 硬盘,一个文件 使用FileWriter

但是FileWriter是使用的默认编码表GBK

但是存储时,需要加入指定编码表UTF-8,而指定的编码表只有转换流可以指定

所以要使用的对象时OutputStreamWriter

而该转换流对象要接受一个字节输出流。而且还可以操作文件的字节输出流FileOutputStream

OutputStreamWriter osw = newOutputStreamWriter(new FileOutputStream(“d:\\a.txt”),”UTF-8”);

需要高效吗? 需要

所以,记住,转换流是字节和字符之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流


一、File类:

1.File:文件和目录路径名的抽象表现形式

2.特点:

        (1)用来将文件或文件夹封装成对象

        (2)方便于对文件与文件夹的属性信息进行操作

        (3)File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变

        (4)File对象可以作为参数传递给流的构造函数

3.File创建对象的三种方式:

方式一:      

             File f =new File("a.txt");

        将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。

 方式二:

            File f2=newFile("c:\\abc","b.txt");

        将文件所在目录路径和文件一起传入,指定文件路径。

 方式三:

            File d=new File("c:\\abc");

             File f3=new File(d,"c.txt");

        将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。

小知识:

        File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\windows中表示表示转义后的分隔符,但是在linux系统中就不是)。


递归

1、定义

       当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。称为递归。

2、递归注意事项

        a限定条件。是来结束循环调用,否则是死循环。

        b注意递归的次数,尽量避免内存溢出。因为每次调用自身的时候都会先执行下一次调用自己的方法,所以会不断在栈内存中开辟新空间,次数过多,会导致内存溢出。

小例子:

package Impro;

public class DiguiDemo {

	//十进制转成二进制
	public static void toBin(int num)
	{
		if(num>0)
		{
			//如果不为0,继续调用自身,num/2,
			toBin(num/2);
			System.out.println(num%2);
		}
	}
	public static void main(String[] args) {
		toBin(20);

	}

}


举例:

1.列举多级文件或文件夹,带层级的;

原理:当碰到文件夹时,继续调用自身函数,知道访问到文件为止;

package Impro;
import java.io.*;

public class ListFileDemo {
	

	public static void main(String[] args) {
		//关联指定目录
		File dir = new File("E://黑马学习");
		//列出所有目录
		showDir(dir,0);
		

	}
	
	
	public static void showDir(File dir,int level)
	{
		//加层级输出
		System.out.println(getLevel(level)+dir.getName());
		level++;
		//调用listFile方法,获取本目录下的所以文件和目录的抽象路径 
		File[] files=dir.listFiles();
		//遍历
		for(int i=0;i<files.length;i++)
		{
			if(files[i].isDirectory())
				//如果是目录,继续递归
				showDir(files[i], level);
			else
				//打印文件名
				System.out.println(getLevel(level)+files[i].getName());
		}
		
	}
	//带层级的列表
	public static String getLevel(int level)
	{
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		//每多一级目录,就多添加“ ”,
		for(int i=1;i<=level;i++)
		{
			//sb.append("|--");
			sb.insert(0, "  ");
		}
		return sb.toString();
		
	}

}

练习2:删除多级文件目录

原理:目录从里往外删,用递归

package Impro;
import java.io.*;

public class RemoveDirDemo {

	
	public static void main(String[] args) {
		//指定目录
		File dir= new File("E://黑马学习");
		//删除目录 
		removeDir(dir);
				
				

	}
	//删除传入目录 
	public static void removeDir(File dir)
	{
		//列出目录下的所以文件和文件夹  
		File[] files=dir.listFiles();
		for(int i=0;i<files.length;i++)
		{
			 //如果还是目录,递归
			if(files[i].isDirectory())
				removeDir(files[i]);
			else
				//删除文
				System.out.println(files[i].getName()+":::"+files[i].delete());
		}
		//删除目录 
		System.out.println(dir.getName()+"::"+dir.delete());
	}

}

练习3:copy多级文件夹,先复制文件夹,在复制文件。

package Impro;

import java.io.*;

public class CopyDirDemo {
	public static void main(String[] args) throws IOException {
		//指定源目录
		File dir= new File("E://黑马学习");
		//指定目的目录
		File d = new File("E://黑马学习2");
		//copy目录
		copyDir(dir, d);
				

	}

	public static void copyDir(File sourceDir, File desDir) throws IOException {
		//创建指定目录
		String name = sourceDir.getName();
		File target = new File(desDir, name);
		if (!target.exists())
			target.mkdirs();
		//列出源目录的所有文件目录或文件
		File[] files = sourceDir.listFiles();
		//遍历
		for (File file : files) {
			if (file.isDirectory())
				//如果是目录,递归
				copyDir(file, target);
			else
				//如果不是目录,copy文件
				copyFile(file, new File(target, file.getName()));
		}

	}

	public static void copyFile(File sourceFile, File desFile) throws IOException {
		//建立读取流
		BufferedInputStream bis = 
				new BufferedInputStream(new FileInputStream(sourceFile));
		//建立写入流
		BufferedOutputStream bos = 
				new BufferedOutputStream(new FileOutputStream(desFile));
		int ch=0;
		//读取的文件写入指定的目录
		while((ch=bis.read())!=-1)
		{
			bos.write(ch);
			
		}
		//关闭流
		bos.close();
		bis.close();
	}

}

练习4:将一个指定目录下的txt文件的绝对路径,存储到一个文本文件中。建立一个java文件列表的文件。

<span style="color:#000000;">package Impro;
import java.io.*;
import java.util.*;

public class JavaFileListDemo {

	
	public static void main(String[] args) throws IOException {
		//指定目录
		File dir = new File("E://黑马学习");
		//定义一个List集合,用于存储.java文件的File对象 
		List<File> list = new ArrayList<File>();
		//调用获取文件路径方法  
		fileToList(dir, list);
		//指定写入文件  
		File file = new File("E://heima.txt");
		if(!file.exists())
			file.createNewFile();
		//调用写入文件方法  
		writeToFile(list, file.toString());
		

	}
	//获取指定文件夹内的所有java文件的绝对路径,并存入集合中  
	public static void fileToList(File dir,List<File> list)
	{
		File[] files=dir.listFiles();
		for(File f:files)
		{
			if(f.isDirectory())
				 //如果是目录,则继续获取 
				fileToList(f,list);
			else if(f.getName().endsWith(".txt"))
				//将是.txt文件的绝对路径存入
				list.add(f);	
		}
	}
	//将集合中元素写入到一个文本文件中  
	public static void writeToFile(List<File> list,String name) throws IOException
	{
		 //建立字符流缓冲对象指定写入对象
		BufferedWriter bw = new BufferedWriter(new FileWriter(name));
		
		for(File f:list)
		{
			//写入 
			bw.write(f.getAbsolutePath());
			//换行
			bw.newLine();
			//刷新
			bw.flush();
		}
		
		bw.close();
	}

}
</span>


一、Properties

1PropertiesHashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。简单说,Properties=map+IO;

2、特点:

        1)可用于键值对形式的配置文件

        2)在加载时,需要数据有固定的格式,常用的是:键=

举例1:

//演示,如何将流中的数据存储到集合中。
	//想要将info.txt中键值数据存到集合中进行操作。
	/*
		1,用一个流和info.txt文件关联。
		2,读取一行数据,将该行数据用"="进行切割。
		3,等号左边作为键,右边作为值。存入到Properties集合中即可。

	*/
		//将文件数据存储进Properties集合方法
	public static void method()throws IOException
	{
		//使用字符读取缓冲流关联文件
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));

		String line = null;
		//定义Properties集合
		Properties prop = new Properties();

		   	while((line=bufr.readLine())!=null)
		{
			String[] arr = line.split("=");//将一行数据以“=”号进行分割
			//将=左边作为键存入,将=右边作为值存入
			prop.setProperty(arr[0],arr[1]);
		}

		bufr.close();//关流

		System.out.println(prop);
	}

举例2

/*
练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。
	
原理:
很容易想到的是:计数器。可是该计数器定义在程序中,随着该应用程序的退出,该计数器也在内存中消失了。
所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。键值对数据是map集合。数据是以文件形式存储。使用io技术。那么map+io——>Properties。

思路:1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建
	  2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。
	  3、将值小于等于5次的信息数据存入文件中
*/
import java.util.*;
import java.io.*;

class  RunCount
{
	public static void main(String[] args)throws IOException 
	{
		int count=runCount();
		if(count>5)//如果程序被使用了超过5次,则终止使用,并提示
		{
			System.out.println("次数到了,交钱!!!!!");
			return ;
		}
		else
			System.out.println("程序第"+count+"次Run!");
	}
	//获取程序运行的次数
	public static int runCount()throws IOException
	{
		Properties ps=new Properties();//创建集合对象

		File file=new File("info.ini");//将文件进行封装
		if(!file.exists())//判断是否存在
			file.createNewFile();
		FileReader fr=new FileReader(file);//将文件于读取流进行关联
		
		ps.load(fr);//加载流中的文件数据到集合中

		int count=0;//定义计数器
		String value=ps.getProperty("time");//获取次数值
		
		if(value!=null)//如过值不等于null,则将其赋值给count
		{
			count=Integer.parseInt(value);
		}
		count++;//每启动一次自增
		ps.setProperty("time",count+"");//将次数记录住集合

		FileWriter fw=new FileWriter(file);
		ps.store(fw,"");//将集合中的数据存入硬盘文件中
		
		fr.close();//关流
		fw.close();

		return count;//返回程序启动的次数
	}
}


二、打印流

1.打印流包括:PrintStreamPrintWriter,该流提供了打印方法,可将各种类型的数据都原样打印。

字节打印流:PrintStream 

构造方法中可接收的参数类型:

        1File对象。File

        2、字符串路径:String

        3、字符输出流:OutputStream

 

2.字符串打印流:PrintWriter

构造方法中可接受的参数类型

        1File对象:File

        2、字符串路径:String

        3、字节输出流:OutputStream 注意:很特殊,字符流的构造函数可以接受字节流。没有使用转换流

        4、字符输出流:Writer


二、 序列流

SequenceInputStream对多个流进行合并,而且构造函数定义了泛型上限;

举例: 

1.将三个文件中的数据合并到一个文件来

步骤:

1.创建vector集合。是为了获取Enumeration对象;

2.把三个文件添加进集合中,加入合并流

3.成为一个流后,和一般复制文件一样

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

class  SequenceInputStreamDemo
{
	public static void main(String[] args)throws IOException
	{
		//创建vector集合,并添加相关流对象
		Vector<InputStream> ve=new Vector<InputStream>();
		ve.add(new FileInputStream("E://1.txt"));
		ve.add(new FileInputStream("E://2.txt"));
		ve.add(new FileInputStream("E://3.txt"));
		//创建枚举对象
		Enumeration<InputStream> en=ve.elements();
		//合并流
		SequenceInputStream sis=new SequenceInputStream(en);
		//关联写入文件
		FileOutputStream fos=new FileOutputStream("E://4.txt");
		
		//反复读写操作
		byte[] buf=new byte[1024];
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		
		//关流
		fos.close();
		sis.close();
	}
}

举例2:
切割文件
需求:将一个mp3文件按1M大小切割成几部分
步骤:

1、使用文件字节流关联mp3文件

 2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中

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

class  SplitFile
{
	public static void main(String[] args) throws IOException
	{
		//指定要切割的文件
		File file=new File("E://a.mp3");
		//将指定文件进行切割
		splitFile(file);

		//指定要合并到的文件
		File file1=new File("E://a1.mp3");
		//将部分文件进行合并指定文件中
		merge(file1);

	}
	//接收一个文件,将其按1M大小进行切割
	public static void splitFile(File file)throws IOException
	{
		//关联要切割的文件
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		
		BufferedOutputStream bos=null;

		//定义1M大小存储容器
		byte[] buf=new byte[1024*1024];
		int len=0,x=0;
		while ((len=bis.read(buf))!=-1)
		{
			//每满1M就写入一个新文件中
			bos=new BufferedOutputStream(new FileOutputStream("E:\\"+(++x)+".part"));
			bos.write(buf,0,len);
			//每次写完一个文件要记得关流
			bos.close();
		}
		//关流
		bis.close();
	}

	//将部分文件合并为一个文件
	public static void merge(File file)throws IOException
	{
		//定义一个集合存储这些部分文件关联路径数据
		ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();

		for (int x=1;x<=6 ; x++)
		{
			al.add(new FileInputStream("E:\\"+x+".part"));
		}
		
		//因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类
		final  ListIterator<FileInputStream> it=al.listIterator();
		Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}

			public FileInputStream nextElement()
			{
				return it.next();
			}
		};

		//关联枚举对象
		SequenceInputStream sis=new SequenceInputStream(en);

		//将合并的文件数据写入指定文件中
		FileOutputStream fos=new FileOutputStream(file);
		
		//定义临时存储数据的数组
		byte[] buf=new byte[1024];
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);//写数据
		}

		//关流
		fos.close();
		sis.close();

	}

}












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值