IO流

来源:互联网 发布:网络同传多台机器变慢 编辑:程序博客网 时间:2024/05/22 17:39

一、概念:数据流是一组有顺序的、有起点和终点的字节集合,输入输出过程中传递的数组
组成数据流。从数据流中读取数据时,必须有一个数据源和该数据流相连

IO流的分类:
1)根据数据类型不同分为:字符流和字节流
字符流:
字节流:
2)根据数据流的方向分为:输入流和输出流

Java的输入流主要有InputStream和Reader作为基类,而输出流主要由OutputStream作为基类。

二、常用的基本类
字符流,用于操作字符,针对纯文本文件
1.两个抽象基类:Writer 和 Reader,
2.FileWriter 和 FileReader 其中提高了一些读写方法,可以单个字符读取写入也,也可以以数组的形式读取写入,
由于流的操作涉及到系统资源,所以要处理异常,及关闭资源
例如://数组读写
public static void copy_1()
{ //穿件两个流对象变量
FileWriter fw = null;
FileReader fr = null;
try
{ //关联需要读写的文件
fw = new FileWriter("SystemDemo_copy.txt");
fr = new FileReader("SystemDemo.java");
//定义数组,接收读到数据
char[] buf = new char[1024];

int len = 0;
while((len=fr.read(buf))!=-1)
{ //将数组中的数据写入流
fw.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(fr!=null)
try
{ //关闭读取流
fr.close();
}
catch (IOException e)
{
}
if(fw!=null)
try
{ //关闭写入流
fw.close();
}
catch (IOException e)
{
}
}
}

//字符读写
public static void copy_1()throws IOException//异常抛出
{
//创建目的地。
FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");

//与已有文件关联。
FileReader fr = new FileReader("RuntimeDemo.java");
//定义变量接收所读字符
int ch = 0;

while((ch=fr.read())!=-1)
{
fw.write(ch);
}

fw.close();
fr.close();

}

三、Java流分类:

字符流:Reader 和 Writer
字符流:
操作文件:FileReader、FilterWriter
操作数组:CharArrayReader、CharArrayWriter
操作管道:PipeReader、PipedWriter
缓 冲 流:BufferedReader、 BufferedWriter
字符串流:StringReader、StringWriter
转 换流:InputStreamReader(字节到字符的桥梁)、OutputStreamWriter(字符到字节的桥梁)
打 印 流:PrintWriter

字节流:InputStream 和 OutputStream
字节流:
操作文件:FileInputStream、FileOutputStream
操作数组:ByteArrayInputStream、ByteArrayOutputStream
操作管道:PipedInputStream、PipedOutputStream
缓 冲 流:BufferedInputStream、BufferedOutputStream
对 象 流:ObjectInputStream、ObjectOutputStream
数 据 流:DataInputStream、DataOutputStream
推 回 流:PushbackInputStream
打 印 流:PrintStream

注意:
1、使用Java的IO流执行输出时,不要忘记了关闭输出流,关闭输出流除了可以保证
流的物理资源被回收之外,可能还可以将输出缓冲流中的数据flush到物理节点理。
流的用法。
2、当我们使用处理流来包装底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的
处理流即可,关闭最上层的处理流时,系统会自动关闭被该处理包装的节点流。

1)文件流
FileWriter:
1、flush和close()的区别:
flush:是将缓冲区里面的数据强制输出到文件中去,也就是清空缓冲区,但是

文件流还没有关闭,可以继续使用。
close:是将流资源关闭,关闭之后,流将再也不能使用,也不能flush了。但是

在关闭之前它会将数据flush到文件中去。
2、window系统中的回车换行符时"\r\n",但是在Linux系统中的回车换行符却是'\n'。
3、当我们往一个文件写数据的时候,要将缓冲区flush一下,这样数据才能写入到文件中。
FileReader:
1、创建一个文件读取流对象时,要保证该文件存入,如果不存在将会抛出FileNotFoundException。
2、调用读取方法时,当返回的值为-1的时候,表示已经读到文件的结尾了,所以我们就可以将这个-1来作为文件结束的标志。
FileInputStream:
FileInputStream的三种读取方式:
1、利用循环一个一个字节的读取while((int ch = read())!=-1)
2、在文件比较小的时候(小于64M,也就是虚拟机默认的内存空间),利用开辟一个字节数组,长度为available。
3、利用循环将数据读到一个字节数组中,byte buf = new byte[n] while((int ien=read(buf))!=-1)
三种读取方式的优缺点:
第一种方式:不能读取文件中的中文,因为中文是由两个字节组成的。而且读取效率又是非常的低。
第二种方式:在文件不大的情况下,我们是用buf[available],可以将文件中的数据刚刚好的放在

