黑马程序员——Java基础---IO(二)---对象流、管道流、RandomAccessFile、数据流、数组流、字符编码

-----------android培训java培训、java学习型技术博客、期待与您交流!------------

第一讲. 对象流 ObjectInputStream, ObjectOutputStream 

  1. 对象流可以把堆内存中的对象存储起来。首先要求对象本身implements Serializable接口,标示其可以序列化,否则会有NotSerializableException。
  2. Serializable 是一个标记接口,本身不要求其实现类为其实现任何方法。
  3. 静态成员无法序列化,即不会被存入硬盘中,因为它在方法区存储,而不在堆内存中
  4. 可以加入transient 关键字修饰类成员,令其不会被序列化

import java.io.*;
class ObjectIODemo
{
	public static void main(String[] args) throws Exception 
	{
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.txt"));
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.txt"));
		out.writeObject(new Person("Lisi",20));
		Person p = (Person)in.readObject();
		System.out.println(p);
		in.close();
		out.close();
	}
}

class Person //implements Serializable  
/**
<span style="white-space:pre">	</span>序列号uid是通过类的成员计算得到的。也可以自己指定。
**/
{
	private static final long serialVersionUID = 42L; //自定义uid
	String name;
	int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return "name="+name+";age="+age;
	}
}

第二讲. 管道流PipedInputStream PipedOutputStream

  1. 管道流为多线程而设计的IO流,单线程会导致死锁,读写两个管道应异步进行。
  2. 可以对接,读写双发可以在创建时把对方当参数传入,也可以利用connect方法

import java.io.*;
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();
	}
}

class Read implements Runnable
{
	private PipedInputStream in;
	Read(PipedInputStream in){this.in = in;}
	public void run(){
		try{
			byte[] buff = new byte[1024];
			int len = in.read(buff);
			String s = new String(buff,0,len);
			System.out.println(s);
			in.close();
		}
		catch(IOException e){
			throw new RuntimeException("Error in input Pipe!");
		}
	}
}
class Write implements Runnable
{
	private PipedOutputStream out;
	Write(PipedOutputStream out){this.out = out;}
	public void run(){
		try{
			out.write("hahahaha!".getBytes());
			out.close();
		}
		catch(IOException e){
			throw new RuntimeException ("Error in output Pipe~"); 
		}
	}
}

第三讲.RandomAccessFile  

  1. 工具类,直接继承自Object 
  2. 里面封装了一个数组,通过指针对元素进行操作
  3. 在内部封装了字节输入和输出流
  4. 只能操作文件,而且有模式限制(只读"r",读写"rw"等)。rw对文件进行追加,若没有则创建。r不会创建文件。当然为了防止你写错,会抛异常。
  5. 可以实现多线程下载(通过指针指定文本的不同位置),即异步同时写入

import java.io.*;
class RandomAccessFileDemo 
{
	public static void main(String[] args) throws IOException
	{
		writeFile();
		readFile();
	}
	private static void writeFile() throws IOException
	{
		RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
		raf.write("李四".getBytes());
		raf.writeInt(97);//raf.write(97);  // 只取最低8位
		raf.write("王五".getBytes());
		raf.writeInt(99);
		raf.seek(8*3);
		raf.write("周七".getBytes());
		raf.writeInt(102);
		raf.close();
	}
	private static void readFile() throws IOException
	{
		RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
		raf.seek(8);  //raf.skipBytes(8);
		byte[] buff = new byte[4];
		raf.read(buff);
		String name = new String(buff);
		int age = raf.readInt();
		System.out.println(name+age);
		raf.close();
	}
}

第四讲. DataInputStream, DataOutputStream 专门用来操作基本数据类型

  1. 数据流,可以用它处理各种基本类型数据
  2. writeUTF方法写入的数据只能用对应的readUTF读,它写入的格式跟一般utf格式是不一样的。

import java.io.*;
class DataStreamDemo 
{
	public static void main(String[] args) throws IOException
	{
		writeData();
		readData();
	}
	private static void writeData() throws IOException
	{
		DataOutputStream out = new DataOutputStream (new FileOutputStream("data.txt"));
		//out.writeInt(345);
		out.writeUTF("你好");//只能用对应的readUTF读
		out.close();
	}
	private static void readData() throws IOException
	{
		DataInputStream in = new DataInputStream (new FileInputStream ("data.txt"));
		System.out.println(in.readUTF());
		in.close();
	}
}

