JAVA 基础之OutputStream 详解
目录
- 流的概念
- 输出流
- OutputStream
- 方法
- close 关闭流
- write 将数据写入输出流
- flush 清空输出流
- ByteArrayOutputStream
- 方法
- toString 指定字符集转换为字符串定义
- toByteArray
- PipedOutputStream
- 方法
- connect 连接管道输出流
- FilterOutputStream
- 子类
- 总结
- DataOutputStream
- BufferedOutputStream
- PrintStream
- FileOutputStream
- ObjectOutputStream
流的概念
在 Java 中所有数据都是使用流读写的。流是一组有序的数据序列,将数据从一个地方带到另一个地方。根据数据流向的不同,可以分为输入(Input)流和输出(Output)流两种。流是一个相对抽象的概念,所谓流就是一个传输数据的通道,这个通道可以传输相应类型的数据。进而完成数据的传输。这个通道被实现为一个具体的对象。
输出流
在 Java 中所有输出流类都是 OutputStream 抽象类(字节输出流)和 Writer 抽象类(字符输出流)的子类。其中 OutputStream 类是字节输出流的抽象类,是所有字节输出流的父类。
(1)
OutputStream是以字节为单位的输出流的超类,提供了write()函数从输出流中读取字节数据。
(2)
ByteArrayOutputStream是字节数组输出流,写入ByteArrayOutputStream的数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()获取数据。
(3)
PipedOutputStream是管道输出流,和PipedInputStream一起使用,能实现多线程间的管道通信。
(4)
FilterOutputStream是过滤输出流,是DataOutputStream,BufferedOutputStream和PrintStream的超类
(5)
DataOutputStream是数据输出流,用来装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。
(6)
BufferedOutputStream是缓冲输出流,它的作用是为另一个输出流添加缓冲功能。
(7)
PrintStream是打印输出流,用来装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值
(8)
FileOutputStream是文件输出流,通常用于向文件进行写入操作。
(9)
ObjectOutputStream是对象输出流,它和ObjectInputStream一起对基本数据或者对象的持久存储。
OutputStream
- OutputStream类是Java IO API中所有输出流的基类。子类包括BufferedOutputStream,FileOutputStream等等。
- OutputStream是一个典型的装饰者模式,使用的时候直接new子类。
- OutputStream可以输出到console,文件,磁盘等目标媒介中。
方法
close 关闭流
如果进行关闭输出流挥刀自系统资源被大量占用(句柄、内存等等),最终可能回导致超出句柄或者内存溢出。
public static void main(String[] args) throws Exception
{
OutputStream out = System.out;
try
{
byte[] bs = "欢迎来到www.51gjie.com网站".getBytes();
out.write(bs);
}
catch(IOException e)
{
}
finally
{
out.close(); // 关闭输出流
}
}
write 将数据写入输出流
- write(int b) 作为抽象类中唯一的抽象方法,(非抽象)子类必须实现这个方法。这个方法用得比较少,一般在子类的实现中使用。
- write(byte b[])直接输出一个字节数组中的全部内容。
- write(byte b[], int off, int len) 要输出的内容已存储在了字节数组b[]中,但并非全部输出,只输出从数组off位置开始的len个字节。
- 输出了流里面的内容,一定更要记得关闭资源。
public static void main(String[] args)
{
OutputStream os = null;
try
{
String str = "欢迎加入JAVASCHOOL";
byte[] bytes = str.getBytes();
for(int i = 0; i < bytes.length; i++)
{
os.write(bytes[i]);
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(os != null)
{
try
{
os.close(); //关闭资源
}
catch(IOException e)
{}
}
}
OutputStream out = System.out;
try
{
byte[] bs = "一起来学习JAVA".getBytes();
out.write(bs);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
out.close(); // 关闭输出流
}
}
flush 清空输出流
- flush()下达一条命令给缓冲区,让它将所储存的数据全部清空,即发送给下一级。
- flush()刷空输出流,并输出所有被缓存的字节。由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。
- OutputStream.flush()方法将所有写入到OutputStream的数据冲刷到相应的目标媒介中。比如,如果输出流是FileOutputStream,那么写入到其中的数据可能并没有真正写入到磁盘中。即使所有数据都写入到了FileOutputStream,这些数据还是有可能保留在内存的缓冲区中。通过调用flush()方法,可以把缓冲区内的数据刷新到磁盘(或者网络,以及其他任何形式的目标媒介)中。
// 模拟浏览器,给tomcat服务端发送符合http协议的请求消息
public static void main(String[] args) throws IOException
{
Socket s = new Socket("127.0.0.1", 80);
PrintWriter out = new PrintWriter(s.getOutputStream()); //这里的ture表示流会自动刷新,在后面可以不用使用flush()方法
out.println("GET /myweb/test.jsp HTTP/1.1");
out.println("Accept: */*");
out.println("Accept-Language: zh-CN");
out.println("Accept-Encoding: gzip, deflate");
out.println();
out.flush(); // 清空缓存并输出流
InputStream in = s.getInputStream();
byte b[] = new byte[1024];
int leng = 0;
while((leng = in .read(b)) != -1)
{
String str = new String(b, 0, leng);
System.out.println(str);
}
s.close();
}
ByteArrayOutputStream
ByteArrayOutputStream在内存中创建了一个字节数组,所有发送到输出流的数据都会保存到该字节数组的缓冲区中。数据写入缓冲区以后,然后使用toByteArray()和toString()输出。
//将此字节数组输出流的计数字段重置为零,以便丢弃该输出流中所有当前累积的输出。
public void reset()
//返回缓冲区的当前大小。
public int size()
//关闭输出流
public void close()
实例:
public static void main(String[] args)
{
ByteArrayOutputStream bos = null;
FileInputStream fs = null;
try
{
bos = new ByteArrayOutputStream();
fs = new FileInputStream("c:\\51gjie.txt");
int len;
while((len = fs.read()) != -1)
{
// 把读取到的数据逐个写到ByteArrayOutputStream中
bos.write(len);
}
byte[] array = bos.toByteArray();
// 指定utf-8解码的字符集
System.out.println(new String(array, "utf-8"));
fs.close();
}
catch(IOException e)
{}
finally
{
fs.close();
}
}
方法
toString 指定字符集转换为字符串定义
ByteArrayOutputStream.toString通过使用指定的charsetName解码字节,将缓冲区的内容转换为字符串。 新String的长度是字符集的函数,因此可能不等于字节数组的长度。
public String toString()
public String toString(String charsetName)
public String toString(int hibyte)
参数
charsetName:指定字符集(utf-8,GB2312等)。
返回
从缓冲区内容解码的字符串。
异常
UnsupportedEncodingException :不支持指定的字符集
实例:
public static void main(String args[]) throws Exception
{
InputStream in = null;
ByteArrayOutputStream out = null;
try
{
in = new FileInputStream(new File("c:\\51gjie.txt"));
out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024 * 8];
int len = 0;
while((len = in .read(bytes)) != -1)
{
out.write(bytes, 0, len);
}
System.out.println(out.toString("GBK"));//使用GBK编码转换成字符串
}
catch(FileNotFoundException e)
{}
finally
{
try
{
out.close(); in .close();
}
catch(IOException e)
{}
}
}
toByteArray
ByteArrayOutputStream.toByteArray()将缓冲区的数据全部获取出来,返回字节数组,然后通过string 的方法,使用指定的字符集,通过解码字节将缓冲区内容转换为字符串。
PipedOutputStream
-
in 是输入的位置,out是已经读出去的位置值,读取和写入是多个线程处理的。如果inout:代表输入值从out到尾端的值还没读出,0到in的位置也还没读出;如果inout:代表还有out-in的值没有读取如果in==out :代表没有空间,所有空间都写完了。
-
一个PipedInputStream实例对象必须和一个PipedOutputStream实例对象进行连接而产生一个通信管道.PipedOutputStream可以向管道中写入数据,PipedIntputStream可以读取PipedOutputStream向管道中写入的数据.这两个类主要用来完成线程之间的通信.
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
Thread.sleep(1000);
out.write("hello www.51gjie.com".getBytes());
out.close();
}
catch(Exception e)
{}
}
}
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);
String s = new String(buf, 0, len);
System.out.println("读取到的数据:" + s); in .close();
}
catch(IOException e)
{}
}
}
public static void main(String[] args)
{
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();
}
方法
connect 连接管道输出流
参数
snk:要连接的管道输入流。
如果snk是未连接的管道输入流,而src是未连接的管道输出流,则可以通过src.connect(snk)或snk.connect(src),这两个调用具有相同的效果。
返回
无任何返回
异常
IOException:如果此对象已经连接到其他管道输入流,则抛出IOException。
FilterOutputStream
构造函数
public FilterOutputStream(OutputStream out)
out:分配给字段this.out以供以后使用的基础输出流;如果要在没有基础流的情况下创建此实例,则为null。
子类
FilterOutputStream是以下3个子类的父类:
- DataOutputStream是数据输出流,用来装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。
- BufferedOutputStream是缓冲输出流,它的作用是为另一个输出流添加缓冲功能。
- PrintStream是打印输出流,用来装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值。
总结
- FilterOutputStream继承了OutputStream大部分方法,是所有过滤输出流的基类,
- FilterOutputStream是过滤输出流的所有类的超类。这些流位于已存在的基础输出流之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。
DataOutputStream
DataOutputStream允许应用程序以与机器无关方式将Java基本数据类型(boolean,byte,int,long,string等)写到底层输出流。
public static void main(String[] args) throws IOException
{
FileOutputStream in = new FileOutputStream("c\\51gjie.txt");
DataOutputStream out = new DataOutputStream( in );
String string = "欢迎来到www.51gjie.com";
out.writeBytes(string);
out.writeChars(string);
out.writeUTF(string);
out.close();
System.out.println("写入成功!");
}
BufferedOutputStream
-
当创建BufferedOutputStream时,会创建一个内部缓冲区数组,应用程序可以向底层输出流写入字节数据,当写入数据时,可以不用每次都去调用底层方法,而是直接从缓存区获取数据。
-
BufferedOutputStream缓冲输出流在输出的时候,不是直接一个字节一个字节的操作,而是先写入内存的缓冲区内。直到缓冲区满了或者我们调用close方法或flush方法,该缓冲区的内容才会写入目标。才会从内存中转移到磁盘上,因此效率是非常高的。
public static void main(String[] args) throws IOException
{
OutputStream os = new FileOutputStream("c:/51gjie.txt");
OutputStream bs = new BufferedOutputStream(os);
byte[] buffer = "欢迎来到www.51gjie.com".getBytes();
bs.write(buffer);
bs.close();//写入文件
os.close();
}
如果文件太大,一次性读取这个大文件的所有数据,内存可能装不下,但是如果每次只读一个字节数据,会耗时太慢。因此用BufferedInputStream一次读取1024*8个字节数据,用BufferedOutputStream放入缓冲区,分批读写。代码如下:
public static void main(String[] args) throws IOException
{
BufferedInputStream bufferInput = null;
BufferedOutputStream bufferOutput = null;
try
{
// 输入缓冲流
InputStream input = new FileInputStream(new File("c:\\100MB.txt"));
bufferInput = new BufferedInputStream(input);
// 输出缓冲流
OutputStream output = new FileOutputStream(new File("c:\\100MB_test.txt"));
bufferOutput = new BufferedOutputStream(output);
// 定义个8kb字节数组,作为缓冲区流
byte[] bytes = new byte[1024 * 8];
int len = 0;
while((len = bufferInput.read(bytes)) != -1)
{
bufferOutput.write(bytes, 0, len);
}
}
catch(IOException e)
{
}
finally
{
try
{
if(bufferInput != null)
{
bufferInput.close();
}
if(bufferOutput != null)
{
bufferOutput.close();
}
}
catch(IOException e)
{
}
}
}
PrintStream
构造函数
public PrintStream(OutputStream out)
public PrintStream(OutputStream out,boolean autoFlush)
public PrintStream(OutputStream out,boolean autoFlush,String encoding)
public PrintStream(String fileName)
public PrintStream(String fileName,String csn)
public PrintStream(File file)
public PrintStream(File file,String csn)
out:要将值和对象打印到的输出流。
autoFlush:如果为true,则每当写入字节数组,调用println方法之一或写入换行符或字节(’\ n’)时,都会刷新输出缓冲区。
fileName:用作此打印流目标的文件名。 如果文件存在,那么它将被截断为零大小; 否则,将创建一个新文件。 输出将被写入文件并被缓冲。
csn:支持的字符集
PrintStream.print()也是打印数据,和println差不多,也可以输入java基本类型的数据,只不过是不会自动加上换行符。print和printin底层都是调用了write方法,基本上都差不多。
//追加数据到输出流
public PrintStream append(char c)
public PrintStream append(CharSequence csq,int start,int end)
public PrintStream append(CharSequence csq)
//关闭输出流
public void close()
//刷新输出流
public void flush()
例子
public static void main(String[] args)
{
PrintStream ps = null;
try
{
FileOutputStream fos = new FileOutputStream("G:/51gjie.txt");
ps = new PrintStream(fos);
}
catch(Exception e)
{
}
if(ps != null)
{
//将输出定向到文件
System.setOut(ps);
//系统打印用PS输出
System.out.println("hello www.51gjie.com");
}
}
- PrintStream流有自动刷新机制,例如当向PrintStream流中写入一个字节数组后自动调用flush()方法。
- PrintStream将基本的数据类型的数据或引用数据类型的对象格式化成字符串后再输出。使用该类不必书写转化成字符串的操作方法,可以直接输出。
- PrintStream可以通过setOut()改变System.out不用打印到控制台,而且转到其他媒介。
- PrintStream一般用得比较少,它能做的PrintWriter也都能实现,并且PrintWriter的功能更为强大,所以可以替代。
FileOutputStream
构造函数
public FileOutputStream(String name)
public FileOutputStream(File file)
public FileOutputStream(File file,boolean append)
public FileOutputStream(FileDescriptor fdObj)
file:要打开以进行写入的文件。append:是否往文件中添加数据。
实例:
public static void main(String[] args)
{
OutputStream fs = null;
try
{
StringBuffer buf = new StringBuffer();
buf.append("Hello JAVASCHOOL!").append("\r\n");
buf.append("Hello www.51gjie.com").append("\r\n");
fs = new FileOutputStream(new File("c:\\51gjie.txt"), true)
fs.write(buf.toString().getBytes())
}
catch(Exception e)
{}
finally
{
fs.close();
}
}
- FileOutputStream是文件字节输出流,它把内存中的数据写入到硬盘的文件中,一般用于向文件进行写入操作。
- FileOutputStream默认会覆盖原文件数据,如果要在文件后面添加数据,append一定要设置成true。
- 使用完流之后,要进行关闭,否侧会占用JVM的一定资源。
ObjectOutputStream
构造函数
public ObjectOutputStream?(OutputStream out)
public ObjectOutputStream?()
实例:
public static void main(String[] args) throws IOException
{
try
{
FileOutputStream fos = new FileOutputStream("c:\\51gjie.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(666);
oos.writeObject("hello");
oos.writeObject(new Date());
oos.close();
}
catch(Except e)
{}
}
-
ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
-
ObjectOutputStream一定是用来往输出流上写用户自定义的对象的,比如数据库中某表的一行数据对应一个对象,这时可通过这种方法存在硬盘上。
-
ObjectOutputStream将Java对象的原始数据类型写入OutputStream。可以使用ObjectInputStream读取(重新组合)对象。对象的持久存储可以通过使用流的文件来实现。如果流是网络套接字流,则可以在另一台主机上或在另一个进程中重建对象。
更多推荐
所有评论(0)