一个字节数组中,不用去循环了,这样既节省了大量的空间,而且还可以提高读取的效率,

但是遇到大文件是行不通的。非常方便用于读取文本文件之类的。
第三种方式:这种方式是最好的,即使遇到了大文件也没有关系。但是数组的空间长度要划分的合

理,这样的话可以节省空间。
注意:当我们在使用FileInputStream时,如果没有对应的文件的话,那么将会抛出异常,所以在调用此流时要保证有文件存在。
FileOutputStream:
1、用法:用于写入诸如图像数据之类的原始字节的流
2、主要的方法:
1)void write(byte b):将 b.length 个字节从指定 byte 数组写入此文件输出流中。
2)void write(byte[] b,int off,int len): 将指定 byte 数组中从偏移量 off 开始的

len 个字节写入此文件输出流。
3)void write(int b):将指定字节写入此文件输出流。
FileOutputStream和FileInputStream代码演示:
public class CopyMediaFile{
  private FileInputStream fis;
  private FileOutputStream fos;
public static void main(String[] args)throws IOException{
  CopyMediaFile cmd = new CopyMediaFile();
cmd.CopyPic();
cmd.CopyMusic();
cmd.CopyFile();
}
//将D盘下的Test.jpg拷贝到当前目录下。
public void CopyPic()throws IOException
{
fos = new FileOutputStream("copy_test.jpg");
fis = new FileInputStream("D:\\Test.jpg");
byte buf[] = new byte[1024];
int len = 0;
while((len = fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fis.close();
fos.close();
}
//将D盘下的Test.wma拷贝到当前目录下。
public void CopyMusic()throws IOException{
fos = new FileOutputStream("copy_test.wma");
fis = new FileInputStream("D:\\Test.wma");
int len = fis.available();
byte buf[] = new byte[len];
fos.write(buf,0,len);
fis.close();
fos.close();
}
//将D盘下的Test.txt拷贝到当前目录下。
public void CopyFile()throws IOException{
fos = new FileOutputStream("copy_test.txt");
fis = new FileInputStream("D:\\Test.txt");
byte buf[] = new byte[1024];
int len = 0;
while((len = fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fis.close();
fos.close();
}
}
2)缓冲流:
BufferedReader:
1、从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
2、该流提供了一个方法String readLine(),用于读取文件中的一行数据;当读取到文件末尾时,返回一个空。
3、readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
4、readLine的原理:无论是读取一行还是读取多个字符,其实都是在硬盘上一个一个读取,它底层还是利用read()方法一个一个的读取的。
BufferedWriter:
1、将文本写入字符输出流中,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
2、在创建缓冲区之前,必须要先有流对象,否则将会报异常。
3、write("\r\n");只能用在windows操作系统上的换行,在别的系统上不一定是回车换行符,但是Java提供了newLine()跨平台的换行。
4、只要用到了缓冲区,就要记得刷新一下。
5、主要方法:
write(char[] buf,int off,int len)写入字符数组的某一部分
write(String s,int off,int len)写入字符串的某一部分。
newLine()写入一个行分隔符
write(int c)写入单个字符
3)数组流:
ByteArrayStream--->字节数组流对象
注意:该流对象没有调用底层资源,所以关闭此流是无效的,
此类中的方法在关闭此流后仍可被调用的,而不会产生任何IOException
ByteArrayInputStream:在构造的时候,需要接收数据源。而且数据源是一个字节数组
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了

可变长度的字节数组。
简单代码演示:
public class ByteArrayStreamDemo{
  public static void main(String[] args){
//创建数据源
ByteArrayInputStream bis = new ByteArrayInputStream("我来了。".getBytes());
//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch = 0;
while((ch = bis.read())!=-1){
bos.write(ch);
}
  System.out.println(bos.size());
System.out.println(bos.toString());
}
}
4)打印流:
PrintStream:
1、这是一个字节打印流它为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
2、永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。
3、为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,
可调用其中一个 println 方法,或写入一个换行符或字节 ('\n')。
PrintWriter:
1、与 PrintStream 类不同,如果启用了自动刷新,则只有在调用println、printf或format的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。
2、此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用 checkError() 是否出现错误。
5)序列流:
SequenceInputStream:
定义:表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾, 接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
主要的的构造方法:
SequenceInputStream(Enumeration<? extends InputStream> e)
--->通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成

运行时类型为InputStream 对象的 Enumeration 型参数。
  SequenceInputStream(InputStream s1,InputStream s2)
--->通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,
先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
代码演示:
public static void main(String[] args) throws IOException{
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] buf = new byte[1024];
  int len =0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
  fos.close();
  sis.close();
}


 

 

原创粉丝点击