“Java的IO类”的版本间的差异

来自CloudWiki
跳转至: 导航搜索
(创建页面,内容为“==IO流的概念== ===流=== 流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以…”)
 
 
第18行: 第18行:
 
(1) 字节流:数据流中最小的数据单元是字节。
 
(1) 字节流:数据流中最小的数据单元是字节。
 
(2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
 
(2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
== 二进制I/O ==
 
  
(1)InputStream和OutputStream
+
返回 [[Java程序设计]]
 
 
InputStream和OutputStream是字节流的两个顶层父类,提供了输入流类与输出流类的通用API。如图6-10所示列出了一些实现二进制I/O的类。
 
 
 
[[文件:java6-10.png]]
 
 
 
图6-10 二进制I/O类
 
 
 
InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法。Inputstream类中的常用方法如表6-3所示。
 
 
 
表6-3 Inputstream类常用方法
 
<nowiki>方法名 说明
 
public abstract int read( ) 读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
 
public int read(byte b[ ]) 读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的
 
public int read(byte b[ ], int off, int len) 从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。
 
public int available( ) 返回输入流中可以读取的字节数。注意若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,
 
public long skip(long n) 忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取
 
public int close( ) 我们在使用完后,必须对我们打开的流进行关闭.</nowiki>
 
 
 
OutputStream是输出字节数据用的类,它提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。OutputStream常用方法如表6-4所示。
 
 
 
表6-4 Outputstream类常用方法
 
 
 
<nowiki>方法名 说明
 
public void write(byte b[ ]) 将参数b中的字节写到输出流。
 
public void write(byte b[ ], int off, int len) 将参数b的从偏移量off开始的len个字节写到输出流。
 
public abstract void write(int b) 先将int转换为byte类型,把低字节写入到输出流中。
 
public void flush( ) 将数据缓冲区中数据全部输出,并清空缓冲区。
 
public void close( ) 关闭输出流并释放与流相关的系统资源。</nowiki>
 
 
 
(2)FileInputStream和FileOutputStream
 
 
 
FileInputStream类和FileOutputStream类用于从/向文件读取/写入字写。他们的方法都是从InputStream类和OutputStream类继承的。
 
 
 
FileInputStream类和FileOutputStream类没有引入新的方法。FileInputStream类构造方法如表6-5所示。
 
 
 
表6-5 FileInputStream类构造方法
 
 
 
<nowiki>方法名 说明
 
FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
 
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。</nowiki>
 
 
 
【注意】如果试图为一个不存在的文件创建FileInputStream对象,将会发生java.io.NotFoundException异常。
 
 
 
要构造FileOutputStream对象,使用如表6-6所示的构造方法。
 
 
 
表6-6 FileOutputStream类常用方法
 
 
 
<nowiki>方法名 说明
 
FileOutputStream(File file) 使用File对象创建文件输出流对象,如果文件打开失败,将抛出异常。
 
FileOutputStream(String name) 直接使用文件名或路径创建文件输出流对象。
 
FileOutputStream(File file, boolean append) 使用File对象创建文件输出流对象,并由参数append指定是否追加文件内容,true为追加,false为不追加。
 
FileOutputStream(String name, boolean append) 直接使用文件名或路径创建文件输出流对象,并由参数append指定是否追加。
 
如果这个文件不存在,就会创建一个新的文件,如果这个文件已经存在,前两个构造方法会删除文件的当前内容。为了在文件内容基础上追加新数据,需要采用后两种构造方法,并将append设置为true。</nowiki>
 
 
 
(3) 输入输出流的操作步骤
 
 
 
#使用引入语句引入java.io包:import java.io.*;
 
#根据不同数据源和输入输出任务,建立字节流或字符流对象;
 
#若需要对字节或字符流信息组织加工为数据,在已建字节流或字符流对象上构建数据流对象。
 
#用输入输出流对象类的成员方法进行读写操作,需要时,设置读写位置指针。
 
#关闭流对象。
 
 
 
几乎所有的I/O类中的方法都会抛出异常java.io.IOExcepton。因此,必须在方法中声明会抛出java.io.IOExcepton异常,或将代码放到try-catch块中。
 
 
 
下面程序,使用二进制I/O完成了文件的复制。
 
 
 
<nowiki>public static void main(String[] args) throws IOException {
 
File srcFile = new File("cache/01_cache.txt"); // 源文件对象
 
File destFile = new File("src/desc.txt"); // 目标文件对象
 
// 使用源文件对象创建文件输入流对象
 
FileInputStream fis = new FileInputStream(srcFile);
 
// 使用目标文件对象创建文件输出流对象
 
FileOutputStream fos = new FileOutputStream(destFile);
 
int hasRead = 0;// 读取字节长度
 
byte[] buf = new byte[1024]; // 创建字节数组,作为临时缓冲
 
System.out.println("开始复制文件...");
 
while ((hasRead = fis.read(buf)) != -1) { // 循环从文件输入流中读取数据
 
if (hasRead < 1024)//读取长度<数组长度,复制读取内容
 
fos.write(Arrays.copyOf(buf, hasRead));
 
else
 
fos.write(buf);
 
}
 
System.out.println("文件复制成功!");
 
fis.close(); // 关闭流
 
fos.close();
 
}</nowiki>
 
 
 
(4) 使用try-with-resource自动关闭资源。
 
 
 
在编写IO操作时经常会忘记关闭IO流,JDK7提供了新的try-with-resource语法来自动关闭IO流,语法格式如下:
 
 
 
<nowiki>try(声明和创建资源){
 
使用资源来处理文件
 
}</nowiki>
 
 
 
使用try-with-resource语法,重写了复制文件程序中的代码:
 
 
 
<nowiki>public static void main(String[] args) throws IOException {
 
File srcFile = new File("cache/01_cache.txt"); // 源文件对象
 
File destFile = new File("src/desc.txt"); // 目标文件对象
 
// 使用源文件对象创建文件输入流对象
 
try (FileInputStream fis = new FileInputStream(srcFile);
 
// 使用目标文件对象创建文件输出流对象
 
FileOutputStream fos = new FileOutputStream(destFile)) {
 
int hasRead = 0;// 读取字节长度
 
byte[] buf = new byte[1024]; // 创建字节数组,作为临时缓冲
 
System.out.println("开始复制文件...");
 
while ((hasRead = fis.read(buf)) != -1) { // 循环从文件输入流中读取数据
 
if (hasRead < 1024)// 读取长度<数组长度,复制读取内容
 
fos.write(Arrays.copyOf(buf, hasRead));
 
else
 
fos.write(buf);
 
}
 
System.out.println("文件复制成功!");
 
}
 
}</nowiki>
 
 
 
【注意】当流不需要使用时,记得使用close()方法将其关闭,或者使用try-with-resource语句自动关闭。不关闭流可能会在输出文件中造成数据受损,或导致其他的程序设计错误。
 
 
 
(5)BufferedInputStream和BufferedOutputStream
 
 
 
BufferedInputStream和 BufferedOutputStream类可以通过减少磁盘读写次数来提高输入和输出的速度。
 
 
 
BufferedInputStream:当向缓冲流写入数据时候,数据先写到缓冲区,待缓冲区写满后,系统一次性将数据发送给输出设备,如图6-11所示。
 
 
 
[[文件:java6-11.png]]
 
 
 
图6-11 BufferedInputStream
 
 
 
若要创建一个BufferedOutputStream流对象,首先需要一个FileOutputStream流对象,然后基于这个流对象创建缓冲流对象。
 
 
 
BufferedOutputStream 类的构造方法如下:
 
 
 
BufferedOutputStream(OutputStream out)
 
BufferedOutputStream(OutputStream out, int size)
 
 
 
下面程序,使用BufferedOutputStream把内容写入到文件buffer.txt中。
 
<nowiki>public static void main(String[] args) throws IOException {
 
try (FileOutputStream fos = new FileOutputStream("buffer.txt");
 
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
 
String str = "hello world";
 
bos.write(str.getBytes());
 
}
 
}</nowiki>
 
 
 
BufferedOutputStream:当向缓冲流读取数据时候,系统先从缓冲区读出数据,待缓冲区为空时,系统再从输入设备读取数据到缓冲区,如图6-12所示。
 
 
 
[[文件:java6-12.png]]
 
图6-12 BufferedOutputStream
 
 
 
若要创建一个BufferedInputStream流对象,需要一个FileInputStream流对象,然后基于这个流对象创建缓冲流对象。BufferedInputStream类的构造方法如下:
 
 
 
*BufferedInputStream(InputStream in)
 
*BufferedInputStream(InputStream in, int size)
 
 
 
下面程序,使用BufferedInputStream把读取并打印文件buffer.txt中内容。
 
 
 
<nowiki>public static void main(String[] args) throws  IOException {
 
try(FileInputStream fis=new FileInputStream("buffer.txt");
 
BufferedInputStream bis=new BufferedInputStream(fis)){
 
byte[] bytes=new byte[1024];
 
int hasRead=0;
 
while((hasRead=bis.read(bytes))!=-1) {
 
System.out.println(new String(bytes,0,hasRead));
 
}
 
}
 
}</nowiki>
 
2.文本IO
 
(1)Reader和Writer
 
Java IO中的java.io.Reader和java.io.Writer的工作原理很像InputStream和OutputStream,但不同的是reader和writer是基于字符的,他们是用来用些文本数据的。其类层级结构如图6-13所示。
 
 
 
图6-13 字符流结构
 
Reader用于读取字符流的抽象类。Reader类的常用方法如表6-7所示。
 
表6-7 Reader类常用方法
 
方法名 说明
 
boolean ready() 输入字符流是否可读
 
int read() 读取一个字符
 
int read(char[] cbuf) 读取一串字符(到字符数组cbuf)
 
long skip(long n) 跳过n个字符
 
mark(int readAheadLimit) 在当前位置做一标记
 
reset() 将读取位置恢复到标记处
 
close() 关闭字符流
 
Writer是写入字符流的抽象类。Writer类的常用方法如表6-8所示。
 
表6-8 Writer类常用方法
 
方法名 说明
 
void close() 关闭流
 
void flush() 强行写入
 
void write(int c) 写入c
 
void write(char[] cbuf) 写入字符数组cbuf
 
void write(char[] cbuf, int off, int len) 写入字符数组cbuf中自位置off开始的len个字符
 
void write(String str) 写入字符串str
 
void write(String str, int off, int len) 写入字符串str中自位置off开始的len个字符
 
(2)FileReader和FileWriter
 
FileReader:与FileInputStream对应,主要用来读取字符文件,使用缺省的字符编码,常用的构造函数如表6-9所示。
 
表6-9 FileReader类构造方法
 
构 造 方 法 说    明
 
FileReader(File file) 使用File对象创建文件输入流对象,如果文件打开失败,将抛出异常
 
FileReader(String name) 使用文件名或路径创建文件输入流对象,如果文件打开失败,将抛出异常
 
FileWrite:与FileOutputStream对应 ,将字符类型数据写入文件,使用缺省字符编码和缓冲器大小,常用的构造函数如表6-10所示。
 
表6-10 FileWriter类构造方法
 
构 造 方 法 说    明
 
FileWriter(File file) 使用File对象创建文件输出流对象,如果文件打开失败,将抛出异常,必须捕捉
 
FileWriter(File file, boolean append) 使用File对象创建文件输出流对象,并由参数append指定是否追加,异常情况同上
 
FileWriter(String name) 直接使用文件名或路径创建文件输出流对象,异常情况同上
 
FileWriter(String name, boolean append) 直接使用文件名或路径创建文件输出流对象,并由参数append指定是否追加,异常情况同上
 
下面程序使用FileReader和Writer将“Hello World”写入文件reader.txt,并读取打印出来。
 
public static void main(String[] args) throws IOException {
 
//把内容写入到文件中
 
try (FileWriter fw = new FileWriter("reader.txt");
 
) {
 
String str = "hello world";
 
fw.write(str.toCharArray());
 
}
 
//把内容显示在屏幕上
 
try(FileReader fr= new FileReader("reader.txt")){
 
char[] c=new char[20];
 
int hasRead=0;
 
while((hasRead=fr.read(c))!=-1) {
 
System.out.print(new String(c,0,hasRead));
 
}
 
}
 
}
 
(3)BufferedReader和BufferedWriter
 
使用FileRead和FileWriter从文件中逐个地读取/写入字符,效率比较低下,因此一般将该类对象包装到缓冲流(BufferedReader和BufferedWriter)中进行操作。BufferedReader和BufferedWriter与BufferedInputStream和BufferOutputStream操作类似,使用缓冲方式文本读取/写入,初次之外还提供了readLine()和newLine()方法,从而提高了读写的效率。
 
下面程序使用BufferedReader和BufferedWriter完成文件的写入和读取。
 
public static void main(String[] args) throws IOException {
 
// 把内容写入到文件中
 
try (FileWriter fw = new FileWriter("reader.txt"); BufferedWriter bw = new BufferedWriter(fw);) {
 
String str = "hello world";
 
bw.write(str);
 
bw.newLine();
 
bw.write("good good study");
 
}
 
// 把内容显示在屏幕上
 
try (FileReader fr = new FileReader("reader.txt"); BufferedReader br = new BufferedReader(fr)) {
 
while (br.ready()) {
 
System.out.println(br.readLine());
 
}
 
}
 
}
 
 
 
== 文本I/O ==
 

2018年4月5日 (四) 07:50的最新版本

IO流的概念

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

文件:Java6-7.png 图6-8 流

输入流和输出流

数据流是指一组有顺序的、有起点和终点的字节集合。它包括输入流和输出流。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。

文件:Java6-8.png 图6-9 输入输出流

如图6-9所示,程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道。程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。

字节流和字符流

流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:

(1) 字节流:数据流中最小的数据单元是字节。 (2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。

返回 Java程序设计