Java IO 基本知识

在Java中,我们把能够读取一个字节序列的对象称作一个输入流;而我们把够写一个字节序列称作一个输出流。它们分别由抽象类
InputStream和OutputStream类表示。因为面向字节的流不方便用来处理存储为Unicode(每个字符使用两个字节)的信息。所以Java
引入了用来处理Unicode字符的类层次,这些类派生自抽象类Reader和Writer,它们用于读写双字节的Unicode字符,而不是单字节字符。
Java.io包简介
JDK标准帮助文档是这样解释Java.io包的,通过数据流、序列和文件系统为系统提供输入输出。
InputStream类和OutputStream类
InputStream类是所有输入数据流的父类,它是一个抽象类,定义了所有输入数据流都具有的共通特性。
java.io.InputStream的方法如下:
public abstract read()throws IOException
读取一个字节并返回该字节,如果到输入源的末则返回-1。一个具体的输入流类需要重载此方法,以提供 有用的功能。例如:在FileInputStream类中,该方法从一个文件读取一个字节。
public int read(byte[] b)throws IOException
把数据读入到一个字节数据中,并返回实际读取的字节数目。如果遇到流末 则返回-1,该方法最多读取b.length个字节。
public abstract int read(byte[] b,int off,int len)throws IOException
把数据读入到一个字节数组中并返回实际读取的字节数目。如果遇到流的末尾则的返回-1。 其中参数off表示第一个字节在b中的位置,len表示读取的最大字节数。
public long skip(long n)throws IOException
略过N个字节不读取,会返回实际略过的字节数目。因为数据流中剩下的数据可能不到N 个字节那么多,所以此时返回值会小于N。
public int available()throws IOException
read方法(包括后面要讲的OutputStream类的Write方法)都能够阴塞一个线程,直到字节被 实际读取或写入。这意味着如果一个流不能立即被读或被写
/**/ /*
* Created on 2005-3-10
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/

package mytestfiles;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**/ /**
* @author zhangqinglin
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/

public class Files
... {
public static void main(String[] args) throws IOException
...{
Files f
= new Files();
// System.out.println(f.readFile("f:/LinkFile.java"));
// f.readAllFile("f:/","LinkFile.java");
// f.readLineFile("f:/","LinkFile.java");
// System.out.println(f.fileIsNull("f:/","122.txt"));
// f.readFolderByFile("F:/PDF");
// System.out.println(f.createAndDeleteFolder("ss","f:/"));
// System.out.println(f.createAndDeleteFile("f:/ss/","TestFile.dat"));
String[] ss = new String[50];
for(int i=0;i<ss.length;i++)
...{
ss[i]
= "信息技术和互联网(计算机软硬件,通讯) "+i;
}

f.writeFile(
"f:/ss/","TestFile.txt",ss);
}

/**//**
* 文件的写入
* @param filePath(文件路径)
* @param fileName(文件名)
* @param args[]
* @throws IOException
*/

public void writeFile(String filePath,String fileName,String[] args) throws IOException
...{
FileWriter fw
= new FileWriter(filePath+fileName);
PrintWriter
out=new PrintWriter(fw);
for(int i=0;i<args.length;i++)
...{
out.write(args[i]);
out.println();
out.flush();
}

fw.close();
out.close();
}

/**//**
* 文件的写入
* @param filePath(文件路径)
* @param fileName(文件名)
* @param args
* @throws IOException
*/

public void writeFile(String filePath,String fileName,String args) throws IOException
...{
FileWriter fw
= new FileWriter(filePath+fileName);
fw.write(args);
fw.close();
}

/**//**
* 创建与删除文件
* @param filePath
* @param fileName
* @return 创建成功返回true
* @throws IOException
*/

public boolean createAndDeleteFile(String filePath,String fileName) throws IOException
...{
boolean result
= false;
File file
= new File(filePath,fileName);
if(file.exists())
...{
file.delete();
result
= true;
System.
out.println("文件已经删除!");
}

else
...{
file.createNewFile();
result
= true;
System.
out.println("文件已经创建!");
}

return result;
}

/**//**
* 创建和删除目录
* @param folderName
* @param filePath
* @return 删除成功返回true
*/

