黑马程序员_day21 (对象的序列化,管道流,转换流的字符数码,字符数码联通)。

本文深入介绍了Java中的IO流概念及其实现方式,包括对象序列化、管道流、RandomAccessFile等高级特性。此外,还详细解释了不同类型的流,如DataInputStream与DataOutputStream的操作方法,以及如何处理字符编码问题。

---------------------- android培训、java培训 期待与您交流! ----------------------

一:对象的序列化。


import java.io.*;

class ObjectStreamDemo
{
 public static void main(String[] args) throws Exception
 {
  //writeObj();
  readObj();
 }
 public static void readObj()throws Exception
 {
  ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));

  Person p = (Person)ois.readObject();

  System.out.println(p);
  ois.close();
 }

 public static void writeObj()throws IOException
 {
  ObjectOutputStream oos =
   new ObjectOutputStream(new FileOutputStream("obj.txt"));

  oos.writeObject(new Person("lisi0",399,"kr"));

  oos.close();
 }
}


import java.io.*;
class Person implements Serializable
{
 
 public static final long serialVersionUID = 42L;

 private String name;
 transient int age;
 static String country = "cn";
 Person(String name,int age,String country)
 {
  this.name = name;
  this.age = age;
  this.country = country;
 }
 public String toString()
 {
  return name+":"+age+":"+country;
 }
}


二:管道流。


import java.io.*;

class Read implements Runnable
{
 private PipedInputStream in;
 Read(PipedInputStream in)
 {
  this.in = in;
 }
 public void run()
 {
  try
  {
   byte[] buf = new byte[1024];

   System.out.println("读取前。。没有数据阻塞");
   int len = in.read(buf);
   System.out.println("读到数据。。阻塞结束");

 

   String s= new String(buf,0,len);

   System.out.println(s);

   in.close();

  }
  catch (IOException e)
  {
   throw new RuntimeException("管道读取流失败");
  }
 }
}

class Write implements Runnable
{
 private PipedOutputStream out;
 Write(PipedOutputStream out)
 {
  this.out = out;
 }
 public void run()
 {
  try
  {
   System.out.println("开始写入数据,等待6秒后。");
   Thread.sleep(6000);
   out.write("piped lai la".getBytes());
   out.close();
  }
  catch (Exception e)
  {
   throw new RuntimeException("管道输出流失败");
  }
 }
}

class  PipedStreamDemo
{
 public static void main(String[] args) throws IOException
 {

  PipedInputStream in = new PipedInputStream();
  PipedOutputStream out = new PipedOutputStream();
  in.connect(out);

  Read r = new Read(in);
  Write w = new Write(out);
  new Thread(r).start();
  new Thread(w).start();


 }
}


三:RandomAccessFile。


import java.io.*;


/*
RandomAccessFile

该类不是算是IO体系中子类。
而是直接继承自Object。

但是它是IO包中成员。因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,
同时可以通过seek改变指针的位置。


其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,,读写rw等。

如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式为rw。操作的文件不存在,会自动创建。如果存则在不会覆盖。

*/
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);

  //跳过指定的字节数
  raf.skipBytes(8);

  byte[] buf = new byte[4];

  raf.read(buf);

  String name = new String(buf);

  int age = raf.readInt();


  System.out.println("name="+name);
  System.out.println("age="+age);

  raf.close();


 }

 public static void writeFile_2()throws IOException
 {
  RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
  raf.seek(8*0);
  raf.write("周期".getBytes());
  raf.writeInt(103);

  raf.close();
 }

 public static void writeFile()throws IOException
 {
  RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");

  raf.write("李四".getBytes());
  raf.writeInt(97);
  raf.write("王五".getBytes());
  raf.writeInt(99);

  raf.close();
 }
}

 


四:IO包中的其他类。

1,操作基本数据类型。
 a,DataInputStream与DataOutputStream。

2,操作字节数组。
 a,ByteArrayInputStream与ByteArrayOutputStream。

3,操作字符数组。
 a,CharArrayReader与CharArrayWrite。

4,操作字符串。
 a,StringReader与StringWriter。

