黑马程序员------IO流(No.4)(打印流、序列流、管道流、RandomAccessFile、常用数据类型的操作流)

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

 

 

微笑PrintWriter打印流

 

PrintStream与PrintWriter

可以直接操作输入流和文件。

 

打印流:

该流提供了打印方法,可以将各种数据类型的数据都原样打印。

 

字节打印流:

PrintStream

构造函数可以接收的参数类型:

1.file对象:File

2.字符串路径:String

3.字节输出流;OutputStream

 

 

字符打印流:(使用较多)

PrintWriter

构造函数可以接收的参数类型:

1.file对象:File

2.字符串路径:String

3.字节输出流;OutputStream

4.字符输出流:Writer

 

/*
PrintWriter
构造函数可以接收的参数类型:
1.file对象:File
2.字符串路径:String
3.字节输出流;OutputStream
4.字符输出流:Writer
*/
import java.io.*;

class PrintStreamDemo{
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		//true是自动刷新
		PrintWriter pw = new PrintWriter(System.out,true);
		//将文件保存到a.txt
		//PrintWriter pw = new PrintWriter(newFileWriter("a.txt"),true);
		String line = null;
		while((line = br.readLine())!=null){
			if("over".equals(line)||"OVER".equals(line))
				break;
			pw.println(line.toUpperCase());
		}
		pw.close();
		br.close();
	}
}

 

 

微笑SequenceInputStream 序列流

 

SequenceInputStream 对多个流进行合并。

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

class SequenceDemo{
	public static void main(String[] args)throws IOException{
		Vector<FileInputStream> v = new Vector<FileInputStream>();
		v.add(new FileInputStream("1.txt"));
		v.add(new FileInputStream("2.txt"));
		v.add(new FileInputStream("3.txt"));
		//得到Enumeration类型的数据
		Enumeration<FileInputStream> en = v.elements();
		//传入Enumeration类型参数
		SequenceInputStream sis = new SequenceInputStream(en);
		BufferedReader br = new BufferedReader(new InputStreamReader(sis));
		//建立写入缓冲区并与文件关联
		BufferedWriter bw = new BufferedWriter(new FileWriter("4.txt"));
		String line = null;
		while((line=br.readLine())!=null){
			bw.write(line);
			bw.newLine();
		}
		//关闭资源
		bw.close();
		br.close();
	}
}


mp3文件的切割以及切割后的还原。

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

class SplitDemo{
	public static void main(String[] args)throws IOException{
		splitMethod();
		mergeMethod();
	}
	//切割文件的功能
	public static void splitMethod()throws IOException{
		//建立文件与输入字节流的关联
		FileInputStream fis = new FileInputStream("Sagyman.mp3");
		FileOutputStream fos = null;
		byte[] buf = new byte[1024*1024];
		int len = 0;
		int count = 1;
		//将指定大小的字节写入指定文件。
		while((len=fis.read(buf))!=-1){
			fos = new FileOutputStream("Sagyman"+(count++)+".part");
			fos.write(buf,0,len);
			//关闭资源
			fos.close();
		}
		//关闭资源
		fis.close();
	}
	//合并文件的功能
	public static void mergeMethod()throws IOException{
		//关联文件碎片
		ArrayList<FileInputStream> a = new ArrayList<FileInputStream>();
		a.add(new FileInputStream("Sagyman1.part"));
		a.add(new FileInputStream("Sagyman2.part"));
		a.add(new FileInputStream("Sagyman3.part"));
		a.add(new FileInputStream("Sagyman4.part"));
		//得到Enumeration类型的数据
		final Iterator<FileInputStream> it = a.iterator();
		Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
			public boolean hasMoreElements(){
				return it.hasNext();
			}
			public FileInputStream nextElement(){
				return it.next();
			}
		};
		//使用SequenceInputStream流,并传入Enumeration参数
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream("Sgyman1.mp3");
		//将字节输入流写入到字节输出流
		int len = 0;
		byte[] buf = new byte[1024];
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
}

上面的程序执行splitMethod();后


 上面的程序执行mergeMethod();后

 

 

 微笑操作对象

 

ObjectInputStream与ObjectOutputStream

被操作的对象需要实现Serializable接口(该接口没有任何方法,只是一个标记接口)

 