第五讲. ByteArrayInputStream,ByteArrayOutputStream 不涉及底层资源操作,直接读写数组 

  1. 用流的读写思想操作数组,同理也有CharArrayReader,CharArrayWriter;StringReader,StringWriter
  2. ByteArrayInputStream需指定一个字节数组作为数据源;ByteArrayOutputStream内部封装一个可变长度的字节数组,不用定义目的
  3. 没有IO异常,close方法无效(也没必要)
  4. ByteArrayOutputStream 有writeTo(OutputStream out) ,讲字节数组缓冲区中的数据写入到一个目的中(只有这个涉及底层操作)

import java.io.*;
class  ByteArrayStreamDemo
{
	public static void main(String[] args) 
	{	
		ByteArrayInputStream in = new ByteArrayInputStream ("ABCDEFG".getBytes());
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int by;
		while((by=in.read())!=-1)
			out.write(by);
		System.out.println(out.toString());
	}
}

第六讲. 字符编码

Ascii 码表美国标准信息交换码 ,用一个字节的7位可以表示
ISO8859-1拉丁码表、欧洲码表,用一个字节的8位表示,一些服务器会使用
GB2313中国的中文编码表,两个字节表示。为了兼容英文码表,两个字节高位都是1(都是负数),6k~7k字
GBK中文编码表升级版,容纳更多的字,约20k字
Unicode国际标准编码表,融合多种文字,所有都两个字节表示
UTF-8:8-bit unicode transformation format最少用一个字节,最多用三个字节表示一个字符,为使其便于识别,每个字节前都加入特定码头,如下图:

                                                   

  1. “你好”的utf-8编码形式,被GBK解码得到“浣犲ソ”;“你好”GBK编码被utf-8解码得到“??”
  2. 像“联通”,它的编码是符合uft-8的编码头的,用记事本打开会按照utf-8解码
  3. 为 String.getBytes(String charSet) 方法指定字符集时会抛出UnsupportedEncodingException异常,防止不支持的字符集输入

/**
编码:字符串变字节数组 String str;str.getBytes(String charsetName);
解码:字节数组变字符串 new String(byte[],charsetName);
**/
import java.util.*;
class  EncodeDemo
{
	public static void main(String[] args) throws Exception
	{
		String str1 = "你好";
		byte[] b1 = str1.getBytes("uft-8"); //默认是GBK
		//模拟服务器端应用欧洲码表的场景,此时需用重编解码的方式获得原中文文本
		String str2 = new String(b1,"iso8859-1"));
		byte[] b2 = str2.getBytes("ios8859-1"));
		String str3 = new String(b2,"utf-8");
	}
}

练习题

/** 练习:
1.有五个学生,每个学生有三门课的成绩
2.有键盘输入,格式如Lisi,45,48,87 , 计算总分
3.按总成绩大小顺序将学生信息输出到"stud.txt"文件中
**/
import java.io.*;
import java.util.*;
class Test 
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		Set<Student> students = new TreeSet<Student>();
		String name;
		int[] scores = new int[3];
		for (int i=1;i<=5 ;i++ )
		{
			System.out.println("请输入第"+i+"名学生的信息:");
			String line = in.readLine();
			String[] strs = line.split(",");
			name=strs[0].trim();
			for (int j=2;j<=strs.length ;j++ )
				scores[j-2]=Integer.parseInt(strs[j-1].trim());
			students.add(new Student(name,scores));
		}
		in.close();
		PrintStream out = new PrintStream("stud.txt");
		out.println(students);
		out.close();
	}
}

class Student implements Comparable<Student>
{
	private String name;
	private int[] scores = new int[3];
	private int score;
	Student(String name,int[] scores)
	{
		this.name = name;
		for (int i=0;i<scores.length ;i++ )
		{
			this.scores[i]=scores[i];
			score+=scores[i];
		}
	}
	public int compareTo(Student stu){
		return stu.score-this.score;
	}

	public boolean equals(Object stu){
		if (!(stu instanceof Student))
			return false;
		return this.name.equals(((Student)stu).name);
	}
	public String toString(){
		StringBuilder str = new StringBuilder();
		str.append(name+",");
		for (int i=0;i<3 ;i++ )
		{
			str.append(scores[i]);
			str.append(",");
		}
		str.append("总分:"+score+"\n");
		return str.toString();
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值