System类:
System类包含一些有用类字段和方法,他不能被实例化,类中的方法和属性都是静态
getProperties获取当前系统的属性;
out:标准输出默认是控制台
int:标准输入,默认是键盘
因为Properties是HashTables的子类,也就是Map集合的一个子类对象,那么可以通过Map的方法取出该集合中的元素,该集合中存储的都是字符串,没有泛型定义
如何在系统中定义一些特有的信息呢?例如System.setProperties("myKey","myValue");
可以用java -D<name>=<value> class文件类实现jvm启动时的动态加载属性
Runtime类:
Runtime不可以创建对象因为没有可见的构造函数,他运用了单利设计模式。Runtime r=Runtime.getRuntime();
他里面有exce方法此方法可以打开指定的程序并返回Process类型,可以用Process中的destroy结束上面的进程
Date类:
SimpleDateFormat格式模板
format()格式函数
import java.util.*;
import java.text.*;
class DateTest
{
public static void main(String[] args)
{
Date d=new Date();//创建时间对象
SimpleDateFormat adf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//创建时间模板
String str=adf.format(d);//对时间对象进行格式化
System.out.println(str);//输出时间字符串
}
}
记住:SimpleDateFormat类是java.text中的,Date是java.util中的
获取任一年二月有几天:
//获取任一年的二月有多少天
Calendar c=Calendar.getInstance();
c.set(2013,2,1);
c.add(Calendar.DAY_OF_MONTH,-1);
System.out.println(c.get(Calendar.DAY_OF_MONTH));
Date d=new Date();//创建时间对象
c.setTime(d);//将现在的时间传给Calendar
c.add(Calendar.DAY_OF_MONTH,-1);//
System.out.println(c.get(Calendar.YEAR)+"年"+(c.get(Calendar.MONTH)+1)+"月"
+c.get(Calendar.DAY_OF_MONTH)+"日"+" "+c.get(Calendar.HOUR_OF_DAY)+"时"+
c.get(Calendar.MINUTE)+"分"+c.get(Calendar.SECOND)+"秒");//输出昨天现在的时刻
Math类:
这个类中常用的方法有:
random()随机取数
ceil() 返回大于指定数字的最小整数
floor()返回小于指定数字的最大值
round()四舍五入
pow() 指数幂运算
Math.random()*10 包括零不包括10;
IO(Input OutPut)流:
IO流用来处理设备之间的数据传输,java对数据的操作是通过流的方式实现的,java用于操作流的对象都在IO包中,流按照操作数据可以分为:字节流和字符流
按流向可以分为输入流和输出流
无论硬盘还是内存都可以用字节流来搞定,那为什么还要出现字符流呢
无论是什么数据,字节流都能搞定,但其中一部分是文本数据,他是比较常见的,为了方便处理这些数据,就单独分离出来了个字符流
为什么要单独分理处字符流来:
是因为编码表的存在,可以在内部融合编码表。字符流的出现是为了解决这些编码表转换之间的问题
IO流常用基数:
字节流的抽象基类:
InputStream OutputStream;
字符流的抽象类:
Reader,Writer
注:有这四个类派生出来的子类名称都是以其父类名作为子类的后缀名
如:InputStream的子类FileInputStream Reader的子类 FileReader
字符流的特点:
既然IO流是操作数据的,那么数据常见的形式就是文件
FileWriter会创建到指定目录下,如果该目录下有指定文件会将其覆盖,也可用FileWriter(文件名,true)可以指定当文件存在是不创建,当文件不存在时创建
调用Write方法,将字符传写入到流中调用flush方法刷新新对象缓冲区中的数据,将数据刷到目的地中
close的作用是关闭资源,但是关闭之前会刷新一次内部的缓冲区的资源,将数据刷新到目的地中
和flush的区别是flush运行完还可以继续添加数据,而close后就不能再添加了
import java.io.*;
class WriterTest
{
public static void main(String[] args) throws IOException
{
String str="F:\\Txt\\1.txt";
FileWriter fw=null;
try{
fw=new FileWriter(str);//不管文件中有没有此文件他都要创建个新的文件,如果有那么他将覆盖原文件
fw.write("zhang俊迪");
}catch(IOException e1){
}finally{//因为不管发生异常还是不发生异常都要关闭资源所以要将关闭程序放在finally中,这样增强程序的健壮性
try{
if(fw!=null)//判断文件是否存在,如果没存在也没有关闭的必要了
fw.close();
}catch(IOException e2){
}
}
fw=new FileWriter(str,true);//在这个地方加true是为了在当文件存在是不覆盖,直接在文件尾追加
fw.write("asdsadasd");//这个地方也应和上面一样try只是为了演示所以将异常抛出去了
fw.close();
}
}
创建一个读入流对象和指定名称的文件相关联,要保证文件存在,如果不存在,会发生FileNotFoundException异常
在window中换行是\r\n在linux中是\n
FileReader:读取文件中的信息
String str="F:\\Txt\\1.txt";
FileReader fr=new FileReader(str);//打开文件
int ch;
while((ch=fr.read())!=-1)//读取数据返回字符的ASCII码
System.out.print((char)ch);//将ASCII码转成字符输出
fr.close();
fr=new FileReader(str);
char[] ch1=new char[1024];//定义一个1024的字符串,这个地方最好是1024的整数倍
int num=0;
while((num=fr.read(ch1))!=-1){//读取数据并将读取的字符数传递给num
System.out.print(new String(ch1,0,num));
}
fr.close();
字符流的缓冲区:BufferedWriter BufferedReader
字符流的缓冲区的出现提高了流对象的读写效率
在流的基础上对流的功能进行了增强,提供了newLine换行方法,还有readLine一次读一行,当返回null时,表示到了结尾了,创建缓冲区之前必须得有流对象,只需要将要提高效率的流对象作为参数传递给缓冲取得构造函数即可,关闭缓冲区就是在关闭文件流,因此只需要关闭缓冲区即可,且如果只关闭文件流的话将不能将缓冲区的数据写入文件中切记;
public static void main(String[] args)
{
String str="F:\\Txt\\1.txt";
String str1="F:\\Txt\\2.txt";
FileWriter fw=null;//声明对象
FileReader fr=null;
BufferedWriter bw=null;
BufferedReader br=null;
try{
fr=new FileReader(str);
br=new BufferedReader(fr);
fw=new FileWriter(str1);
bw=new BufferedWriter(fw);
String s=null;
while((s=br.readLine())!=null)//读取一行的数据
{
bw.write(s);
bw.newLine();//换行
bw.flush();//记住只要用到缓冲区就要刷新,因为如果在写的时候如果缓冲区的信息没有及时刷新到文件中有可能会出现安全性
//问题,例如断电了数据还在缓冲区类没有刷新过去,那么这段的信息将会丢失
}
}
catch(IOException e1){}
finally{
try{
bw.close();//应定要关闭缓冲区的资源否则如果没有flush的话将不能讲缓冲区的数据写入到文件中去
br.close();
}catch(IOException e2){
}
}
}
readLine的原理:
不管是读一行,还是获取多个字符,其实在硬盘上都是一个一个的读入的,所以最终还是read方法
对于BufferedWriter没有子类,但是BufferedReader有一个子类LineNumberReader此类有个特有方法是getLineNumber和SetLineNumber分别是获得和设置当前行号
自定义BufferedReader的功能类,并且实现每行添加行号
import java.io.*;
class LineNumberTest
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("F:\\Txt\\1.txt");
LineNumber ln=new LineNumber(fr);//创建缓冲流对象
String str=null;
while((str=ln.addLineNumber())!=null){//获取信息
System.out.println(str);
}
ln.close();
}
}
class LineNumber extends Reader{
private Reader fr;
static int line=1;//将其声明为静态对象是为了实现行号累加功能,以为每次换号都要用到它所以设为静态了
LineNumber(Reader fr){
this.fr=fr;
}
public String addLineNumber()throws IOException{
StringBuilder sb=new StringBuilder();
int num=0;
while((num=fr.read())!=-1){
if(sb.length()==0)
sb.append(line+":");
char c=(char)num;
if(c=='\r')
continue;
if(c=='\n'){//及判断"\r"有判断"\n"是为了实现跨平台因为linux和window下的换行符不同
line++;
return sb.toString();
}
else
sb.append(c);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
/*
实例化Reader类中的抽象方法
*/
public int read(char[] buf,int off,int len)throws IOException{
return fr.read(buf,off,len);
}
public void close() throws IOException{
fr.close();
}
public void myClose() throws IOException{
fr.close();
}
}
装饰设计模式:
当想对已有的对象功能进行增强时,可以定义一个类,将已有的对象传入,基于已有的功能,比提供加强功能,那么把自定义的该类成为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供了更强的功能
装饰和继承的区别:
装饰模式比继承要灵活,避免了集成体系的臃肿,而且降低了类与类之间的关系
装饰类因为增强了已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都属于一个体系
操作字符和字节的一些类及方法:
字符流:
Writer类
|--包含的常用方法:
|----write(int c) 写入单个字符。
|----write(String s)写入字符串。
|----write(String s,int off,int len)写入字符串的某一部分。
|----- BufferedWriter类:
|---特有方法:
|--------BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。
|--------void write(char[] cbuf,int off,int len)写入字符数组的某一部分
|--------void newLine()换行
|------OutputStreamWriter类:
|---特有方法:
|-------OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。(System.out);
|--------void write(char[] cbuf,int off,int len)写入字符数组的某一部分
|---FileWriter类:
|----特有方法
|----FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
|----FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
读:
Reader:
|----常用方法:
|------ int read() 读取单个字符。返回字符编码,结束返回-1
|------int read(char[] cbuf)将字符数组读入,返回字符数,结束返回-1
|------void reset()重置该流
|------boolean ready()判断是否准备读取此流
|----BufferedReader类:
|------特有方法:
|-----int read(char[] cbuf,int off,int len)将字符读入数组的某一部分
|-----String readLine()读取一行
|------LineNumberReader类
|------特有方法:
|-----getLineNumber()得到当前行号
|-----setLineNumber(int lineNumber)设置当前行号
|----InputStreamReader类:
|------特有方法:
|------InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。(System.in)
|------int read(char[],int,int)将字符读入数组中的某一部分
|------String getEncoding()返回此流使用的字符编码的名称
|------FileReader类
|-----特有方法:
|------FileReader(File file) 创建读操作的文件
字节流:
读:
InputStream
|----常用方法:
|----int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
|----int read(byte[] b, int off, int len)将输入流中最多 len 个数据字节读入 byte 数组。
|----void reset()将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。
|----long skip(long n)跳过和丢弃此输入流中数据的 n 个字节。
|-----FileInputStream类:
|----特有方法:
|----int read()下一个数据字节;如果已到达文件末尾,则返回 -1。
|-----FilterInputStream类:
|----特有方法:
|-----int read()
|----BufferInputStream类
写:
OutputStream
|----常用方法:
|----void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
|----void write(byte[] b,int off,int len)将制定byte数组中从偏移量off开始的len个字符写入此输出流
|----FileOutputStream类:
|-----常用方法:
|-----void write(int b)将指定字节写入到文件中
|----FilterOutputStream类:
|------BufferedOutputStream类:
对于自定义的BufferedInputStream类
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf=new byte[1024*5];
private int count=0;
private int pos=0;
MyBufferedInputStream(InputStream in)
{
this.in=in;
}
public int myRead() throws IOException
{
if(count==0)//当count为零时上数组中抓入一定量的字节
{
count=in.read(buf);//将抓入的自己数复制给count
if(count==-1)//防止count上来就是-1而传多一个字节
return -1;
pos=0;//将指针归零
byte b=buf[pos];//将第一个字节传给b
count--;//字节数-1
pos++;
return b&0xff;//因为有可能读到的字节是-1所以这个地方自动提升为int类型并且将后八位不持原样其余至零
}
if(count>0)
{
byte b=buf[pos];
count--;
pos++;
return b&0xff;
}
return -1;
}
public void close()throws IOException
{
in.close();
}
}
通过写程序发现问题:
为什么read方法的返回值是int型而不是byte型
原因是信息文件都是二进制编码,很有可能出现八个1在一起的,而八个一是-1,但文件结束的条件也是-1,因此不能用byte返回,而用int返回,用int返回需要将数据进行修改,就是只保留最后八位的完整性,将其与的全变零,这样就不可能出现-1的情况了,这样一看字节多了,可是write方法中有强制转换的方法,类避免数据损失,他只读低八位
read方法在做提升,但write方法在做强转,从而保证了数据的完整性