黑马程序员---IO包中的其他类(一)

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

 

<PrintStream & PrintWriter、SequenceInputStream、ObjectOutputStream & ObjectInputStream、PipedInputStream & PipedOutputStream>

 

打印流

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

 

PrintStream

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

1.file,File对象

2.String路径文件名称

3.字节输出流 OutputStream

构造方法摘要
PrintStream(File file)
          创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(File file,String csn)
          创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(OutputStream out)
          创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush)
          创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush,String encoding)
          创建新的打印流。
PrintStream(String fileName)
          创建具有指定文件名称且不带自动行刷新的新打印流。
PrintStream(String fileName,String csn)
          创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

 

PrintWriter:(相比之下,这个更常用一些)

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

1.file,File对象

2.String路径文件名称

3.字节输出流 OutputStream

4.字符输出流 Writer

构造方法摘要
PrintWriter(File file)
          使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(File file,String csn)
          创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
PrintWriter(OutputStream out)
          根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush)
          通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(String fileName)
          创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName,String csn)
          创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out)
          创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush)
          创建新 PrintWriter。

import java.io.*;
class PrintWriterDemo 
{
	public static void main(String[] args) throws IOException
	{
		//将键盘录入打印到屏幕上

		//源:文本FileReader 设备:键盘System.in属于字节流
		//使用字节转换流InputStreamReader(System.in)
		//提高效率BufferedReader
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		/*
		//目的:纯文本FileWriter 设备:控制台System.out属于字节打印流
		//使用字节流输出转换流OutputStreamWriter(System.out)
		//提高效率BufferedWriter
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		String line = null;
		while((line=br.readLine())!=null)
		{
			if(line.equals("over"))
				break;
			else
			{
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		}
		*/

		//使用特殊的打印流PrintWriter代替BufferedWriter
		PrintWriter pw = new PrintWriter(System.out, true);
		//可以直接接收OutputStream类型,可以带着自动刷新标记true

		String line = null;
		while((line=br.readLine())!=null)
		{
			if(line.equals("over"))
				break;
			pw.println(line);//带着换行的打印方法
		}

		br.close();
		pw.close();
	}
}


将键盘录入打印到文件中

import java.io.*;
class PrintWriterDemo 
{
	public static void main(String[] args) throws IOException
	{
		//将键盘录入打印到硬盘文件中

		//源:文本FileReader 设备:键盘System.in属于字节流
		//使用字节转换流InputStreamReader(System.in)
		//提高效率BufferedReader
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//使用特殊的打印流PrintWriter代替BufferedWriter
		//PrintWriter pw = new PrintWriter("a.txt");//没有标记的不能设置自动刷新
		
		//将文件名封装到流里面,就可以添加自动刷新标记了
		PrintWriter pw = new PrintWriter(new PrintStream("a.txt"),true);
		
		

		String line = null;
		while((line=br.readLine())!=null)
		{
			if(line.equals("over"))
				break;
			pw.println(line);//带着换行的打印方法
		}

		br.close();
		pw.close();
	}
}


 

序列流

SequenceInputStream

对多个流进行合并。

构造方法摘要
SequenceInputStream(Enumeration<? extendsInputStream> e)       泛型限定
          通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的Enumeration 型参数。
SequenceInputStream(InputStream s1,InputStream s2)
          通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。

 

把三个文件合并成一个文件:

import java.io.*;
import java.util.*;
class SequenceDemo 
{
	public static void main(String[] args) throws IOException
	{
		Vector<FileInputStream> ve = new Vector<FileInputStream>();
		ve.add(new FileInputStream("1.txt"));
		ve.add(new FileInputStream("2.txt"));
		ve.add(new FileInputStream("3.txt"));

		Enumeration<FileInputStream> en = ve.elements();

		SequenceInputStream sis = new SequenceInputStream(en);

		FileOutputStream fos = new FileOutputStream("4.txt");

		byte[] by = new byte[1024];

		int len = 0;
		while((len=sis.read(by))!=-1)
		{
			fos.write(by,0,len);
		}
		sis.close();
		fos.close();
	}
}


 

切割文件:

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

