您的位置:首页 > 编程语言 > Java开发

JAVA I/O输入输出流详解

2015-11-13 16:24 471 查看
1、Java流的分类

a,按流向分:

输入流: 程序可以从中读取数据的流。

输出流: 程序能向其中写入数据的流。

b,按数据传输单位分:

字节流: 以字节为单位传输数据的流

字符流: 以字符为单位传输数据的流

c,按功能分:

节点流: 用于直接操作目标设备的流

过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

2、java.io常用类:

JDK所提供的所有流类位于java.io包中,都分别继承自以下四种抽象流类:

InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位)。

OutputSteam:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位)。

Reader:继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位)。

Writer:继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)。

3,Java中的流分为两种:

(1)字节流

表示以字节为单位从stream中读取或往stream中写入信息,即io包中的inputstream类和outputstream类的派生类。通常用来读取二进制数据,如图象和声音。

(2)字符流

以Unicode字符为导向的stream,表示以Unicode字符为单位从stream中读取或往stream中写入信息。

区别:

Reader和Writer要解决的,最主要的问题就是国际化。原先的I/O类库只支持8位的字节流,因此不可能很好地处理16位的Unicode字符流。Unicode是国际化的字符集(更何况Java内置的char就是16位的Unicode字符),这样加了Reader和Writer之后,所有的I/O就都支持Unicode了。此外新类库的性能也比旧的好。

但是,Read和Write并不是取代InputStream和OutputStream,有时,你还必须同时使用"基于byte的类"和"基于字符的类"。为此,它还提供了两个"适配器(adapter)"类。InputStreamReader负责将InputStream转化成Reader,而OutputStreamWriter则将OutputStream转化成Writer。

4,InputStream类

  inputstream类和outputstream类都为抽象类,不能创建对象,可以通过子类来实例化。

  InputStream是输入字节数据用的类,抽象了应用程序读取数据的方式.Inputstream类中的常用方法:

  1)public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。

  2)public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。该方法实际上是调用下一个方法实现的

  3)public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。

  4)public int available( ):返回输入流中可以读取的字节数。

  5)public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取。

  6)public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.。

5,OutputStream类

  OutputStream抽象了应用程序写出数据的方式,提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。

  1) public void write(byte b[ ]):将参数b中的字节写到输出流。

  2) public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。

  3) public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。

  4) public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。

  5) public void close( ) : 关闭输出流并释放与流相关的系统资源。

6,FileInputStream类

  FileInputStream类是InputStream类的子类,能够具体实现在文件上读取数据。使用方法:

  方式1:

  File fin=new File("d:/ab.txt");

  FileInputStream in=new FileInputStream(fin);

  方式2:

  FileInputStream in=new

  FileInputStream("d: /ab.txt");

  方式3:

  构造函数将 FileDescriptor()对象作为其参数。

  FileDescriptor() fd=new FileDescriptor();

  FileInputStream f2=new FileInputStream(fd);

7,FileOutputStream类

  FileOutputStream是OutputStream的一个重要子类,能够具体实现向文件中写出byte数据。

  创建文件流对象的方法:

  方式1:

  File f=new File("d:/abc.txt");

  FileOutputStream out=new FileOutputStream (f);

  方式2:

  FileOutputStream out=new

  FileOutputStream("d:/abc.txt");

  方式3:构造函数将 FileDescriptor()对象作为其参数。

  FileDescriptor() fd=new FileDescriptor();

  FileOutputStream f2=new FileOutputStream(fd);

方式4:构造函数将文件名作为其第一参数,将布尔值作为第二参数,表示若有此文件则内容追加。

  FileOutputStream f=new FileOutputStream("d:/abc.txt",true);

8,下面通过一个实例来详细讲解FileInputStream类和FileOutputStream类的使用。FileInputStream类的代码:

package cn.edu.io;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

