黑马程序员--Java基础之IO包中的其他一些类

JAVA学习第22天

 

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

ByteArrayInputStream :(读取)在构造的时候,需要接收数据源,而且数据源是一个字节数组

ByteArrayOutputStream:(写入)在构造的时候,不用定义数据目的,因为该对象中已经
内部封装了可变长度的字节数组

因为这两个流对象都操作的字节数组,并没有使用系统资源,
所以,不用进行close()关闭

在流操作规律讲解时:

源设备;
 键盘 System.in 键盘 FileStream 内存 ArrayStream
目的设备:
 控制台 System.out  硬盘 FileStream  内存 ArrayStream

*/

import java.io.*;
class  ByteArrayStreamDemo
{
 public static void main(String[] args)
 {
  ByteArrayInputStream bis = new ByteArrayInputStream("ALJGLA".getBytes()); //读取数据
  
  ByteArrayOutputStream bos = new ByteArrayOutputStream(); //写入数据

  int ch =0;
  while ((ch = bis.read()) != -1)
  {
   bos.write(ch);
  }
  System.out.println(bos.size());
  System.out.println(bos.toString());
 }
}

 

/*
管道流:PipedInputStream 管道输入流(读取) 和 PipedOutputStream 管道输出流(写入)
管道需要连接才能使数据流通, 对于数据谁先读取还是写入,这涉及到多线程问题
*/
import java.io.*;

//管道读取线程
class Read implements Runnable
{
 private PipedInputStream in;
 Read(PipedInputStream in)
 {
  this.in = in;
 }
 public void run()
 {
  try
  {
   System.out.println("管道读取流开始。。。");
   byte[] buf = new byte[1024]; //定义字节数组,当读取管道中的数据时,临时存放的容器
   int len = 0;
   //in.read(buf) 返回的是一共向buf数组中存入了多少数据
   len = in.read(buf);                // in.read(buf)将管道中的数据读取存入到buf数组中
   
   System.out.println(new String(buf,0,len)); //new String(buf,0,len) 字节数组转换成字符串

   System.out.println("管道读取流结束。。。");
   in.close();

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

 }
}

//管道写入线程
class Write implements Runnable
{
 private PipedOutputStream out;
 Write(PipedOutputStream out)
 {
  this.out = out;
 }
 public void run() //调用线程函数,try异常处理
 {
  try
  {
   System.out.println("管道写入流开始,请等待6秒 ");
   Thread.sleep(6000);   //线程等待6秒
   out.write("piped lai le ".getBytes());  //管道输出流写入数据
   System.out.println("管道写入流结束");
   out.close();
  }
  catch (Exception e)
  {
   throw new RuntimeException("管道写入失败");
  }

 }
}
class  PipedStreamDemo
{
 public static void main(String[] args) throws IOException
 {
  PipedOutputStream out = new PipedOutputStream();
  PipedInputStream in = new PipedInputStream();
  out.connect(in);     //管道连接
  Write w = new Write(out);
  Read r = new Read(in);
  new Thread(r).start();
  new Thread(w).start();
  
 }
}

/*
操作对象,
ObjectInputStream 与ObjectOutputStream
 被操作的对象需要实现Serializable(标记接口)

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

 //该方法的功能是将person对象存入到obj.txt文件中
 public static void writeObj()throws IOException
 {
  ObjectOutputStream oos =
   new ObjectOutputStream(new FileOutputStream("obj.txt"));//输出流,要将对象写入到obj.txt文件中

  oos.writeObject(new Person("zzh001",25));

  oos.close();
 }
}

 

/*
Serializable接口是标记接口,没有方法
用于堆中的对象的序列化,会根据类成员生成UID
*/
import java.io.*;
class  Person implements Serializable //Serializable
{
 //public static final long serialVersionUID = 42L; //用于方便序列化操作
 
 //static String country = "cn";  静态成员存在方法区中,不会参与序列化
 //transient int age;  被transient修饰的成员即使存在堆内存中,也不会参与序列化

 String name;
 int age;
 Person(String name,int age)
 {
  this.name=name;
  this.age=age;
 }