class SplitFile 
{
	public static void main(String[] args) throws IOException
	{
		FileInputStream fis = new FileInputStream("cat.jpg");

		FileOutputStream fos = null;
		
		byte[] buf = new byte[1024];

		int len = 0;
		int count = 1;
		while((len=fis.read(buf))!=-1)
		{
			fos = new FileOutputStream(".\\splitFiles\\"+(count++)+".part");
			fos.write(buf,0,len);
			fos.close();
		}

		fis.close();
	}
}


将碎片文件合并:

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

class SplitFile 
{
	public static void main(String[] args) throws IOException
	{
		mergeFiles();
	}

	//合并文件
	public static void mergeFiles()throws IOException
	{
		ArrayList<InputStream> al = new ArrayList<InputStream>();//ArrayList没有加锁,所以比Vector高效。
		for(int x=1;x<=7;x++)
		{
			al.add(new FileInputStream(".\\splitFiles\\"+x+".part"));
		}
		final Iterator<InputStream> it = al.iterator();

		Enumeration<InputStream> en = new Enumeration<InputStream>()//匿名内部类实现Enumeration接口。
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public InputStream nextElement()
			{
				return it.next();
			}
		};

		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(".\\splitFiles\\cat.jpg");

		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		sis.close();
		fos.close();
	}
}


 

如何切割较大的文件,且字节数组不能开太大,但又不想把文件切成太多份:

可以按照以下思想去做:

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

class SplitFile 
{
	public static void main(String[] args) throws IOException
	{
		splitFile();
	}

	//切割文件
	public static void splitFile() throws IOException
	{
		FileInputStream fis = new FileInputStream("cat.jpg");

		FileOutputStream fos = null;
		
		byte[] buf = new byte[1024];//这个数组不能开太大,因为会发生内存溢出。

		int len = 0;
		int count = 1;
		int time = 0;
		fos = new FileOutputStream(".\\splitFiles\\"+(count++)+".part");
		while((len=fis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
			time++;
			if(time>2)
			{
				fos.close();
				fos = new FileOutputStream(".\\splitFiles\\"+(count++)+".part");
				time = 0;
			}
		}

		if(fos!=null)
			fos.close();
		fis.close();
	}



	//合并文件
	public static void mergeFiles()throws IOException
	{
		ArrayList<InputStream> al = new ArrayList<InputStream>();
		for(int x=1;x<=3;x++)
		{
			al.add(new FileInputStream(".\\splitFiles\\"+x+".part"));
		}
		final Iterator<InputStream> it = al.iterator();

		Enumeration<InputStream> en = new Enumeration<InputStream>()
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public InputStream nextElement()
			{
				return it.next();
			}
		};

		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(".\\splitFiles\\cat.jpg");

		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		sis.close();
		fos.close();
	}
}



 

能操作对象的流:(对象的持久化,也叫序列化)

ObjectOutputStream

java.lang.Object

          |--java.io.OutputStream

                       |--java.io.ObjectOutputStream

public class ObjectOutputStream

extends OutputStream implements ObjectOutput, ObjectStreamConstants

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。通过在流中使用文件可以实现对象的持久存储。

构造方法摘要
protected ObjectOutputStream()
          为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。
 ObjectOutputStream(OutputStream out)            
          创建写入指定 OutputStream 的 ObjectOutputStream。

 将一个对象写入文件里面去,对象是纯文本吗?纯文本是你能够看得懂的字符,对象是字节码文件,所以只能用字节流。

方法摘要
 voidwrite(int val)
          写入一个字节。
 voidwriteInt(int val)
          写入一个 32 位的 int 值。
以上两个方法不同之处在于:

write(int value)只写入这个int型值的最低8位,

writeInt(int value) 将这个int型值的整个32位都写入。

 

 voidwriteObject(Object obj)
          将指定的对象写入 ObjectOutputStream。

被操作的对象需要实现Serializable 接口(标记接口)。

类通过实现 java.io.Serializable 接口以启用其序列化功能。此接口没有方法,称之为:标记接口。

 

ObjectInputStream

java.lang.Object

          |--java.io.InputStream

                      |--java.io.ObjectInputStream

public class ObjectInputStream

extends InputStream implements ObjectInput, ObjectStreamConstants

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