/*
DataInputStream与DataOutputStream

可以用于操作基本数据类型的数据的流对象。

*/
import java.io.*;
class DataStreamDemo
{
 public static void main(String[] args) throws IOException
 {
  //writeData();
  //readData();

  //writeUTFDemo();

//  OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
//
//  osw.write("你好");
//  osw.close();

//  readUTFDemo();

 }
 public static void readUTFDemo()throws IOException
 {
  DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));

  String s = dis.readUTF();

  System.out.println(s);
  dis.close();
 }

 

 public static void writeUTFDemo()throws IOException
 {
  DataOutputStream dos = 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();
  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();

  ObjectOutputStream oos = null;
  oos.writeObject(new O());

  
 }
}

 

五:ByteArrayStream。

/*
用于操作字节数组的流对象。

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();

  int by = 0;

  while((by=bis.read())!=-1)
  {
   bos.write(by);
  }

 

  System.out.println(bos.size());
  System.out.println(bos.toString());

 // bos.writeTo(new FileOutputStream("a.txt"));

 }
}

 

六:字符编码。

 1,字符流的出现为了方便操作字符。

 2,更重要的是加入了编码转换。

 3,通过子类转换流来完成。
  a,InputStreamReader。
  b,OutputStreamWriter。

 4,在两个对象进行构造的时候可以加入字符集。

 5,编码表的由来。
  a,计算机只能识别二进制数据,早期由来是电信号。
  b,为了方便应用计算机,让它可以识别各个国家的文字。
  c,就将各个国家的文字用数字来表示,并一一对应,形成一张表。
  d,这就是编码表。

 6,常见的编码表。
  a,ASCII:美国标准信息交换码。(用一个字节的7位可以表示)

  b,ISO8859-1:拉丁码表,欧洲码表。(用一个字节的8位表示)

  c,GB2312:中国的中文编码表。

  d,GBK:中国的中文编码表升级,融合了更多的中文文字符号。

  e,Unicode:国际标准码,融合了多种文字。(所有文字都用两个字节来表示,Java语言使用的就是Unicode)

  f,UTF-8:做多用三个字节来表示一个字符。
  
  g,......

⑴:转换流的字符编码。
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(new FileInputStream("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();
 }
 public static void writeText()throws IOException
 {
  OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");

  osw.write("你好");

  osw.close();
 }

}


⑵:字符编码。

 

/*
编码:字符串变成字节数组。


解码:字节数组变成字符串。

String-->byte[];  str.getBytes(charsetName);


byte[] -->String: new String(byte[],charsetName);

*/
import java.util.*;
class  EncodeDemo
{
 public static void main(String[] args)throws Exception
 {
  String s = "哈哈";

  byte[] b1 = s.getBytes("GBK");

  System.out.println(Arrays.toString(b1));
  String s1 = new String(b1,"utf-8");
  System.out.println("s1="+s1);

  //对s1进行iso8859-1编码。
  byte[] b2 = s1.getBytes("utf-8");
  System.out.println(Arrays.toString(b2));

  String s2 = new String(b2,"gbk");

  System.out.println("s2="+s2);

  

 }
}

 

⑶:字符编码-联通。


class EncodeDemo2
{
 public static void main(String[] args) throws Exception
 {
  String s = "��ͨ";

  byte[] by = s.getBytes("gbk");

  for(byte b : by)
  {
   System.out.println(Integer.toBinaryString(b&255));
  }


  System.out.println("Hello World!");
 }
}


七:练习。


/*
有五个学生,每个学生有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(String name,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)
 {
  int num = new Integer(this.sum).compareTo(new Integer(s.sum));
  if(num==0)
   return this.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(!(obj instanceof Student))
   throw new ClassCastException("类型不匹配");
  Student s = (Student)obj;

  return this.name.equals(s.name) && this.sum==s.sum;
 }

 public String toString()
 {
  return "student["+name+", "+ma+", "+cn+", "+en+"]";
 }
}

class StudentInfoTool
{
 public static Set<Student> getStudents()throws IOException
 {
  return getStudents(null);
 }

 public static Set<Student> getStudents(Comparator<Student> cmp)throws IOException
 {
  BufferedReader bufr =
   new BufferedReader(new InputStreamReader(System.in));

  String line = 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
 {
  BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt"));

  for(Student stu : stus)
  {
   bufw.write(stu.toString()+"\t");
   bufw.write(stu.getSum()+"");
   bufw.newLine();
   bufw.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);
 }
}

---------------------- android培训、java培训 期待与您交流! ----------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值