 public String toString()
 {
  return name+":"+age;
 }
}

/*
DataInputStream 与 DataOutputStream

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

*/
import java.io.*;

class  DataStreamDemo
{
 public static void main(String[] args) throws IOException
 {
  //writeData();
  //readData();
  //writeUTFDemo();

  OutputStreamWriter osw =  //向utf.txt文件中写入汉字,按照utf-8编码表,汉字是字符,需要转换成字节流存储
   new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8");

  osw.write("你好");  //6个字节,
  osw.close();
 }

 public static void writeUTFDemo()throws IOException
 {
  DataOutputStream dos =
   new DataOutputStream(new FileOutputStream("UTFFile.txt"));
  //而且要读取出来数据,必须使用 readUTF()方法
  dos.writeUTF("你好");  //8个字节,自定义utf编码表与--不一样
  dos.close();

 }

 public static void readData()throws IOException
 {
  DataInputStream dis =
   new DataInputStream(new FileInputStream("dataFile.txt")); //从dataFile.txt文件中读取数据
  int num = dis.readInt();
  boolean d = dis.readBoolean();
  double b = dis.readDouble();
  
  System.out.println("num:"+num+",d:"+d+",b:"+b);
  dis.close();
 }

 public static void writeData()throws IOException 
 {
  DataOutputStream dos =
   new DataOutputStream(new FileOutputStream("dataFile.txt")); //往dataFile.txt文件中写入数据
  dos.writeInt(123);
  dos.writeBoolean(true);  //用那个基本数据类型写入的就要使用对应的基本数据类型读取出来
  dos.writeDouble(954.2564);
  dos.close();
 }

}

/*
RandomAccessFile 随机读取类

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

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

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

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

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

*/
import java.io.*;

class  RandomAccessFileDemo
{
 public static void main(String[] args)throws IOException
 {
  //writeFile();
  //readFile();
  readFile_2();
 }

 public static void readFile_2()throws IOException
 {
  RandomAccessFile raf = new RandomAccessFile("raf.txt","rw");
  //如果我想读取李四的姓名和年龄,可以设置指针直接获取李四的信息
  raf.seek(8);
  //还可以通过 跳过指定的字节数
  //raf.skipBytes(8)  效果和raf.seek(8);一样,但是区别是只能向后,不能向前

  byte[] buf = new byte[4];
  raf.read(buf);   
  String name = new String(buf); 
  System.out.println("name="+name);

  int age;
  age = raf.readInt(); 
  System.out.println("age="+age);

  raf.close();
 }

 public static void readFile()throws IOException
 {
  RandomAccessFile raf = new RandomAccessFile("raf.txt","r");  //只读模式
  byte[] buf = new byte[4];
  raf.read(buf);   //将raf.txt文件中的数据读取出来存放到buf 字节数组中
  String name = new String(buf); //字节数组变字符串

  int age;
  //age = raf.read(); //read()方法读取数据是按照一个字节一个字节来读取的
  age = raf.readInt();  //一下安装4个字节来读取数据
  System.out.println("name="+name);
  System.out.println("age="+age);

  raf.close();

 }

 public static void writeFile()throws IOException
 {
  RandomAccessFile raf = new RandomAccessFile("raf.txt","rw"); //读写模式
  raf.write("张三".getBytes());
  //raf.write(258);   因为write()存入数据是按照字节来存的,一个字节是8位,所以最大是255,
  //解决办法是存入的最大值4个字节,32位就好了
  raf.writeInt(97);

  raf.write("李四".getBytes());
  raf.writeInt(99);
  raf.close();
 }
}

/*
编码:字节最小单位,字符是常见的数据
 (字符串变字节数组,eg 发报)
String --> byte[] : srt.getBytes();使用的编码表是默认GBK码表
   也可以使用指定编码表:  str.getBytes(charsetName)


解码:字节数组变成字符串
byte[] --> String : new String(byte[]);
 也可以使用指定编码表:  new String(byte[],charsetName);

*/
import java.util.*;
class  EncodeDemo
{
 public static void main(String[] args) throws Exception
 { 
  /*
  //编码
  String s = "你好";
  byte[] b1 = s.getBytes("GBK"); //byte[] b1 = s.getBytes();
  System.out.println(Arrays.toString(b1));// 打印结果是4个数字
  
  //解码
  String s1 = new String(b1,"iso8859-1");
  System.out.println("s1="+s1);

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

  //再解码
  String s2 = new String(b2);
  System.out.println("s2="+s2);
  */


  /*************************************
  这种情况一定要小心
  *************************************/
  //编码
  String s = "你好";
  byte[] b1 = s.getBytes("GBK"); //byte[] b1 = s.getBytes();
  System.out.println(Arrays.toString(b1));// 打印结果是4个数字
  
  //解码
  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);
  System.out.println("s2="+s2);