若对象要被序列化,必须实现Serializable接口。

 

1.只有存在与堆内存中的数据才能被序列化
2.private String name ;//堆内存中的属性,可以被序列化
3.transient int age; //虽然在堆内存中,但有transient关键字修饰,无法被序列化
4.static String country = "cn";//静态属性在共享区(方法区也叫静态区),无法被序列化 

要实现序列化的类

import java.io.*;
//若对象要被序列化,必须实现Serializable接口。
class Person implements Serializable{
	public static final long serialVersionUID = 42L;
	//只有存在与堆内存中的数据才能被序列化
	private String name ;//堆内存中的属性,可以被序列化
	transient int age;	//虽然在堆内存中,但有transient关键字修饰,无法被序列化
	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 ObjectStreamDemo{
	public static void main(String[] args)throws Exception{
		readObj();
	}
	public static void writeObj()throws IOException{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.object"));
		//向文件写入一个序列化的对象
		oos.writeObject(new Person("zhangsan",12,"en"));
		oos.close();
	}
	public static void readObj()throws Exception{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.object"));
		//从文件读一个序列化对象
		Person p = (Person)ois.readObject();
		System.out.println(p);
		ois.close();
	}
}



 微笑管道流

 

PipedInputStream和PipedOutputStream

输入输出可以直接进行连接,通过结合线程使用

 

    数据由某个线程从PipedInputStream对象读取,并由其他线程将其写入相应的PipedOutStream中。

不建议使用单线程,这样会出现死锁现象。 管道输入流包含一个缓冲区,可在缓冲区规定的范围内

读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,那么这个管道流已经损坏。

 

class Read implements Runnable	{
		private PipedInputStream in;
		Read(PipedInputStream in){
			this.in = in;
		}
		public void run(){
			try
			{
				byte[] buf = new byte[1024];
				int len = in.read();
				String s = new String(buf,0,len);
				System.out.println(s);
				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
			{
				out.write("piped is come".getBytes());
				out.close();
			}
			catch (Exception e)
			{
				throw new RuntimeException("管道读取流失败");
			}
		}
	}


微笑RandomAccessFile

 

该类不算是IO体系中子类。

而是直接继承自object。

 

但是它是IO包中的成员。因为它具备读和写的功能。

内部封装了一个数组,而且通过指针对数组的元素进行操作。

可以通过getFilePointer获取指针位置,

同时可以通过seek改变指针的位置。

 

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

 

通过构造函数可以看出,该类只能操作文件。

而且操作文件还有模式:只读r,读写rw等。

 

如果模式为只读r,不会创建文件。会失去读取一个已存在文件,如果该文件不存在,则会出现异常。

如果模式rw,操作的文件不存在,会自动创建;如果文件存在,不会覆盖文件内容。

 

import java.io.*;

class RandomAccessFileDemo{
	public static void main(String[] args)throws IOException{
		//readFile();
		writeFile();
	}
	public static void readFile()throws IOException{
		RandomAccessFile raf = new RandomAccessFile("raf.txt","r");
		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);
	}
	public static void writeFile()throws IOException{
		RandomAccessFile raf = new RandomAccessFile("raf.txt","rw");
		raf.write("李四".getBytes());
		raf.writeInt(97);
		raf.write("武大".getBytes());
		raf.writeInt(101);
		//调整对象中的指针
		raf.seek(8*5);
		raf.write("本山".getBytes());
		raf.writeInt(110);
		//跳过指定的字节数
		raf.skipBytes(8);
		raf.write("笨蛋".getBytes());
		raf.writeInt(110);
		raf.close();
	}
}

 

微笑数据操作。

 

操作基本数据类型

DataInputStream与DataOutputStream。参见文档

 

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream

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

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("ABCDA".getBytes());
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		int by = 0;
		while((by=bis.read())!=-1){
			System.out.println(by);
			bos.write(by);
		}
		System.out.println(bos.size());
		System.out.println(bos);
		//可设置输出目的。要处理异常。
		//bos.writeTo(System.out);
	}
}


以下两种实现方式与操作字节数组类似,详细参考文档。

操作字符数组

CharArrayReader与CharArrayWriter

操作字符串

StringReader与StrinWriter

 

 

---------------------- 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、付费专栏及课程。

余额充值