<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.io.ObjectOutputStream
public class ObjectOutputStream
extends OutputStream implements ObjectOutput, ObjectStreamConstantsObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。通过在流中使用文件可以实现对象的持久存储。
构造方法摘要 | |
---|---|
protected | ObjectOutputStream() 为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。 |
| ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。 |
将一个对象写入文件里面去,对象是纯文本吗?纯文本是你能够看得懂的字符,对象是字节码文件,所以只能用字节流。
方法摘要 |
---|
void | write(int val) 写入一个字节。 |
void | writeInt(int val) 写入一个 32 位的 int 值。 |
write(int value)只写入这个int型值的最低8位,
writeInt(int value) 将这个int型值的整个32位都写入。
void | writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 |
被操作的对象需要实现Serializable 接口(标记接口)。
类通过实现 java.io.Serializable 接口以启用其序列化功能。此接口没有方法,称之为:标记接口。
ObjectInputStream
|--java.io.ObjectInputStream
public class ObjectInputStream
extends InputStream implements ObjectInput, ObjectStreamConstantsObjectInputStream 对以前使用 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.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方法进行连接:
方法摘要 | |
---|---|
void | connect(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