public class IOUtil {

/*

* 单字节读取

* 读取指定文件内容,按照16进制输出到控制台

* 并且没输出10个byte换行

*/

public static void printHex(String fileName)throws IOException{

//把文件作为字节流进行读操作

FileInputStream in = new FileInputStream(fileName);

int b; //用来读

int i=1; //定义一个计数器

//当b读到-1时结束

while ((b=in.read())!=-1) {

//将整型b转换为16进制表示的字符串输出

System.out.print(Integer.toHexString(b)+" ");

//输出10个byte后换行

if (i++%10==0) {

System.out.println("");

}

}

//关闭数据流

in.close();

}

/*

* 批量读取

* 对大文件而言,读取效率高

*/

public static void printHexByByteArray(String fileName)throws IOException{

FileInputStream in=new FileInputStream(fileName);

//每次读取20 * 1024(20k)字节

byte[] buf=new byte[20 * 1024];

/*

* 从in中批量读取字节,放到buf这个字节数组中

* 从第0个位置开始放,最多放buf.length个

* 返回的是读到的字节的个数

*/

int bytes=in.read(buf, 0, buf.length);

int j = 1;

//这里是i < bytes,而不是i<buf.length,因为可能没有读满

for (int i = 0; i < bytes; i++) {

System.out.print(Integer.toHexString(buf[i])+" ");

if (j++%10==0) {

System.out.println();

}

}

in.close();

}

/*

* 读、写操作相结合,实现文件的拷贝功能

*/

public static void copyFile(File srcFile,File destFile)throws IOException{

//判断目标文件是否存在

if (!srcFile.exists()) {

throw new IllegalArgumentException("文件"+srcFile+"不存在");

}

//判断目标文件是不是文件

if (!srcFile.isFile()) {

throw new IllegalArgumentException(srcFile+"不是文件");

}

//创建FileInputStream对象,并把目标文件(srcFile)传进去

FileInputStream in=new FileInputStream(srcFile);

//创建FileOutputStream对象,并把复制文件(destFile)传进去,若没有,则新建

FileOutputStream out=new FileOutputStream(destFile);

//批量读写

byte[] buf=new byte[8 * 1024];

int b;

//先把文件从目标文件中取出,然后写入到复制文件中

while ((b=in.read(buf, 0, buf.length))!=-1) {

out.write(buf, 0, b);

out.flush(); //最好写上

}

in.close();

out.close();

}

}

9,FileOutputStream类的代码:

package cn.edu.io;

import java.io.FileOutputStream;

import java.io.IOException;

public class FileOutDemo {

public static void main(String[] args)throws IOException {

// 如果该文件不存在,则直接创建,如果存在,则删除后创建

FileOutputStream out=new FileOutputStream("D:\\EclipseWorkspaces\\IODemo\\src\\io\\1.txt");

// 下面这种两个参数的,如果该文件不存在,则直接创建,如果存在,则在后面追加

//FileOutputStream out=new FileOutputStream("demo/out.dat",true );

out.write('A');//写出了'A'的低8位

out.write('B');

int a=10;

//write只能写8位,那么写一个int型数据需要写4次,每次8位

out.write(a>>24);

out.write(a>>16);

out.write(a>>8);

out.write(a);

//写入自定义类型的数据

byte[] c="中国".getBytes("gbk");

out.write(c);

out.close();

IOUtil.printHex("D:\\EclipseWorkspaces\\IODemo\\src\\io\\1.txt");

//打开指定的目录,会发现写入了“A B 中国”

}

}

10,测试代码(我这里测试的为D盘下的一个java代码):

package cn.edu.io;

import java.io.File;

import java.io.IOException;

public class IOUtilTest {

public static void main(String[] args) {

/*

* 测试单字节读取文件内容

* 并打印出读取文件用的时间

*/

// try {

// long start=System.currentTimeMillis();

// IOUtil.printHex("D:\\EclipseWorkspaces\\Actor\\src\\concurrent\\Actor.java");

// long end=System.currentTimeMillis();

// System.out.println("读取文件用时:"+(end-start)+"ms");

// } catch (IOException e) {

// e.printStackTrace();

// }

/*

* 测试批量读取指定文件

* 并打印出读取文件用的时间

*/

// try {

// long start=System.currentTimeMillis();

// IOUtil.printHexByByteArray("D:\\EclipseWorkspaces\\Actor\\src\\concurrent\\Actor.java");

// long end=System.currentTimeMillis();

// System.out.println("读取文件用时:"+(end-start)+"ms");

// } catch (IOException e) {

// e.printStackTrace();

// }

/*

* 测试拷贝数据

*/

try {

IOUtil.copyFile(new File("D:\\EclipseWorkspaces\\IODemo\\src\\io\\1.txt"),new
File("D:\\EclipseWorkspaces\\IODemo\\src\\io\\2.txt"));

} catch (IOException e) {

e.printStackTrace();

}

//结果:在1.txt下面又多了一个文件2.txt.

}

}

说明:三个测试代码写在了一个main函数中了,测试其中一个时,需把其他两个注释掉,如上。

测试批量读取文件的部分结果为:

74 65 6d 2e 6f 75 74 2e 70 72

69 6e 74 6c 6e 28 54 68 72 65

61 64 2e 63 75 72 72 65 6e 74

54 68 72 65 61 64 28 29 2e 67

65 74 4e 61 6d 65 28 29 2b 22

a 9 7d d a 9 d a 7d d

a 读取文件用时:26ms
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: