黑马程序员-JAVA高级(IO输入与输出)PART4

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------


这部分内容的知识点为:

1.IO包中的其他几个类;

2.字符编码;

3.练习。


一、IO包中的其他几个类


1.对象的序列化:ObjectInputStream和ObjectOutputStream

import java.io.*;

/*
只有实现了Serializable接口的类才可以被序列化
Serializable接口没有任何方法,称为标记接口
*/
class Person implements Serializable
{
	private 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;
	}
}

class ObjectStreamDemo 
{
	public static void main(String[] args) throws IOException,ClassNotFoundException
	{
		//writeObj();
		readObj();
	}

	public static void readObj() throws IOException,ClassNotFoundException
	{
		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("zhangsan2",39,"kr"));

		oos.close();
	}
}

2.管道流:PipedInputStream和PipedOutputStream

输入输出可以直接进行连接,通过结合线程使用。不要对这两个对象使用单线程,因为这样可能死锁线程。

import java.io.*;

class Read implements Runnable
{
	private PipedInputStream in;
	Read(PipedInputStream in)
	{
		this.in = in;
	}
	public void run()
	{
		BufferedReader bufr = null;
		try
		{
			bufr = new BufferedReader(new InputStreamReader(in));

			//byte[] buf = new byte[10];
			System.out.println("读取前。。。没有阻塞");
			//int len = 0;
			String line = null;
			while((line=bufr.readLine())!=null)
			{
				//String s = new String(buf,0,len);
				System.out.println(line);
			}
			System.out.println("读到数据。。。阻塞");
			
		}
		catch (IOException e)
		{
			throw new RuntimeException("管道流读取失败");
		}
		finally
		{
			if(bufr!=null)
				try
				{
					bufr.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("nima le ge dadada osdopao oepwoe woeiupoa".getBytes());

			//out.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("管道流写入失败");
		}
		finally
		{
			try
			{
				out.close();
			}
			catch (IOException 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();
	}
}

3.RandomAccessFile

随机访问文件,自身具备读写的方法。

该类直接继承自Object,不算是IO体系中的子类,但因为读和写功能,它是IO包中成员。其内部封装了一个数组,通过指针对数组元素进行操作。

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

通过构造函数可以看出,该类只能操作文件,包含模式:只读r,读写rw。

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

import java.io.*;

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

		RandomAccessFile raf = new RandomAccessFile("ran1.txt","rw");
	}

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

		//调整对象中指针
		//raf.seek(8);

		//跳过指定的字节数
		raf.skipBytes(8);
		
		byte[] buf = new byte[4];
		raf.read(buf);
		String name = new String(buf);
		int age = raf.readInt();

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

		raf.close();
	}

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

		raf.seek(8*3);

		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(98);
		raf.write("王五".getBytes());
		raf.writeInt(93);

		raf.close();
	}
}


4.操作基本数据类型的流对象:DataInputStream和DataOutputStream

/*
用于操作基本数据类型数据的流对象
*/
import java.io.*;

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

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

		String s = dis.readUTF();

		System.out.println("s::"+s);

		dis.close();
	}

	public static void writeUTFDemo() throws IOException
	{
		DataOutputStream dos = new DataOutputStream(
			new FileOutputStream("utfdata.txt"));

		dos.writeUTF("你好");

		dos.close();
	}

	public static void readData() throws IOException
	{
		DataInputStream dis = new DataInputStream(
			new FileInputStream("data.txt"));

		int a = dis.readInt();
		boolean b = dis.readBoolean();
		double c = dis.readDouble();

		System.out.println("a="+a);
		System.out.println("b="+b);
		System.out.println("c="+c);

	}

	public static void writeData() throws IOException
	{
		DataOutputStream dos = new DataOutputStream(
			new FileOutputStream("data.txt"));

		dos.writeInt(124);
		dos.writeBoolean(true);
		dos.writeDouble(1234.453);

		dos.close();
	}	
}


5.操作字节数组的流对象:ByteArrayInputStream和ByteArrayOutputStream

ByteArrayInputStream在构造的时候,需要接收数据源,而且数据源是一个字节数组。

ByteArrayOutputStream在构造的时候,不用定义数据目的,因为该对象内部已经封装了可变长度的字节数组,这就是数据目的。

因为这两个流对象操作的都是数组,没有使用系统资源,所以不用进行关闭操作。

/*
操作字节数组的流对象
*/
import java.io.*;

class ByteArrayStreamDemo 
{
	public static void main(String[] args) throws IOException
	{
		ByteArrayInputStream bais = new ByteArrayInputStream("你好吗".getBytes());

		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		int b = 0;
		while((b=bais.read())!=-1)
			baos.write(b);

		System.out.println(baos.size());

		System.out.println(baos.toString());

        //将此字节数组输出流的全部内容写入到指定的输出流中
		baos.writeTo(new FileOutputStream("bytearr.txt"));
	}
}



二、编码

常见的编码表:

ASCII:美国标准信息交换码,用一个字节的7位表示;

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

GB2312:中国的中文编码表;

GBK:升级的中文编码表,融合更多中文字符;

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

UTF-8:最多用三个字节表示一个字符,可以是一个或两个字节。


1.转换流的字符编码

import java.io.*;

class EncodeStreamDemo 
{
	public static void main(String[] args) throws IOException
	{
		//writeText();
		readText();
	}

	public static void readText() throws IOException
	{
		InputStreamReader isr = new InputStreamReader(
			new FileInputStream("utf.txt"),"utf-8");

		char[] arr = new char[10];
		int len = isr.read(arr);

		System.out.println(new String(arr,0,len));

		isr.close();
	}

	public static void writeText() throws IOException
	{
		OutputStreamWriter osw = new OutputStreamWriter(
			new FileOutputStream("utf.txt"),"utf-8");

		osw.write("你好");

		osw.close();
	}
}

2.字符编码

编码:字符串变成字节数组

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

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,"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,"gbk");
		System.out.println("s2="+s2);
	}

}
以上代码编码解码的过程类似tomcat服务器中的编解码过程。tomcat服务器默认编码是 iso8859-1,如果浏览器提交的数据是gbk编码的汉字,服务器收到后就是乱码,所以必须再次通过 iso8859-1编码,然后再通过 gbk解码才可以。但如果服务器端的编码默认是 utf-8,就不可以这样做。


3.字符编码-联通

现象:在一个文本文件中仅仅输入“联通”两个字,保存之后再次打开的时候显示的是乱码。

解释:文本文件的默认编码是gbk,“联通”两个字通过gbk编码后是11000001 10101010 11001101 10101000,正好符合utf-8编码的形式,所以再次打开文本文件的时候会被误认为是utf-8编码而用utf-8解码,自然就显示乱码。


三、练习

需求:每个学生有三门课的成绩,从键盘按一定的格式输入学生的姓名和三门成绩(如zhangsan,38,89,98),计算出总成绩,并按总成绩的高低顺序把每个学生的信息存放在磁盘文件“stud.txt”中。

1.描述学生对象;

2.定义一个可操作学生对象的工具类。

思想:

1.获取键盘录入的一行数据,提取信息封装成学生对象;

2.因为要存储学生信息,所以使用集合,又因为要排序,所以用TreeSet对象;

3.将集合的信息写入文件中。

import java.io.*;
import java.util.*;

class Student implements Comparable
   
   
    
    
{
	private String name;
	private int mt,cn,en;
	private int sum;

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

	public String getName()
	{
		return this.name;
	}

	public int getSum()
	{
		return this.sum;
	}

	public int hashCode()
	{
		return this.name.hashCode()+this.sum*78;
	}

	public boolean equlas(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 "studnt["+this.name+","+this.mt+","+this.cn+","+this.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;
	}
}

class StudentInfoTool
{
	public static Set
    
    
     
      getStudents()
	{
		return getStudents(null);
	}
	public static Set
     
     
      
       getStudents(Comparator
      
      
       
        cmp)
	{
		Set
       
       
         stus = null; if(cmp==null) stus = new TreeSet 
        
          (); else stus = new TreeSet 
         
           (cmp); BufferedReader bufr = null; try { bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; String[] info = line.split(","); Student s = new Student(info[0],Integer.parseInt(info[1]), Integer.parseInt(info[2]),Integer.parseInt(info[3])); stus.add(s); } return stus; } catch (IOException e) { throw new RuntimeException("学生信息录入失败"); } finally { if(bufr!=null) try { bufr.close(); } catch (IOException e) { throw new RuntimeException("读取流关闭异常"); } } } public static void write2File(Set 
          
            stus) { BufferedWriter bufw = null; try { bufw = new BufferedWriter(new FileWriter("stud.txt")); for(Student s:stus) { bufw.write(s.toString()+"\t"); bufw.write(s.getSum()+""); bufw.newLine(); bufw.flush(); } } catch (IOException e) { throw new RuntimeException("学生信息写入文件失败"); } finally { if(bufw!=null) try { bufw.close(); } catch (IOException e) { throw new RuntimeException("文件写入流关闭失败"); } } } } class StudentInfoTest { public static void main(String[] args) { Comparator 
           
             cmp = Collections.reverseOrder(); Set 
            
              stus = StudentInfoTool.getStudents(cmp); StudentInfoTool.write2File(stus); } } 
             
            
           
          
         
       
      
      
     
     
    
    
   
   


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值