导读:其他对象(System,Runtime,Date,Calendar,Math_Random),IO流(概述,FileWriter,IO异常处理方式,文件的续写,文本文件读取,拷贝文本文件)
1、其他对象(System)
Ø static long currentTimeMillis() :返回以毫秒为单位的当前时间。
Ø static void exit(int status) :终止当前正在运行的 Java 虚拟机。
Ø static void gc() :运行垃圾回收器。
Ø static Properties getProperties() :确定当前的系统属性。
Ø static String getProperty(String key) :获取指定键指示的系统属性。
Ø static String getProperty(String key,String def) :获取用指定键描述的系统属性。
Ø static void setProperties(Properties props) :将系统属性设置为 Properties 参数。Østatic String setProperty(String key, Stringvalue):设置指定键指示的系统属性。
l System类是一个系统类,它描述一个系统环境,系统环境在虚拟机启动的时候,它为会加载一些系统默认的属性信息。
l 虚拟机在启动的时候都做了一些什么事情,它都加载了哪些信息呢?
虚拟机先走一遍你的系统信息(系统没有关闭的时候,一直存在的信息。)
系统虚拟机,它如果是跨平台的话,每次启动的时候都要获取一下这个平台上的特有的信息。
/*
l System:类中的方法和属性都是静态的。(包含一些有用的类字段和方法。它不能被实)例化。
l out:标准输出,默认是控制台。(Out为什么能打印数据呢,因为他对应了一个打印流:public static final PrintStream out,这个打印流中有很多方法)
l in:标准输入,默认是键盘。
l 获取系统属性信息:Properties getProperties(); (它是Hashtable的一个子类,虽然Hashtable被替代了,但是的子类还能用。它即然是HashTable的子类,那么我们就可以直接用了。因为它是Map集合中的一员,Map集合我掌握了,Map集合中的所有的子对象我是不是都能用)
*/
l import java.util.*;
class SystemDemo
{
publicstatic void main(String[] args)
{
Propertiesprop = System.getProperties();
//因为Properties是Hashtable的子类,也就是Map集合的一个子类对象。
//那么可以通过map的方法取出该集合中的元素。
//该集合中存储都是字符串。没有泛型定义。
//如何在系统中自定义一些特有信息呢?(也让他存在于系统级的属性当中)
System.setProperty("mykey","myvalue");
//获取指定属性信息。(下次启动虚拟系统的时候,这个值已经存在,我们可能在其他程序里面,虽时,可以用system类拿到这个值,参于运算)
Stringvalue = System.getProperty("os.name");
System.out.println("value="+value);
//可不可以在jvm启动时,动态加载一些属性信息呢?(java命令,可是在启支虚拟机的同时,给它加上一引起信息。如,java –Dhaha=hello)
Stringv = System.getProperty("haha");
System.out.println("v="+v); //没有这个键,返回结果为:v=null;
/*
//获取所有属性信息。
for(Objectobj : prop.keySet()) //用for来遍历整个set集合,也可以用iterator来实现。
{
Stringvalue = (String)prop.get(obj);
System.out.println(obj+"::"+value);
//publicSet<String> stringPropertyNames(),运用这个打印也可以。
}
*/
}
}
2、其他对象(Runtime)
l Runtime对象
该类并没有提供构造函数。说明不可以new对象。那么会直接想到该类中的方法都是静态的。发现该类中还有非静态方法。说明该类肯定会提供了方法获取本类对象。而且该方法是静态的,并返回值类型是本类类型。(不让建对象,那应该给我提供一个对象才对。而这个对象要通过一个方法,来获取,这个方法,一定是静态的。)
l static Runtime getRuntime(),返回与当前 Java应用程序相关的运行时对象。这个对象是不需要你建立的应用程序一执行,它本身就创建完毕了。只需要获取这个对象用就行了。
l 由这个特点可以看出该类使用了单例设计模式完成。(保证对象的唯一性)
l class RuntimeDemo
{
publicstatic void main(String[] args) throws Exception
{
Runtimer = Runtime.getRuntime();
Processp = r.exec("notepad.exe SystemDemo.java");
//我们可以打开一个文件,只要找到和文件,相关联的程序就行。如,用记事本打开SystemDemo.java
//r.exec(“c:\\winmine.exe”); //它可以打开直接放在c盘下的扫雷程序。也可以写为r.exec(“winmine.exe”);通过环境变量path来找到,并打开。反斜线是转义字符的意思,要用“\\”,把反斜线作为普通目录分割符存在。
//Thread.sleep(4000); //等4秒后再杀。否则看不到资源管理器中出现的进程,及图形化界面,还没有出现呢,就被干掉了。
//p.destroy();
}
}
l Runtime中的方法,Processexec(String command):在单独的进程中执行指定的字符串命令。它返回的是一个Process。
l java.lang中的类Process,public abstract class ProcessextendsObjectProcessBuilder.start() 和 Runtime.exec方法创建一个本机进程,并返回 Process子类的一个实例,该实例可用来控制进程并获得相关信息。它中的方法都是抽象的,它应该有子类,可以它并没有子类的描述。应用程序一被执行,就已经产生进程了。这个进程不是我们创建的,而是调用底层的资源完成的,所以没有定义子类实现方式,底层在帮它做这件事情,我们也不知道该怎么实现,因为不知道该怎么去调用本机平台上的内容。
l Process中的一个方法:abstract void destroy():杀掉子进程。(你只能杀这个程序启动的进程。如果想杀资源管理器中的进程的话,写的一具c或者c++的程序,调用Windows的API就可以了。)
3、其他对象(Date)
l 它对日期和时间进行描述。如果你把时间封装成一个对象,对于时间进行操作是不是更是容易一些。
l java.util中的类Date,表示特定的瞬间,精确到毫秒。有两个构造方法,可能通过new来创建。我想按我想要的方式输出,可以有很多方法都过时了。
l import java.util.*;
import java.text.*; //这个包比较特殊,因为日期转换出来的话,转换成了一个文本。
class DateDemo
{
publicstatic void main(String[] args)
{
Dated = new Date();
System.out.println(d);//打印的时间看不懂,希望有些格式。
//将模式封装到SimpleDateformat对象中。
SimpleDateFormatsdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
//调用format方法让模式格式化指定Date对象。(SimpleDateFormate中的构造方法可能不支持所有语言环境。要覆盖所有语言环境,要使用父类 DateFormat 类中的工厂方法。)
Stringtime = sdf.format(d);
System.out.println("time="+time);
longl = System.currentTimeMillis();
Dated1 = new Date(l);
System.out.println("d1:"+d1);
}
}
l 我想按我想要的输出格式输出,可是有很多方法都过时了。一般和类相关联的类,都会在API的 “另请参见”这里的所描述。Date的另请参见:DateFormat,Calendar, TimeZone, 序列化表格。
l DateFormat是一个abstract的类,它有一个子类叫:SimpleDateFormat。在SimpleDateFormat中有一个SimpleDateFormat(String pattern)的构造方法,可以用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
4、其他对象(Calendar)
l 如果我想单独获取年月日的内容怎么办呢?
l import java.util.*;
import java.text.*;
class CalendarDemo
{
publicstatic void main(String[] args)
{
Calendarc = Calendar.getInstance();
String[]mons = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[]weeks = {
"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",
};
intindex = c.get(Calendar.MONTH); //MONTH都为静态的所以要加Calendar.
intindex1 = c.get(Calendar.DAY_OF_WEEK);
sop(c.get(Calendar.YEAR)+"年");
//sop((c.get(Calendar.MONTH)+1)+"月"); //每次还要加1麻烦,用查表法
sop(mons[index]);
sop(c.get(Calendar.DAY_OF_MONTH)+"日");
//sop("星期"+c.get(Calendar.DAY_OF_WEEK));
sop(weeks[index1]);
/*
Dated = new Date();
SimpleDateFormatsdf = new SimpleDateFormat("yyyy");
Stringyear = sdf.format(d); //它返回的是一个字符串,强是我想加一年减一年的话,怎么办呢?用Integer.parseInt()。麻烦!但Date中的getYeat()方法已经过时,可以用Calendar.get(Calendar.YEAR);把年字段传进来我就行获取这个年了。
System.out.println(year);
*/
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
l java.util中的类Calendar中的方法int get(int field):返回给定日历字段的值。
l Calenda是抽象的类,可以用它的子类GregorianCalendar直接new一个对象。也要可以Calendar中的一个获实例的方法:staticCalendar getInstance():使用默认时区和语言环境获得一个日历。
l 计算机计算月份是按照从零开始的。0~11代表1到12月。老外,把Sunday作 为一周的第一天,因此当为星期日的时候,DAY_OF_WEEK=1。
l void set(int year, int month, int date)
设置日历字段 YEAR、MONTH和 DAY_OF_MONTH的值。
l 怎样把日期推两年,推五年?
abstract void add(int field, int amount)
根据日历的规则,为给定的日历字段添加或减去指定的时间量。
练习:
1,获取任意年的二月有多少天。
思路:根据指定年设置一个时间就是
c.set(year,2,1)//某一年的3月1日。(注意是3月)
c.add(Calenar.DAY_OF_MONTH,-1);//3月1日,往前推一天,就是2月最后一天。(可以往前推,后面跟的数可以是负数)
2,获取昨天的现在这个时刻。
c.add(Calenar.DAY_OF_MONTH,-1);
5、其他对象(Math_Random)
l java.lang中的类Math,它中定义的都是静态的,它没有共享数据。
l static double E:比任何其他值都更接近 e(即自然对数的底数)的 double 值。
l static double PI:比任何其他值都更接近 pi(即圆的周长与直径之比)的 double 值。
l 方法:
Ø abs():返回绝对于值
Ø static double ceil(double a):向上取整
Ø static double floor(double a):向下取整
Ø static long round(double a):四舍五入
Ø static double pow(double a, double b):a -底数,b -指数。返回:值 ab。
Ø static double random():返回带正号的 double值,该值大于等于 0.0且小于 1.0。返回是一个伪随机数。(它实际上是借助了一个随机数生成器,它底层且个算法,算出来的这个随机数,只要是算法算出来的,它就有可能找出规律,你只要算的多就行了,找到规律就不是随机的了)
l import java.util.*;
class MathDemo
{
publicstatic void main(String[] args)
{
/*
Randomr = new Random();
for(intx=0; x<10; x++)
{
//intd = (int)(Math.random()*10+1); //随机数1到10,强转把小数给舍掉。*6+1的话,就是筛子。与表达式new java.util.Random完全相同。(java.util中的类Random)
intd = r.nextInt(10)+1;
sop(d);
}
*/
saveTwo(12.3456,3,true);//12.34
}
publicstatic void saveTwo(double d,int scale,boolean isRound)
{
doublebase = Math.pow(10,scale);
doublenum = isRound?Math.round(d*base)/base:((int)(d*base))/base;
sop("num="+num);
/*
doubled1 = d*100;
sop("d1="+d1);
d1= d1+0.5;
doubled2 = (int)d1;
sop("d2="+d2);
doubled3 = d2/100;
sop("d3="+d3);
*/
}
publicstatic void show()
{
doubled = Math.ceil(16.34);//ceil返回大于指定数据的最小整数。
doubled1 = Math.floor(12.34);//floor返回小于指定数据的最大整数。
longl = Math.round(12.54);//四舍五入
sop("d="+d);
sop("d1="+d1);
sop("l="+l);
doubled2 = Math.pow(2,3);
sop("d2="+d2);
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
l Java.util中的类Radom中的方法int nextInt():返回一个int伪随机数。它会做一个强转的动作。
练习。给定一个小数。保留该小数的后两位。
选作。可以考虑,保留时进行四舍五入。
6、IO流(概述)
l 我们可以用java语言来处理,设备上已有的数据(硬盘上存放的文件,内存中驻留的数据),这个是我们进行计算机操作的时候一个比较常见的动作。
l IO(Input Output)流
Ø IO流用来处理设备之间的数据传输
Ø Java对数据的操作是通过流的方式
Ø Java用于操作流的对象都在IO包中
Ø 流按操作数据分为两种:字节流与字符流。
Ø 流按流向分为:输入流,输出流。
l 早期IO包中出现的都是字节流。因为数据无论是硬盘上的还是内存中的他们的体现形式都是字节。最终这个机器上的都是二进制。数据都是二进制的,因此字节流都能搞定。但是其中有一部分文本数据它是比较常见的,为了单独处理它,分离出来字符流。
l 编码表:ASCII(美国信息标准交换码)
GB2312(中文的文字及中文的标点符号,有几千个。对汉字进行了扩容,这张表称之为GBK 2万多个汉字)。中国有56个民族,把少数民族的文字给我搞进来,后来形成了18030。把所有国家的字都重新进行编排,形成了国际标准码表unicode码表。又对于这张表进行了优化,叫做UTF-8。Unicode中无论什么字符都用两个字节16位来表示。UTF-8,如果你用一个能装的话,你就用一个,一个装不下就用两个,两个装不下三个足够了。
l 当输入中文的时候,GBK的码表识别,UTF-8的码表也识别,那两者对于应的数字是一样的吗?肯定不一样。如,你好的“你”,在不同的识别中文的编码表中对应的数字是不一样的。如,我写中文往计算机上存的时候,查的是GBK的码表,我存的时候,对应的就是GBK码表是对应的二进制数据。你到了另外一台机器上,它上面是UTF-8的编码表,它不能将数据读出来,产生乱码。为了解决这些问题,java当中在流技术上基于字节流,产生了字符流。它可以在内部融合编码表,也就是你读到的字节数据,你读到的是GBK的码表呢,还是查UTF-8的码表呢,可以由你去指定。这们我们处理文字的时候就会变得很方便。一句话:字符流的这些对象里面整合了编码表。只有文字适合编码。我现在想处理图片的话,用什么流?字节流。通用的是字节流,字符流基于字节流。
l 对于数据的操作只有两种,读写。
l IO流常用基类
Ø 字节流的抽象基类:
InputStream,OutputStream。
Ø 字符流的抽象基类:
Reader, Writer。(名字更形象)
Ø 注:由这四个顶层类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
l 四个基类都是抽象的,因为里面有抽象的方法,需要被子类分别实现。
7、IO流(FileWriter)
l java.io中的类Writer:public abstract class Writer
l 构造方法Writer()是Protcted的只能被子类使用。
l Writer的直接已知子类: BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter,PipedWriter, PrintWriter, StringWriter,前缀名,就是这个对象的功能:
l java.io.OutputStreamWriter中的子类,java.io.FileWriter。没有空的构造函数,该流文件一被初始化,就必须要有被操作的文件存在。
/*
l 字符流和字节流:
Ø 字节流两个基类:
InputStream OutputStream
Ø 字符流两个基类:
Reader Writer
l public void write(int c) throws IOException
abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分。
public void flush() throws IOException
public void close() throws IOException
这几个都抛异常。在IO问题中IO异常是最常见的异常,要做一些处理动作。
l 先学习一下字符流的特点。
既然IO流是用于操作数据的,那么数据的最常见体现形式是:文件。
那么先以操作文件为主来演示。
l 需求:在硬盘上,创建一个文件并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象。FileWriter。后缀名是父类名。前缀名是该流对象的功能。
*/
import java.io.*;
class FileWriterDemo
{
publicstatic void main(String[] args) throws IOException
{
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriterfw = new FileWriter("demo.txt");
//调用父类outputStreamWriter中的write方法,将字符串写入到流中(没有写到目的地demo.txt,它写到了内存中去了,流在内存中,我创建了流对象)。
fw.write("abcde");
//流在流进内存的时候有一个缓冲,临时的存放这些数据,如果要将数据刷到目的地中,要刷新流对象中的缓冲中的数据。
//fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。将数据刷到目的地中。
//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
fw.close();
}
}
Java能在windows中写入数据,说明java在调用windows中的写动作。这些都是在使用windows的资源,你使用完后,要释放出来。有一个动作一定要做,那就是close();close()会先调用flush();
8、IO流(IO异常处理方式)
l凡是能和设备上的数据发生关系的,能去处理的都会发生IO异常,无论读还是写。
/*
IO异常的处理方式。
*/
import java.io.*;
class FileWriterDemo2
{
publicstatic void main(String[] args)
{
FileWriterfw = null; //在try代码块中的语句,代码块外边访问不到,所以要在外面建立引用,在try内进行初始化。这样fw函数作用于整个函数。
try
{
fw= new FileWriter("demo.txt");
fw.write("abcdefg");
}
catch(IOException e)
{
System.out.println("catch:"+e.toString());
}
finally
{
try
{
if(fw!=null) //这里一定要进行不等于空的判断。
fw.close(); //这条语句要单独处理(try-catch)一下。
//如果你开启了五个流对象的话,你要判断五次,关闭五次,而且要一个一个的关,不能放在一个if()判断中来关闭五个。
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
三句话每一句话都会抛出异常,这三句话是有关联的,如果你写了三个try的话,第一个try做了处理的话,程序还会往下面执行,这样就没有意义了。所以将三个try写在一个try中。
9、IO流(文件的续写)
l FileWriter一new对象,就在硬盘下建立一个新的文件,原来的文件就没有了。
l public FileWriter(String fileName,booleanappend) throws IOException
Ø fileName - 一个字符串,表示与系统有关的文件名。
Ø append - 一个 boolean值,如果为 true,则将数据写入文件末尾处,而不是写入文件开始处。
/*
演示对已有文件的数据续写。
*/
import java.io.*;
class FileWriterDemo3
{
publicstatic void main(String[] args) throws IOException
{
//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
FileWriterfw = new FileWriter("demo.txt",true);
fw.write("nihao\r\nxiexie"); //在windows中它地回车符是由两个字符来表示的:\r\n。在Linux中\n可以代表换行。只写一个\n在记事本中没有换行,但是如果在EditPlus中就会显示换行。
fw.close();
}
}
10、IO流(文本文件读取)
l java.io中的类Reader,它是一个抽象的类。直接子类: BufferedReader, CharArrayReader,FilterReader, InputStreamReader, PipedReader, StringReader
l Reader中的方法,close()是不用刷新流的。
int read():读取单个字符。返回:作为整数读取的字符,范围在 0 到 65535之间 (0x00-0xffff),如果已到达流的末尾,则返回-1
int read(char[] cbuf):将字符读入数组。返回:读取的字符数,如果已到达流的末尾,则返回 -1
l 流对象有一点好处就是几乎都是对应的。
l java.io中的类InputStreamReader
直接已知子类:
java.io中的类FileReader用来读取字符文件的便捷类。此类的构造方法假定默认字符编码(你系统中的编码)(字符流百分之百都有编码)。
构造方法FileReader(StringfileName):在给定从中读取数据的文件名的情况下创建一个新 FileReader。
/*
第一种方式:通过单字符进行读取。
*/
import java.io.*;
class FileReaderDemo
{
publicstatic void main(String[] args) throws IOException
{
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException(它是IOException的一个子类)
FileReaderfr = new FileReader("demo.txt");
//调用读取流对象的read方法。
//read():一次读一个字符。而且会自动往下读。
intch = 0;
while((ch=fr.read())!=-1)//读到未尾返回-1我们就有了循环的条件。
{
System.out.println((char)ch);//这里要进行强制转换的读出来的值为int型。
}
/*
while(true) //里面只有一个条件不用写while(true);将它优化成上面的形式。
{
intch = fr.read();
if(ch==-1)
break;
System.out.println("ch="+(char)ch);
}
*/
fr.close();
}
}
在磁盘上存数据的时候,每一个文件结束的时候都会有一个windows的结束标示。Java判断到这个标示的时候,并不是返回windows人家定义的标识,可是返回一个-1;
/*
第二种方式:通过字符数组进行读取。
*/
import java.io.*;
class FileReaderDemo2
{
publicstatic void main(String[] args) throws IOException
{
FileReaderfr = new FileReader("DateDemo.java");
//定义一个字符数组。用于存储读到字符。
//该read(char[])返回的是读到字符个数。
char[]buf = new char[1024]; //通常这里会定义1024的整数倍。
intnum = 0;
while((num=fr.read(buf))!=-1) //写成循环的形式。
{
System.out.println(newString(buf,0,num)); //将字符数组转换成字符串。打印的时候,只用打印有效位就可以了。如果数组长度,小于总字符的长度,数组存满后(先存到内存中),输出(输出到硬盘等),再从头存入数据。如果数组长度大于总字符的长度,返回一个长度,读了几位打印几位。
}
fr.close();
}
}
l 两种读取方式,哪一种更好?
Ø 第二种方式更好。第一种方式,我读一个打一下,读一个打一下。第二种方式,我读一个存一下,读一个存一下,存满一次后我全打出去。
Ø 如果数据超过1024的话,因为读多少,打多少,当再读入新的数据的时候,会换行后输出。因此可能会在不该换行的时候换行了。
11、IO流(拷贝文本文件)
//将C盘一个文本文件复制到D盘。
/*
复制的原理:
其实就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
*/
import java.io.*;
class CopyText
{
publicstatic void main(String[] args) throws IOException
{
copy_2();
}
publicstatic void copy_2()
{
FileWriterfw = null;
FileReaderfr = null;
try
{
fw= new FileWriter("SystemDemo_copy.txt");
fr= new FileReader("SystemDemo.java");
char[]buf = new char[1024];
intlen = 0;
while((len=fr.read(buf))!=-1)
{
fw.write(buf,0,len);
}
}
catch(IOException e)
{
thrownew RuntimeException("读写失败");
}
finally
{
if(fr!=null)
try
{
fr.close();
}
catch(IOException e)
{
}
if(fw!=null)
try
{
fw.close();
}
catch(IOException e)
{
}
}
}
//从C盘读一个字符,就往D盘写一个字符。
publicstatic void copy_1()throws IOException
{
//创建目的地。
FileWriterfw = new FileWriter("RuntimeDemo_copy.txt");
//与已有文件关联。
FileReaderfr = new FileReader("RuntimeDemo.java");
intch = 0;
while((ch=fr.read())!=-1) //太慢了,每读出一个字符,就写一次。
{
fw.write(ch);
}
fw.close();
fr.close();
}