构造方法摘要
protected ObjectInputStream()
          为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。
 ObjectInputStream(InputStream in)
          创建从指定 InputStream 读取的 ObjectInputStream。

 

static的静态数据在方法区不能被序列化,只能序列化堆内存里面的东西。

堆内存中的数据如果也不想被序列化的话,可以加 transient 关键字修饰。

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

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

ANY-ACCESS-MODIFIER(任何访问修饰符):     static final long serialVersionUID = 42L;(long型的值,自己随便定一个值)

这个UID有什么用?

给类定义一个固定标识,为了序列化方便,修改后的新的类还能去操作曾经被序列化的对象。

import java.io.*;
class ObjectStreamDemo
{
	public static void main(String[] args) throws Exception
	{
		readObj();

	}

	public static void writeObj()throws Exception
	{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		oos.writeObject(new Person("lisi",79));
		oos.close();
	}

	public static void readObj()throws Exception
	{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Person p = (Person)ois.readObject();
		System.out.println(p.toString());
		ois.close();
	}
}

这样就把这个Person类的对象存放到了文件中:

真正我们存的时候不存txt格式的,因为txt可以打开,我们打开没意义,打开也不认识,不需要打开,所以我们一般存成 .object 格式的。如:person.object

 读出:

 

总结:

这俩对象得成对使用,也就是说你使用ObjectOutputStream序列化的话,就必须使用ObjectInputStream来读出来(反序列化)。

如果想存许多对象的话,可以一直往里写,写进去之后,read一次读出来一个对象,再read一次又读出来一个对象。

 

 

管道流:

PipedInputStream PipedOutputStream 成对使用(与多线程关联的流)

java.lang.Object

         |--java.io.InputStream

                    |--java.io.PipedInputStream

public class PipedInputStream

extends InputStream

管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。

构造方法摘要
PipedInputStream()
          创建尚未连接PipedInputStream
PipedInputStream(int pipeSize)
          创建一个尚未连接PipedInputStream,并对管道缓冲区使用指定的管道大小。
PipedInputStream(PipedOutputStream src)
          创建 PipedInputStream,使其连接到管道输出流 src
PipedInputStream(PipedOutputStream src, int pipeSize)
          创建一个 PipedInputStream,使其连接到管道输出流 src,并对管道缓冲区使用指定的管道大小。

我们发现PipedInputStream的构造方法就可以连接一个PipedOutputStream,如果使用空参构造函数,可以使用以下connect方法进行连接:

方法摘要
 voidconnect(PipedOutputStream src)
          使此管道输入流连接到管道输出流 src

 

如果输入流先抢到CPU执行权,那么阻塞处于等待状态,然后输出流执行写入数据,然后输入流读到数据,将读到的数据打印。

注意:一定要将管道输入流与管道输出流相连接。因为它们是一根管子,从一端写入从另一端读出。

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];
			int len = in.read(buf);
			/*这里read方法可能出现异常,但在run方法上不能抛异常,
			因为Runnable接口的run方法没有抛异常,
			这个如果抛了就不算覆盖了,只能try、catch*/
			String s = new String(buf,0,len);
			System.out.println("从PipedOutputStream那端读到数据:"+s);
		}
		catch (IOException e)
		{
			throw new RuntimeException("PipedInputStream读取失败!");
		}		
	}
}

class Write implements Runnable
{
	private PipedOutputStream out;
	Write(PipedOutputStream out)
	{
		this.out = out;
	}

	public void run()
	{
		try
		{
			out.write("写入数据啦!balabala".getBytes());
			out.close();
		}
		catch (IOException e)
		{
			throw new RuntimeException("PipedOutputStream写入失败!");
		}		
	}
}

class PipedStreamDemo 
{
	public static void main(String[] args) throws IOException
	{
		PipedInputStream in = new PipedInputStream();
		PipedOutputStream out = new PipedOutputStream();
		in.connect(out);
		/*记住:使此管道输入流in连接到管道输出流out。
		如果此对象已经连接到其他某个管道输出流,则抛出 IOException。*/

		Read r = new Read(in);
		Write w = new Write(out);
		Thread t1 = new Thread(r);
		Thread t2 = new Thread(w);

		t1.start();
		t2.start();
	}
}


 

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

余额充值