public boolean createAndDeleteFolder(String folderName,String filePath)
...{
boolean result
= false;
try
...{
File file
= new File(filePath+folderName);
if(file.exists())
...{
file.delete();
System.
out.println("目录已经存在,已删除!");
result
= true;
}

else
...{
file.mkdir();
System.
out.println("目录不存在,已经建立!");
result
= true;
}

}

catch(Exception ex)
...{
result
= false;
System.
out.println("CreateAndDeleteFolder is error:"+ex);
}

return result;
}

/**//**
* 输出目录中的所有文件及目录名字
* @param filePath
*/

public void readFolderByFile(String filePath)
...{
File file
= new File(filePath);
File[] tempFile
= file.listFiles();
for(int i = 0;i<tempFile.length;i++)
...{
if(tempFile[i].isFile())
...{
System.
out.println("File : "+tempFile[i].getName());
}

if(tempFile[i].isDirectory())
...{
System.
out.println("Directory : "+tempFile[i].getName());
}

}

}

/**//**
* 检查文件中是否为一个空
* @param filePath
* @param fileName
* @return 为空返回true
* @throws IOException
*/

public boolean fileIsNull(String filePath,String fileName) throws IOException
...{
boolean result
= false;
FileReader fr
= new FileReader(filePath+fileName);
if(fr.read() == -1)
...{
result
= true;
System.
out.println(fileName+" 文件中没有数据!");
}

else
...{
System.
out.println(fileName+" 文件中有数据!");
}

fr.close();
return result;
}

/**//**
* 读取文件中的所有内容
* @param filePath
* @param fileName
* @throws IOException
*/

public void readAllFile(String filePath,String fileName) throws IOException
...{
FileReader fr
= new FileReader(filePath+fileName);
int count = fr.read();
while(count != -1)
...{
System.
out.print((char)count);
count
= fr.read();
if(count == 13)
...{
fr.skip(
1);
}

}

fr.close();
}

/**//**
* 一行一行的读取文件中的数据
* @param filePath
* @param fileName
* @throws IOException
*/

public void readLineFile(String filePath,String fileName) throws IOException
...{
FileReader fr
= new FileReader(filePath+fileName);
BufferedReader br
= new BufferedReader(fr);
String line
= br.readLine();
while(line != null)
...{
System.
out.println(line);
line
= br.readLine();
}

br.close();
fr.close();
}

}

 

stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。在Java的IO中,所有的stream(包括Inputstream和Out stream)都包括两种类型:
(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。

一.流的层次结构

定义:

(1)       java将读取数据对象成为输入流,能向其写入的对象叫输出流。结构图如下:输入流:

输出流

二.InputStream

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

InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.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( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,

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

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

三.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( ) : 关闭输出流并释放与流相关的系统资源。

注意:

1. 上述各方法都有可能引起异常。

2.  InputStream和OutputStream都是抽象类,不能创建这种类型的对象。 

四.FileInputStream类

FileInputStream类是InputStream类的子类,用来处理以文件作为数据输入源的数据流。使用方法:

方式1:

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

FileInputStream  in=new FileInputStream(fin);

方式2:

FileInputStream  in=new

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

方式3:

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

FileDescriptor() fd=new FileDescriptor();

FileInputStream f2=new FileInputStream(fd);

五.FileOutputStream类

FileOutputStream类用来处理以文件作为数据输出目的数据流;一个表示文件名的字符串,也可以是File或FileDescriptor对象。

创建一个文件流对象有两种方法:

方式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);

注意:

(1)文件中写数据时,若文件已经存在,则覆盖存在的文件;(2)的读/写操作结束时,应调用close方法关闭流。

举例:2-1

六.File类

File类与InputStream / OutputStream类同属于一个包,它不允许访问文件内容。

File类主要用于命名文件、查询文件属性和处理文件目录。

举例:2-2

七.从一个流构造另一个流

java的流类提供了结构化方法,如,底层流和高层过滤流。

而高层流不是从输入设备读取,而是从其他流读取。同样高层输出流也不是写入输出设备,而是写入其他流。

使用"分层对象(layered objects)",为单个对象动态地,透明地添加功能的做法,被称为Decorator Pattern。Decorator模式要求所有包覆在原始对象之外的对象,都必须具有与之完全相同的接口。这使得decorator的用法变得非常的透明--无论对象是否被decorate过,传给它的消息总是相同的。这也是Java I/O类库要有"filter(过滤器)"类的原因:抽象的"filter"类是所有decorator的基类。Decorator模式常用于如下的情形:如果用继承来解决各种需求的话,类的数量会多到不切实际的地步。Java的I/O类库需要提供很多功能的组合,于是decorator模式就有了用武之地。

为InputStream和OutputStream定义decorator类接口的类,分别是FilterInputStream和FilterOutputStream。

7.1 FilterInputStream

 

FilterInputStream的种类

功能

构造函数的参数

用法

DataInputStream

与DataOutputStream配合使用,这样你就能以一种"可携带的方式(portable fashion)"从流里读取primitives了(int,char,long等)

InputStream

包含了一整套读取primitive数据的接口。

BufferedInputStream

用这个类来解决"每次要用数据的时候都要进行物理读取"的问题。你的意思是"用缓冲区。"

InputStream,以及可选的缓冲区的容量

它本身并不提供接口,只是提供一个缓冲区。需要连到一个"有接口的对象(interface object)"。

LineNumberInputStream

跟踪输入流的行号;有getLineNumber( )和setLineNumber(int)方法

InputStream

只是加一个行号,所以还得连一个"有接口的对象"。

PushbackInputStream

有一个"弹压单字节"的缓冲区(has a one byte push-back buffer),这样你就能把最后读到的那个字节再压回去了。

InputStream

主要用于编译器的扫描程序。可能是为支持Java的编译器而设计的。用的机会不多。

 

FilterOutputStream的种类

功能

构造函数的参数

用法

DataOutputStream

与DataInputStream配合使用,这样你就可以用一种"可携带的方式(portable fashion)"往流里写primitive了(int, char, long,等)

OutputStream

包括写入primitive数据的全套接口。

PrintStream

负责生成带格式的输出(formatted output)。DataOutputStrem负责数据的存储,而PrintStream负责数据的显示。

一个OutputStream以及一个可选的boolean值。这个boolean值表示,要不要清空换行符后面的缓冲区。

应该是OutputStream对象的最终包覆层。用的机会很多。

BufferedOutputStream

用 这个类解决"每次往流里写数据,都要进行物理操作"的问题。也就是说"用缓冲区"。用flush( )清空缓冲区。

OutputStream, 以及一个可选的缓冲区大小

本身并不提供接口,只是加了一个缓冲区。需要链接一个有接口的对象。

DataInputStream类对象可以读取各种类型的数据。

DataOutputStream类对象可以写各种类型的数据;

创建这两类对象时,必须使新建立的对象指向构造函数中的参数对象。例如:

FileInputStream in=new FileInputStream("d:/abc.txt");

DataInputStream  din=new DataInputStream(in);

7.2BufferInputStreambufferOutputStream

允许程序在不降低系统性能的情况下一次一个字节的从流中读取数据。

BufferInputstream定义了两种构造函数

(1)       BufferInputStream  b= new BufferInputstream(in);

(2)       BufferInputStream b=new BufferInputStream(in,size)

第二个参数表示指定缓冲器的大小。

同样BufferOutputStream也有两种构造函数。一次一个字节的向流中写数据。

7.3printstream

用于写入文本或基本类型

两种构造函数方法:

PrintStream ps=new PrintStream(out);

PrintStream ps=new PrintStream(out, autoflush)

第二个参数为布尔值,控制每次输出换行符时java是否刷新输出流。

八.字符流的读取和写入

java.io.Reader java.io.InputStream 组成了Java 输入类。Reader 用于读入16位字符,也就是Unicode 编码的字符;而 InputStream 用于读入ASCII 字符和二进制数据。
Reader
的体系结构

 

(1)       FileReader

   FileReader主要用来读取字符文件,使用缺省的字符编码,有三种构造函数:

  --将文件名作为字符串

   FileReader f=new FileReader(“c:/temp.txt”);

--构造函数将File对象作为其参数。

  File f=new file(“c:/temp.txt”);

FileReader f1=new FileReader(f);

--构造函数将FileDescriptor对象作为参数

FileDescriptor() fd=new FileDescriptor()

FileReader f2=new FileReader(fd);

(2)    charArrayReader

  将字符数组作为输入流,构造函数为:

public CharArrayReader(char[] ch);

(3)    StringReader

  读取字符串,构造函数如下:

public StringReader(String s);

(4)    InputStreamReader

从输入流读取字节,在将它们转换成字符。

Public inputstreamReader(inputstream is);

(5)    FilterReader

允许过滤字符流

protected filterReader(Reader r);

(6)    BufferReader

  接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。

Public BufferReader(Reader r);

Writer类体系结构

 

(1)       FileWrite

   将字符类型数据写入文件,使用缺省字符编码和缓冲器大小。

Public FileWrite(file f);

(2)chararrayWrite()

   将字符缓冲器用作输出。

  Public CharArrayWrite();

(3)    PrintWrite

  生成格式化输出

public PrintWriter(outputstream os);

(4)    filterWriter

  用于写入过滤字符流

protected FilterWriter(Writer w);

 

FilterOutputStream的种类

功能

构造函数的参数

用法

DataOutputStream

与DataInputStream配合使用,这样你就可以用一种"可携带的方式(portable fashion)"往流里写primitive了(int, char, long,等)

OutputStream

包括写入primitive数据的全套接口。

PrintStream

负责生成带格式的输出(formatted output)。DataOutputStrem负责数据的存储,而PrintStream负责数据的显示。

一个OutputStream以及一个可选的boolean值。这个boolean值表示,要不要清空换行符后面的缓冲区。

应该是OutputStream对象的最终包覆层。用的机会很多。

BufferedOutputStream

用 这个类解决"每次往流里写数据,都要进行物理操作"的问题。也就是说"用缓冲区"。用flush( )清空缓冲区。

OutputStream, 以及一个可选的缓冲区大小

本身并不提供接口,只是加了一个缓冲区。需要链接一个有接口的对象。

DataInputStream类对象可以读取各种类型的数据。

DataOutputStream类对象可以写各种类型的数据;

创建这两类对象时,必须使新建立的对象指向构造函数中的参数对象。例如:

FileInputStream in=new FileInputStream("d:/abc.txt");

DataInputStream  din=new DataInputStream(in);

7.2BufferInputStreambufferOutputStream

允许程序在不降低系统性能的情况下一次一个字节的从流中读取数据。

BufferInputstream定义了两种构造函数

(1)       BufferInputStream  b= new BufferInputstream(in);

(2)       BufferInputStream b=new BufferInputStream(in,size)

第二个参数表示指定缓冲器的大小。

同样BufferOutputStream也有两种构造函数。一次一个字节的向流中写数据。

7.3printstream

用于写入文本或基本类型

两种构造函数方法:

PrintStream ps=new PrintStream(out);

PrintStream ps=new PrintStream(out, autoflush)

第二个参数为布尔值,控制每次输出换行符时java是否刷新输出流。

八.字符流的读取和写入

java.io.Reader java.io.InputStream 组成了Java 输入类。Reader 用于读入16位字符,也就是Unicode 编码的字符;而 InputStream 用于读入ASCII 字符和二进制数据。
Reader
的体系结构

 

(1)       FileReader

   FileReader主要用来读取字符文件,使用缺省的字符编码,有三种构造函数:

  --将文件名作为字符串

   FileReader f=new FileReader(“c:/temp.txt”);

--构造函数将File对象作为其参数。

  File f=new file(“c:/temp.txt”);

FileReader f1=new FileReader(f);

--构造函数将FileDescriptor对象作为参数

FileDescriptor() fd=new FileDescriptor()

FileReader f2=new FileReader(fd);

(2)    charArrayReader

  将字符数组作为输入流,构造函数为:

public CharArrayReader(char[] ch);

(3)    StringReader

  读取字符串,构造函数如下:

public StringReader(String s);

(4)    InputStreamReader

从输入流读取字节,在将它们转换成字符。

Public inputstreamReader(inputstream is);

(5)    FilterReader

允许过滤字符流

protected filterReader(Reader r);

(6)    BufferReader

  接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。

Public BufferReader(Reader r);

Writer类体系结构

 

(1)       FileWrite

   将字符类型数据写入文件,使用缺省字符编码和缓冲器大小。

Public FileWrite(file f);

(2)chararrayWrite()

   将字符缓冲器用作输出。

  Public CharArrayWrite();

(3)    PrintWrite

  生成格式化输出

public PrintWriter(outputstream os);

(4)    filterWriter

  用于写入过滤字符流

protected FilterWriter(Writer w);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值