黑马程序员_Java基础_IO流(四)_21_创建一个像文件date中写基本数据类型数据的流对象的语言为-程序员宅基地

技术标签: java学习  theima之旅  

                                                ------- 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培训、期待与您交流!----------  

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dapengaaa111/article/details/19022925

智能推荐

5个超厉害的资源搜索网站,每一款都可以让你的资源满满!_最全资源搜索引擎-程序员宅基地

文章浏览阅读1.6w次,点赞8次,收藏41次。生活中我们无时不刻不都要在网站搜索资源,但就是缺少一个趁手的资源搜索网站,如果有一个比较好的资源搜索网站可以帮助我们节省一大半时间!今天小编在这里为大家分享5款超厉害的资源搜索网站,每一款都可以让你的资源丰富精彩!网盘传奇一款最有效的网盘资源搜索网站你还在为找网站里面的资源而烦恼找不到什么合适的工具而烦恼吗?这款网站传奇网站汇聚了4853w个资源,并且它每一天都会持续更新资源;..._最全资源搜索引擎

Book类的设计(Java)_6-1 book类的设计java-程序员宅基地

文章浏览阅读4.5k次,点赞5次,收藏18次。阅读测试程序,设计一个Book类。函数接口定义:class Book{}该类有 四个私有属性 分别是 书籍名称、 价格、 作者、 出版年份,以及相应的set 与get方法;该类有一个含有四个参数的构造方法,这四个参数依次是 书籍名称、 价格、 作者、 出版年份 。裁判测试程序样例:import java.util.*;public class Main { public static void main(String[] args) { List <Book>_6-1 book类的设计java

基于微信小程序的校园导航小程序设计与实现_校园导航微信小程序系统的设计与实现-程序员宅基地

文章浏览阅读613次,点赞28次,收藏27次。相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低学校的运营人员成本,实现了校园导航的标准化、制度化、程序化的管理,有效地防止了校园导航的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询和修正建筑速看等信息。课题主要采用微信小程序、SpringBoot架构技术,前端以小程序页面呈现给学生,结合后台java语言使页面更加完善,后台使用MySQL数据库进行数据存储。微信小程序主要包括学生信息、校园简介、建筑速看、系统信息等功能,从而实现智能化的管理方式,提高工作效率。

有状态和无状态登录

传统上用户登陆状态会以 Session 的形式保存在服务器上,而 Session ID 则保存在前端的 Cookie 中;而使用 JWT 以后,用户的认证信息将会以 Token 的形式保存在前端,服务器不需要保存任何的用户状态,这也就是为什么 JWT 被称为无状态登陆的原因,无状态登陆最大的优势就是完美支持分布式部署,可以使用一个 Token 发送给不同的服务器,而所有的服务器都会返回同样的结果。有状态和无状态最大的区别就是服务端会不会保存客户端的信息。

九大角度全方位对比Android、iOS开发_ios 开发角度-程序员宅基地

文章浏览阅读784次。发表于10小时前| 2674次阅读| 来源TechCrunch| 19 条评论| 作者Jon EvansiOSAndroid应用开发产品编程语言JavaObjective-C摘要:即便Android市场份额已经超过80%,对于开发者来说,使用哪一个平台做开发仍然很难选择。本文从开发环境、配置、UX设计、语言、API、网络、分享、碎片化、发布等九个方面把Android和iOS_ios 开发角度

搜索引擎的发展历史

搜索引擎的发展历史可以追溯到20世纪90年代初,随着互联网的快速发展和信息量的急剧增加,人们开始感受到了获取和管理信息的挑战。这些阶段展示了搜索引擎在技术和商业模式上的不断演进,以满足用户对信息获取的不断增长的需求。

随便推点

控制对象的特性_控制对象特性-程序员宅基地

文章浏览阅读990次。对象特性是指控制对象的输出参数和输入参数之间的相互作用规律。放大系数K描述控制对象特性的静态特性参数。它的意义是:输出量的变化量和输入量的变化量之比。时间常数T当输入量发生变化后,所引起输出量变化的快慢。(动态参数) ..._控制对象特性

FRP搭建内网穿透(亲测有效)_locyanfrp-程序员宅基地

文章浏览阅读5.7w次,点赞50次,收藏276次。FRP搭建内网穿透1.概述:frp可以通过有公网IP的的服务器将内网的主机暴露给互联网,从而实现通过外网能直接访问到内网主机;frp有服务端和客户端,服务端需要装在有公网ip的服务器上,客户端装在内网主机上。2.简单的图解:3.准备工作:1.一个域名(www.test.xyz)2.一台有公网IP的服务器(阿里云、腾讯云等都行)3.一台内网主机4.下载frp,选择适合的版本下载解压如下:我这里服务器端和客户端都放在了/usr/local/frp/目录下4.执行命令# 服务器端给执_locyanfrp

UVA 12534 - Binary Matrix 2 (网络流‘最小费用最大流’ZKW)_uva12534-程序员宅基地

文章浏览阅读687次。题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93745#problem/A题意:给出r*c的01矩阵,可以翻转格子使得0表成1,1变成0,求出最小的步数使得每一行中1的个数相等,每一列中1的个数相等。思路:网络流。容量可以保证每一行和每一列的1的个数相等,费用可以算出最小步数。行向列建边,如果该格子是_uva12534

免费SSL证书_csdn alphassl免费申请-程序员宅基地

文章浏览阅读504次。1、Let's Encrypt 90天,支持泛域名2、Buypass:https://www.buypass.com/ssl/resources/go-ssl-technical-specification6个月,单域名3、AlwaysOnSLL:https://alwaysonssl.com/ 1年,单域名 可参考蜗牛(wn789)4、TrustAsia5、Alpha..._csdn alphassl免费申请

测试算法的性能(以选择排序为例)_算法性能测试-程序员宅基地

文章浏览阅读1.6k次。测试算法的性能 很多时候我们需要对算法的性能进行测试,最简单的方式是看算法在特定的数据集上的执行时间,简单的测试算法性能的函数实现见testSort()。【思想】:用clock_t计算某排序算法所需的时间,(endTime - startTime)/ CLOCKS_PER_SEC来表示执行了多少秒。【关于宏CLOCKS_PER_SEC】:以下摘自百度百科,“CLOCKS_PE_算法性能测试

Lane Detection_lanedetectionlite-程序员宅基地

文章浏览阅读1.2k次。fromhttps://towardsdatascience.com/finding-lane-lines-simple-pipeline-for-lane-detection-d02b62e7572bIdentifying lanes of the road is very common task that human driver performs. This is important ..._lanedetectionlite

推荐文章

热门文章

相关标签