------- android培训、java培训、期待与您交流!----------
导读:对象的序列化,管道流,RandomAccessFile,操作基本数据类型的流对象, ByteArrayStream,字符流的字符编码,编码解码,字符编码-联通,练习
1、IO流(对象的序列化)
- IO包中的其他类:操作对象,ObjectInputStream与ObjectOutputStream,它们是能对“对象”进行操作的字节流。流是用来操作数据的,可是数据被封装到了堆内存中了。因为对象都存储在堆内存中,当程序运行完后,在堆内存中的垃圾就会被垃圾回收机制给回收了。运用些流,可以将堆内存中的对象存放到硬盘上,这些数据也会随着对象存储到了硬盘上(对象的持久化存储,或者叫对象的序列化)。如果想拿数据来用的话,只用把文件中的对象读一次就可以了。
- 被操作的对象需要实现Serializable (标记接口); public interfaceSerializable类通过实现 java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。(在这个接口中没有方法,没有方法的接口称之为标记接口)
- 对象想要序列化,类必须实现这个Serializable接口,这叫做标记,你具备这个资格才让你序列化。原理是,给类加一个UID标识,这个UID是给编译器使用的。如果类改变的话,会生成一个新的ID号(根据类中不同的成员算这个ID)。生成的文件是对象中的数据,用记事本打开,记事本要查GBK的表,生成的文件没有希望你能看得懂。
- 构造方法:
Ø ObjectOutputStream(OutputStream out):创建写入指定 OutputStream 的ObjectOutputStream。(接收一个流进来)
- ObjectOutputStream,java.io中的类publicclass ObjectOutputStreamextends OutputStream,ObjectOutputStream将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用ObjectInputStream 读取(重构)对象。它继承自OutputStream,它中有OutputStream中的相关的方法。
- 方法:
Ø write();
Ø writeInt(int val)等:可以操作基本数据类型。writeInt(int val),可以将四个字节全部写出去。区别于write(int val)方法。
Ø write():只将最低的8位写出去。
Ø void writeObject(Object obj):将指定的对象写入 ObjectOutputStream。(方法可以接收一个对象进来)
- 我对某些已经定义好的对象中的数值进行了持久化的存储,你不需要再住里面传值了,你也不知道要往里面传什么。把对象读出来,拿出来用就可以了(不需要new,不需要数值的传递了)。
- import java.io.*;
class ObjectStreamDemo
{
publicstatic void main(String[] args) throws Exception
{
//writeObj();
readObj();
}
public static void readObj()throws Exception
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
Personp = (Person)ois.readObject();
System.out.println(p);
ois.close();
}
public static void writeObj()throws IOException
{
ObjectOutputStream oos =
newObjectOutputStream(new FileOutputStream("obj.txt"));
//一般不存成obj.txt,因为txt可以打开,可是打开也看不懂,可以存成person.object
oos.writeObject(newPerson("lisi0",399,"kr")); //这里的kr是不能够被序列化到硬盘上,因为kr传进去之后是静态的,不是在堆内存中的,不被序列化。这里可以写多个oos.writeObject(new Person("",""));存入多个对象,readObject()一次返回一个对象,readObject()第二次,返回第二个对象。
oos.close();
}
}
import java.io.*;
class Person implements Serializable
{
//UID给类定义一个序列化的标识,其实就是了为序列化的方便。在生成obj.txt后,在name前加上一个private的时候就会生成一个新的UID。这个时候就不能和原来的obj.txt文件了,不让你读了。为了还可以读原来的文件,可以在类中自己定义一个UID不让java自动生成。
publicstatic final long serialVersionUID = 42L;//自己定义一相UID新的类,还可以用原来的,序列化的对象。
privateString name;
transientint age; //如果非静态的成员也不想让它序列化的话,可以加上transient,其值在堆内存中存在,而不在文本文件中存在。
staticString country = "cn";
Person(Stringname,int age,String country)
{
this.name= name;
this.age= age;
this.country= country;
}
public String toString()
{
return name+":"+age+":"+country;
}
}
- ObjectOutputStream和ObjectInputStream必须成对的出现。
2、IO流(管道流)
- IO包中的其他类:
管道流(PipedInputStream和PipedOutputStream),输入输出可以直接进行连接,通过结合线程使用。
- 读写流,中间有一个中转站(数组)。而管道流,他们可以接上。从这个管子里面写,从那个管子中就可以读到,这两根管子可以拧到一块去。
- public class PipedInputStreamextendsInputStream管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。(涉及了多线程技术的IO流对象。)
- 集合当中涉及到IO流的是Properties,在IO流中涉及到多线程的是管道流。
- PipedInputStream(PipedOutputStream src):创建 PipedInputStream,使其连接到管道输出流src。
- PipedInputStream():创建尚未连接的 PipedInputStream。
- 要么非空的构造函数传入输入管道流,要么空的构造函数用方法,void connect(PipedOutputStream src):使此管道输入流连接到管道输出流 src。
- import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStreamin)
{
this.in= in;
}
publicvoid run()
{
try
{
byte[] buf = new byte[1024];
System.out.println("读取前。。没有数据阻塞");
intlen = in.read(buf);
System.out.println("读到数据。。阻塞结束");
Strings= new String(buf,0,len);
System.out.println(s);
in.close();
}
catch(IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
{
privatePipedOutputStream out;
Write(PipedOutputStreamout)
{
this.out= out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待6秒后。");
Thread.sleep(6000);
out.write("pipedlai la".getBytes());
out.close();
}
catch(Exception e)
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
publicstatic void main(String[] args) throws IOException
{
PipedInputStreamin = new PipedInputStream();
PipedOutputStreamout = new PipedOutputStream();
in.connect(out);
Readr = new Read(in);
Writew = new Write(out);
newThread(r).start();
newThread(w).start();
}
}
- 两个线程,谁先抢到资源,不重要。因为有一个阻塞式的方法read(),我没有写你就得等,等我写完了你再执行。
3、IO流(RandomAccessFile)
- RandomAccessFile,随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问。(它的结尾处没有父类名,是自动一派的工具类,直接继承自Object,publicclass RandomAccessFileextends Object)此类的实例支持对随机访问文件的读取和写入(即能读又能写)。
- 可以实现文件的分段写入。将数据分成段之后,可以让一个线程负责一段(下载软件的原理)。一般的流是从前往后写,它们写出来的文件就不是连续的文件了。
- RandomAccessFile该类不是算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
- 其实完成读写的原理就是内部封装了字节输入流和输出流。
- 构造函数:
Ø RandomAccessFile(File file, String mode)
Ø RandomAccessFile(String name, String mode)
mode 参数指定用以打开文件的访问模式
- 局限性:
通过构造函数可以看出,该类只能操作文件。(设备上只有硬盘,没有别的)。而且操作文件还有模式:只读r,读写rw等。
如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
- 方法:
Ø int read(byte[] b)
Ø int readInt():读基本数据类型等。
Ø String readLine():读一行。
Ø void seek(long pos):指向位置。
Ø void write(byte[] b)
Ø void writeInt(int v)
Ø int skipBytes(int n):跳过多少个字节。
- import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile_2();
//readFile();
//System.out.println(Integer.toBinaryString(258));
}
public static void readFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中指针。(前提:要保证数据是有规律的,不然取起来就费劲了,为使数据有规律,可以在存的时候补位)
//raf.seek(8*1); //取第二个人。取第一个人是8*0。seek()是前后都能指,想指哪指哪。
//跳过指定的字节数
raf.skipBytes(8); //跳过可以往下跳,但是不能往回跳。
byte[]buf = new byte[4];
raf.read(buf);
Stringname = new String(buf);
intage = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile_2()throws IOException
{
RandomAccessFileraf = new RandomAccessFile("ran.txt","rw");
//一new对象的话,不另创建文件,而是直接在里面写数据。而输出流一new对象就要覆盖文件。
raf.seek(8*3); //如果这里是8*0的话,对于李四这个位置上的数据修改为周七。
raf.write("周七".getBytes());
//随机的可以往里面读写。第一个位置是,李四。第二个位置是王五。第三个位置不知道是什么,直接在第四个位置里写入周七。
raf.writeInt(103);
raf.close();
}
publicstatic void writeFile()throws IOException
{
RandomAccessFileraf = new RandomAccessFile("ran.txt","rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99); //直接写基本数据类型。
raf.close();
}
}
4、IO流(操作基本数据类型的流对象)
- DataInputStream与DataOutputStream可以用于操作基本数据类型的数据的流对象。(如果只是为了操作基本数据类型的话,用这个是非常方便的。)
- 构造方法:
DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。
- void writeUTF(String str):以与机器无关方式使用 UTF-8 修改版(null 字节 '\u0000' 是用 2-byte 格式而不是 1-byte 格式编码的)编码将一个字符串写入基础输出流。(用这种方式写入的字符串,只能用它对应的方式写出来,用转换流读不出来)
- import java.io.*;
class DataStreamDemo
{
public static void main(String[] args) throws IOException
{
//writeData();
//readData();
//writeUTFDemo();
// OutputStreamWriterosw = new OutputStreamWriter(newFileOutputStream("gbk.txt"),"gbk");
// osw.write("你好"); //这里占了4个字节,UTF-8写入占6个字节,修改版的UTF-8占了8个字节。只能用相对应的方法读出来,而不能用UTF-8读出来
// osw.close();
// readUTFDemo();
}
public static void readUTFDemo()throws IOException
{
DataInputStreamdis = new DataInputStream(new FileInputStream("utf.txt"));
Strings = dis.readUTF(); //只能用这个读出来。
System.out.println(s);
dis.close();
}
public static void writeUTFDemo()throws IOException
{
DataOutputStreamdos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
dos.writeUTF("你好");
dos.close();
}
public static void readData()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt(); //写的时候是先写的整数,读的时候也要先读整数。要是以前的话,要先存入4个字节,再将4个字节转化为字符串,再将字符串强转成一个整数。
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
dis.close();
}
public static void writeData()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);
dos.close();
ObjectOutputStreamoos = null;
oos.writeObject(newO());
}
}
5、IO流(ByteArrayStream)
- 操作字节数组
ByteArrayInputStream与ByteArrayOutputStream,是能直接操作字节数组中字节数据的流对象。
- public class ByteArrayInputStream extends InputStream,ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。关闭ByteArrayInputStream 无效(没有和文件打交道,就没有调用底层资源,关闭是没有什么效果的,关不关都一样)。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
- ByteArrayInputStream(byte[] buf)
- 方法摘要
Ø int available():返回可从此输入流读取(或跳过)的剩余字节数。
Ø int read():从此输入流中读取下一个数据字节。
Ø void reset():将缓冲区的位置重置为标记位置。
Ø long skip(long n):从此输入流中跳过 n 个输入字节。
- public class ByteArrayOutputStreamextendsOutputStream此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。 关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
- ByteArrayOutputStream():创建一个新的 byte 数组输出流。
ByteArrayOutputStream(int size):size用于指定大小的缓冲区容量。
对象中封装的就是一个可变长度以字节数组,这个数组就是目的。
- int size():返回缓冲区的当前大小。
byte[] toByteArray():创建一个新分配的 byte 数组。
String toString()
void writeTo(OutputStream out):写到目的中去,这个目的可以是一个字节输出流。
- 用于操作字节数组的流对象。
Ø ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。
Ø ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源。所以,不用进行close关闭。
- 在流操作规律讲解时:
源设备,
键盘 System.in,硬盘FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。
- 对于数组进行封装,不仅是为了代码的封装性、代码的复用性,更重要的是:用流的读写思想来操作数组。对数组的操作无非有两个,一个是读,一个是写。
- import java.io.*;
class ByteArrayStream
{
public static void main(String[] args)
{
//数据源。
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());
//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
intby = 0;
while((by=bis.read())!=-1) //不用判断数组大小,更方便了。读操作
{
bos.write(by); //写操作
}
System.out.println(bos.size()); //缓冲区的大小
System.out.println(bos.toString());
// bos.writeTo(newFileOutputStream("a.txt")); //只有这一个方法涉及到异常了。
}
}
- 下面两个和上面的ByteArrayInputStream和ByteArrayOutputStream都是以内存为源和目的的操作:
Ø 操作字符数组:CharArrayReader与CharArrayWrite
Ø 操作字符串:StringReader 与StringWriter
6、IO流(字符流的字符编码)
- 字符编码
Ø 字符流的出现为了方便操作字符。
Ø 更重要是的加入了编码转换。
Ø 通过子类转换流来完成。(下面两个是加入了编码表的流对象,还有两个是PrintStream和PrintWriter,这两个只能去打印不能去读取)
Ø InputStreamReader
Ø OutputStreamWriter
Ø 在两个对象进行构造的时候可以加入字符集。
- 编码表的由来
Ø 计算机只能识别二进制数据,早期由来是电信号。
Ø 为了方便应用计算机,让它可以识别各个国家的文字。
Ø 就将各个国家的文字用数字来表示,并一一对应,形成一张表。
Ø 这就是编码表。
- 常见的编码表
Ø ASCII:美国标准信息交换码。(用一个字节的7位可以表示)
Ø ISO8859-1:拉丁码表。欧洲码表(用一个字节的8位表示)
Ø GB2312:中国的中文编码表。(中国的码表兼容ASCII码表,两个字节的高位都用1来表示,带符号六七千个字)
Ø GBK:中国的中文编码表升级,融合了更多的中文文字符号。(扩容了,两万多,56个民族的文字都加进来就好了。GB18030)
Ø Unicode:国际标准码,融合了多种文字。(所有文字都用两个字节来表示,Java语言(char类型)使用的就是unicode。但一个字节能装下的文字,两个字节比较浪费,)
Ø UTF-8:最多用三个字节来表示一个字符。(一个能装下的用一个字节装,二个字节不够的用三个字节装。在每一个字节的开头都有一个标识头,加了之后,就能很容易的区别出什么样的编码才是UTF-8的编码)
- 可是GBK能够识别中文,UTF-8也能识别中文,但是同样的码却对应了不同的文字,这就涉及到了编码的转换问题。有些人用的是UTF-8的编码,有些人用的是GBK的编码,两个码表都能识别中文,可以却出现了乱码,这是因为解析出现了问题。
- 如果下次再出现乱码,你把你好仍进去,如果出现两个??,说明是用GBK编的码,用UTF-8解的码。如果你好仍进去,出现了浣犲,则是用UTF-8编的码,用GBK解的。
- import java.io.*;
class EncodeStream
{
public static void main(String[] args) throws IOException
{
//writeText();
readText();
}
public static void readText()throws IOException
{
InputStreamReader isr = new InputStreamReader(newFileInputStream("utf.txt"),"gbk");
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
isr.close();
}
publicstatic void writeText()throws IOException
{
OutputStreamWriterosw = new OutputStreamWriter(newFileOutputStream("utf.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
}
7、编码解码
- 编码解码就是对于数据进行转换。把看懂得,变成看不懂的,把看懂的变成看不懂的。
- 编码:字符串变成字节数组。
解码:字节数组变成字符串。
- String-->byte[]; str.getBytes(charsetName);
byte[] -->String: newString(byte[],charsetName);
- import java.util.*;
class EncodeDemo
{
public static void main(String[] args)throws Exception
{
Strings = "哈哈";
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
Strings1 = new String(b1,"utf-8");
System.out.println("s1="+s1);
//若对s1进行iso8859-1解码再编码,就能正确的读出来输出正确结果,因为iso8859-1不识别中文。
byte[] b2 = s1.getBytes("utf-8"); //如果这里用utf-8,因为UTF-8和GBK都识别中文,在这里编译将???编码的时候会编码错误,解码的时候也更不会正确。
System.out.println(Arrays.toString(b2));
String s2 = new String(b2,"gbk");
System.out.println("s2="+s2);
}
}
- 为什么要这样去写呢?tomcat用的默认编码是ISO8859-1。玩服务器的时候真的会出现乱码的(????)。这个时候就要将?在服务器端编译一次再解一次。如果get的话,就必须要这么做,如果是post提交的话,你可以通过服务器中一个对象的函数叫做:setCharacterEncoding()设置字符编码,它自动帮你转换。
- 在这个程序中如果s为“你好”,输出s2=锟斤拷锟?,如果s为“哈哈”,输出s2=锟斤拷锟斤拷,s1和s2很像。这是因为在UTF-8中它也支持连续三个负数的文字,先拿了两个或者三个去查,查了之后,没有查着符合UTF-8规则的数据,它把字符编码表中除了对应数据区以外的部分叫做未知字符区域,它到这里面去查去了。查了之后,就查了一堆相似的字符返回来了。
08、字符编码-联通
- UTF-8中可以读两个字符,也可能读三个字符,UTF-8的码表,它都对于字节都加了一个标识头信息,它根据自己的标识头就能知道,我一次是读一个字节呢,还是一次读两个字节呢,还是一次读三个字节呢。一个字节开始位是0。两个字节的话,第一个字节,开始位是110,第二个字节开始位是10。三个字节表示的话,第一个字节开始位是1110,第二个字节开始位是10,第三个字节开始位是10。用这来判断往后面读到底是读一个还是读两个还是读三个。
- class EncodeDemo2
{
public static void main(String[] args) throws Exception
{
Strings = "联通";
byte[] by = s.getBytes("gbk");
for(byteb : by)
{
System.out.println(Integer.toBinaryString(b&255));
}
System.out.println("HelloWorld!");
}
}
- 联通这两个字的二进制形式为:
11000001
10101010
11001101
10101000
正好符合UTF-8的形式,所以用记事本打开的时候,记事本查的是UTF-8的编码而不是GBK的编码。所以出现了乱码。可在在记事本的前面加上一个汉字,这样就用GBK来解,不用UTF-8来解就正确了。
9、练习
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhagnsan,30,40,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中。
1,描述学生对象。
2,定义一个可操作学生对象的工具类。
思想:
1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2,因为学生有很多,那么就需要存储,使用到集合。因为要对学生的总分排序。
所以可以使用TreeSet。
3,将集合的信息写入到一个文件中。
*/
import java.io.*;
import java.util.*;
class Student implements Comparable<Student>
{
private String name;
private int ma,cn,en;
private int sum;
Student(Stringname,int ma,int cn,int en)
{
this.name= name;
this.ma= ma;
this.cn= cn;
this.en= en;
sum= ma + cn + en;
}
public int compareTo(Student s)
{
intnum = new Integer(this.sum).compareTo(new Integer(s.sum));
if(num==0)
returnthis.name.compareTo(s.name);
return num;
}
public String getName()
{
return name;
}
public int getSum()
{
return sum;
}
public int hashCode()
{
return name.hashCode()+sum*78;
}
public boolean equals(Object obj)
{
if(!(objinstanceof Student))
thrownew ClassCastException("类型不匹配");
Students = (Student)obj;
return this.name.equals(s.name) && this.sum==s.sum;
}
publicString toString()
{
return "student["+name+", "+ma+", "+cn+","+en+"]";
}
}
class Student InfoTool
{
//对外提供两个方法,一个是没有比较器的,另一个是有比较器的。没有比较器的和有比较器的代码大致相同。只用传入null即可,在有比较器中做一下判断。
public static Set<Student> getStudents() throws IOException
{
return getStudents(null);
}
public static Set<Student> getStudents(Comparator<Student> cmp)throws IOException
{
BufferedReaderbu fr =
newBufferedReader(new InputStreamReader(System.in));
Stringline = null;
Set<Student>stus = null;
if(cmp==null) //做一下判断。
stus= new TreeSet<Student>();
else
stus= new TreeSet<Student>(cmp);
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
String[]info = line.split(",");
Student stu = new Student(info[0],Integer.parseInt(info[1]),
Integer.parseInt(info[2]),
Integer.parseInt(info[3]));
stus.add(stu); //二叉树在这里已经排了。
}
bufr.close();
return stus;
}
public static void write2File(Set<Student> stus) throws IOException
{
BufferedWriterbu fw = new BufferedWriter(new FileWriter("stuinfo.txt"));
for(Studentstu : stus)
{
bufw.write(stu.toString()+"\t");
bufw.write(stu.getSum()+"");
bufw.newLine();
bufw.flush(); //带缓冲区,一定要flush()
}
bufw.close();
}
}
class StudentInfoTest
{
public static void main(String[] args) throws IOException
{
Comparator<Student> cmp = Collections.reverseOrder();
//定义一个自己的比较器,将成绩反转,按从大到小排列,否则默认的是从小到大。
Set<Student> stus = StudentInfoTool.getStudents(cmp);
StudentInfoTool.write2File(stus);
}
}
/*
猜数字游戏:
1,产生随机数。
2,获取键盘录入。
3,将录入数据变成数字,和随机数比较。
给出提示信息。
4,重复这个过程,如果猜中,程序就结束。
注意:对于输入1~100以外的数字,,以及非数字要给出提示。
*/
import java.io.*;
import java.util.*;
class GuessNumber
{
private int ranNum;
GuessNumber()
{
Randomr = new Random();
ranNum= r.nextInt(100)+1;//(int)Math.random()*100+1;
}
public void play()
{
System.out.println("游戏开始:输入1~100之间的数字:");
boolean b = false;
while(!b)
{
try
{
int num = getNum();
if(num>=1&& num<=100)
b= isLuck(num);
else
System.out.println("数值超出范围");
}
catch(IOException e)
{
throw new RuntimeException("录入数据失败");
}
catch(NumberFormatExceptione)
{
System.out.println("输入了非法数据");
}
}
}
//获取键盘的数字
privateint getNum()throws IOException,NumberFormatException
{
BufferedReaderbu fr = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(bufr.readLine());
return num;
}
//和随机数比较
private boolean isLuck(int num)
{
booleanb = false;
if(num>ranNum)
System.out.println("大了,继续");
elseif(num<ranNum)
System.out.println("小了,继续");
else
{
System.out.println("中了,恭喜");
b= true;
}
returnb;
}
}
class GuessNumberDemo
{
public static void main(String[] args)
{
new GuessNumber().play();
}
}
------- android培训、java培训、期待与您交流!----------