  //解码
  //String s1 = new String(b1,"utf-8");
  //System.out.println("s1="+s1);
 }
}

 

/*
联通问题,在记事本中,写入联通二字,再次打开,因为解码会出现乱码现象

*/

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)); //其结果和utf-8的编码表规则重复,所以会出现乱码,
   //这就是联通问题的原因,参考 API 1.6  DataInput接口的UTF-8 修改版

   //Integer.toBinaryString(b) 十进制转换成二进制
  }
 }
}

 

/*
编码表:
ASCII :美国标准信息交换码
 (一个字节7位表示)
ISO8859-1 拉丁码表,欧洲码表
 (一个字节8位表示)
GB2312:(6k)中国的中文标码表
GBK:(2w)中国的中文标码表升级,融合更多的中文文字符号
Unicode:国际标准吗,融合了多种文字
 所有文字都用两个字节来表示,
UTF-8:最多用三个字节来表示一个字符
unicode transform format 一个字节可以表示的就用一个字节

*/

import java.io.*;
class  EncodeStream
{
 public static void main(String[] args) throws IOException
 {
  //writeTest();
  readTest();
 }

 //要从文件中读取数据,因为文件中得数据是字节形式,而读取出来后是字符形式,需要转换,字节流转换成字符流
 public static void readTest()throws IOException
 {
  //InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"),"GBK");
  
  //对应编码表的文件数据,需要使用对应编码表进行读取,否则会出问题
  InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"UTF-8");

  //byte[] buf = new byte[10]; //为什么从文件中读取的数据不能存储在字节数组中,而可以存储在字符数组中。
  char[] buf = new char[10];
  
  int len = isr.read(buf);

  String s = new String(buf,0,len);
  System.out.println(s);
  isr.close();

 }
 
 //往文件中写入数据,按照不同的标码表写入
 //因为写入的是汉字,为字符,需要转换成字节流
 public static void writeTest()throws IOException
 {
  //按照默认编码表写入数据,4个字节
  //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("code.txt"));
  
  //按照GBK编码表写入数据,4个字节,所以知道默认标码表是GBK
  //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");

  //按照UTF-8 编码表写入数据,6个字节
  OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");

  osw.write("你好");
  osw.close();
 }
}

必须要掌握的知识

 

/*
有五个学生,每个学生有3门课程的成绩,
从键盘数据以上数据(姓名,语文成绩,数学,英语)
输入格式 如:zhangsan,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 cn;
 private int ma;
 private int en;
 private int sum;

 Student(String name,int cn,int ma,int en)
 {
  this.name=name;
  this.cn=cn;
  this.ma=ma;
  this.en=en;
  sum=cn+ma+en;
 }

 public int compareTo(Student stu)
 {
  int num =new Integer(this.sum).compareTo(new Integer(stu.sum));
  if(num==0)
   return this.name.compareTo(stu.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+","+cn+","+ma+","+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));

  Set<Student> stus = null;

  if(cmp==null)
   stus = new TreeSet<Student>();
  else
   stus = new TreeSet<Student>(cmp);

  String line = null;
  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 writeToFile(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.writeToFile(stus);
 }
}

 

 


/*
class StudentInfoTool
{
 public static Set<Student> getStudents()throws IOException
 {
  BufferedReader bufr =
   new BufferedReader(new InputStreamReader(System.in));

  Set<Student> stus = new TreeSet<Student>();
  String line = null;
  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 writeToFile(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();
 }
}
*/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值