Java IO
---------- android培训、java培训、期待与您交流!----------
1、什么是IO
Java IO就是指使用Java进行输入、输出的操作,Java中所有的操作类都存放在java.io包中。在程序中所有的数据都是以流的方式进行传输或者保存的,程序需要数据的时候就会用输入流读取数据,当需要保存数据时就用输出流存储数据,Java中最重要的有5个类:File、Reader、Writer、InputStream、OutputStream。
IO按照流的流向划分:
输入流:只能从中读取数据,而不能向其写数据。输入流基类,InputStream和Reader。
输出流:只能向其写入数据,而不能从中读取数据。输出流基类,OutputStream和Writer。
按照操作数据单元划分:
字节流:操作最小数据单元是8位的字节。字节流基类,InputStream和OutputStream。
字符流:操作最小数据单元是16位字节。字符流基类,Reader和Writer。
IO体系结构图如下图所示:
2、File类
在IO中唯一与文件本身有关的类就是File类,可以使用该类问文件做创建、删除等操作。
File类中的构造方法有:
File(File parent, String child);根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例
File(String pathname);通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例
File(String parent, String child);根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例
一般方法有:
(1) 创建
boolean createNewFile();在指定位置创建文件,如果文件已经存在,则不创建,返回false。 和输出流
boolean createNewFile();在指定位置创建文件,如果文件已经存在,则不创建,返回false。 和输出流
不一样,输出流对象一定创建文件,如果文件已存在,会覆盖旧文件
boolean mkdir();创建单级目录
boolean mkdirs();创建多级目录
(2) 删除
boolean delete();删除此抽象路径名表示的文件或目录,若文件或目录不存在,返回false。注意:当删
boolean mkdir();创建单级目录
boolean mkdirs();创建多级目录
(2) 删除
boolean delete();删除此抽象路径名表示的文件或目录,若文件或目录不存在,返回false。注意:当删
除某个目录时,若目录里有文件存在,则不可删除,返回false
void deleteOnExit();在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
(3) 判断
boolean exists();测试此抽象路径名表示的文件或目录是否存在
boolean isDirectory();判断是否是目录
boolean isFile();判断是否是文件。 注意:判断文件对象是否是文件或者目录时,必须先通过exists()方
void deleteOnExit();在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
(3) 判断
boolean exists();测试此抽象路径名表示的文件或目录是否存在
boolean isDirectory();判断是否是目录
boolean isFile();判断是否是文件。 注意:判断文件对象是否是文件或者目录时,必须先通过exists()方
法判断该文件对象是否存在
boolean isAbsolute();测试此抽象路径名是否为绝对路径名
boolean isHidden();测试此抽象路径名指定的文件是否是一个隐藏文件
boolean canRead();判断File对象所对应的文件或者目录是否可读
boolean canWrite();判断File对象所对应的文件或者目录是否可写
(4) 获取
File getAbsoluteFile();返回此抽象路径名的绝对路径名形式
String getAbsolutePath();返回此抽象路径名的绝对路径名字符串
long getFreeSpace();返回此抽象路径名指定的分区中未分配的字节数
String getName();返回由此抽象路径名表示的文件或目录的名称
String getPath();将此抽象路径名转换为一个路径名字符串
long length();返回由此抽象路径名表示的文件的长度
static File[] listRoots();列出可用的文件系统根
String[] list();列出File对象所有的子文件和路径名,返回String数组
创建文件的演示代码:
boolean isAbsolute();测试此抽象路径名是否为绝对路径名
boolean isHidden();测试此抽象路径名指定的文件是否是一个隐藏文件
boolean canRead();判断File对象所对应的文件或者目录是否可读
boolean canWrite();判断File对象所对应的文件或者目录是否可写
(4) 获取
File getAbsoluteFile();返回此抽象路径名的绝对路径名形式
String getAbsolutePath();返回此抽象路径名的绝对路径名字符串
long getFreeSpace();返回此抽象路径名指定的分区中未分配的字节数
String getName();返回由此抽象路径名表示的文件或目录的名称
String getPath();将此抽象路径名转换为一个路径名字符串
long length();返回由此抽象路径名表示的文件的长度
static File[] listRoots();列出可用的文件系统根
String[] list();列出File对象所有的子文件和路径名,返回String数组
创建文件的演示代码:
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
File file = new File("demo.txt");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用File类中得方法编写程序,列出指定目录下的所有文件及子目录中的文件:
import java.io.File;
public class FileIterate {
public static void main(String[] args) {
File dirs = new File("/Users/howard/Documents/workspace/Java_File_Demo1/src");
iterate(dirs);
}
public static void iterate(File dir){
System.out.println(dir+" 为目录,包含文件:");
File[] dirs = dir.listFiles();
for(int i=0; i
2、字符流
以上的代码已经在磁盘上创建了一个空的文件,现在就需要使用输出流向文件写入并保存数据。
字符流顾名思义,其操作的最基本单位是字符,Java中提供了两个操作字符的基类:Reader与Writer,Writer是一个字符流的输出抽象类,在IO体系结构图种可以得知其对文件进行操作的子类有FileWriter。
其主要方法有:
void close();关闭此流,但要先刷新它。
void flush();刷新该流的缓冲。
void write(char[] buf);写入字符数组。
void write(char[] buf, int off, int len) :写入字符数组的某一部分。
void write(int c);写入单个字符。
void write(String str);写入字符串。
void write(String str, int off, int len);写入字符串的某一部分。
注意:write、close、flush等方法都会出现异常,所以需要对异常进行捕获。
IO异常的处理方式为:
import java.io.FileWriter;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
FileWriter file = null;
try {
file = new FileWriter("demo.txt");
file.write("data");
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
if(file != null)
file.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
既然可以向文件写数据,那么就可以从文件中读取数据,读取即为输入,Reader为字符输入流的基类,直接对文件操作的子类为FileReader。
其主要方法有:
构造方法:
FileReader(String fileName);在给定从中读取数据的文件名的情况下创建一个新 FileReader。
常用方法:
void close();关闭该流并释放与之关联的所有资源。
int read();读取单个字符,会自动记录当前读取的位置,读取到最后没有数据时返回-1
int read(char[] buf);将字符读入数组。
int read(char[] buf, int off, int len);将字符读入数组的某一部分。
综合以上读与写的操作,编写一段复制文件的代码:
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
FileReader sfile = null;
FileWriter dfile = null;
try {
sfile = new FileReader(new File("demo.txt"));
dfile = new FileWriter(new File("demoCopy.txt"));
char[] buf = new char[1024];
int len = 0;
while((len=sfile.read(buf)) != -1){
dfile.write(new String(buf, 0, len));
}
} catch (IOException e) {
System.out.println("复制失败");
}finally{
if(dfile != null && sfile != null){
try {
sfile.close();
dfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("复制成功");
}
}
}
为了提高读写效率,Java中还定义了缓冲区类型的字符流:BufferedReader与BufferedWriter。其出现是为了提高流的读写效率,所以在创建缓冲区之前,必须首先有流的存在,所以它没有无参构造方法。
BufferedWriter
构造方法:
BufferedWriter(Writer out);创建一个使用默认大小输出缓冲区的缓冲字符输出流
常用方法:
void close();关闭此流,但要先刷新它。
void flush();刷新该流的缓冲。
void newLine();写入一个行分隔符,该方法具有跨平台性
void write(char[] buf);写入字符数组
void write(char[] buf, int off, int len);写入字符数组的某一部分
void write(int c);写入单个字符
void write(String str);写入字符串
void write(String s, int off, int len);写入字符串的某一部分
BufferedReader:
构造方法:
BufferedReader(Reader in);创建一个使用默认大小输入缓冲区的缓冲字符输入流
常用方法:
void close();关闭该流并释放与之关联的所有资源
int read();读取单个字符。
int read(char[] buf);将字符读入数组
int read(char[] buf, int off, int len);将字符读入数组的某一部分
String readLine();读取一个文本行。当读取到文件末尾时,返回null
使用带缓冲的字符流复制文件:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
BufferedReader sfile = null;
BufferedWriter dfile = null;
try {
sfile = new BufferedReader(new FileReader("demo.txt"));
dfile = new BufferedWriter(new FileWriter("demoCopy.txt"));
String line = null;
while((line=sfile.readLine()) != null){
dfile.write(line);
dfile.newLine();
}
} catch (IOException e) {
System.out.println("复制失败");
}finally{
if(dfile != null && sfile != null){
try {
sfile.close();
dfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("复制成功");
}
}
}
readLine的原理:无论是读一行还是读取多个字符,最终都是使用read()一个一个读取,当读到行尾换行符时,返回一行数据,但是不包含换行符,所以在使用时需要手动添加newLine()换行。
3、字节流
字节流主要操作byte型数据,两个基类为InputStream与OutputStream。
OutputStream:是IO包种字节输出流的最大基类,并且是一个抽象类,常用的子类为FileOutputStream与BufferedOutputStream。
FileOutputStream:
构造方法:
FileOutputStream(String name);创建一个向具有指定名称的文件中写入数据的输出文件流
FileOutputStream(String name, boolean append);创建一个向具有指定 name 的文件中写入数据的输
出文件流
常用方法:
void close();关闭此文件输出流并释放与此流有关的所有系统资源
void write(byte[] b);将 b.length 个字节从指定 byte 数组写入此文件输出流中
void write(byte[] b, int off, int len);将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流
void write(int b);将指定字节写入此文件输出流
FileInputStream:
构造方法:
FileInputStream(String name);通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通
过文件系统中的路径名 name 指定
常用方法:
int available();返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩
余
字节数
void close();关闭此文件输入流并释放与此流有关的所有系统资源
int read();从此输入流中读取一个数据字节
int read(byte[] b);从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
int read(byte[] b, int off, int len);从此输入流中将最多 len 个字节的数据读入一个 byte 数组中
利用字节输入与输出流编写一个MP3媒体文件复制程序:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class InputStreamDemo {
public static void main(String[] args) {
FileInputStream sfile = null;
FileOutputStream dfile = null;
try {
sfile = new FileInputStream("demo.mp3");
dfile = new FileOutputStream("democopy.mp3");
byte[] buf = new byte[1024];
int len = 0;
while((len=sfile.read(buf)) != -1){
dfile.write(buf, 0, len);
}
} catch (IOException e) {
System.out.println("复制失败");
}finally{
System.out.println("复制成功");
try {
if(sfile != null)
sfile.close();
} catch (IOException e) {
System.out.println("读取关闭失败");
}
try {
if(dfile != null)
dfile.close();
} catch (IOException e) {
System.out.println("写入关闭失败");
}
}
}
}
在字节流中也有带缓冲区的输入输出流,BufferedInputStream与BufferedOutputStream。
BufferedOutputStream:
构造方法:
BufferedOutputStream(OutputStream out);创建一个新的缓冲输出流,以将数据写入指定的底层输出流
常用方法:
void close();关闭此输出流并释放与此流有关的所有系统资源
void flush();刷新此缓冲的输出流
void write(byte[] b, int off, int len);将指定 byte 数组中从偏移量 off 开始 len 个字节写入此缓冲的输出流
void write(int b);将指定的字节写入此缓冲的输出流
void write(byte[] b);将 b.length 个字节写入此输出流
BufferedInputStream
构造方法:
BufferedInputStream(InputStream in):创建一个 BufferedInputStream 并保存其参数,即输入流 in,以
便将来使用
常用方法:
int available():返回可以从此输入流读取(或跳过)不受此输入流接下来的方法调用阻塞的估计字节数
void close():关闭此输入流并释放与该流关联的所有系统资源
int read():从此输入流中读取下一个数据字节
int read(byte[] b):从此输入流中将 byte.length 个字节的数据读入一个 byte 数组中
int read(byte[] b, int off, int len):从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组
字节流与字符流不同的是,字符流用到了缓冲区,所以需要刷新,而字节流是直接面向字节进行操作的,不需要刷新
4、System类
System类表示的是系统类,在Java中System类对IO也有一定的支持。
System.in:实际上是一个键盘的输入流,本身是InputStream类型的对象,可以利用该对象完成键盘的数据读取功能。
System.out:是PrintStream的对象,该对象为向屏幕输出内容。
System.err:表示错误信息输出,如果程序中出现了错误,则可以直接使用它进行输出。
5、转换流
字节流与字符流之间是可以转换的,可以使用Reader的子类:InputStreamReader与Writer的子类:OutputStreamWriter。前者将输入的字节流转为字符流输入,后者将字节流输出转为字符流输出。
System类中的键盘输入流为字节流,那么可以利用转换流将字节流转为字符流,对键盘的输入进行获取并操作,如下代码:
import java.io.*;
public class SystemInDemo {
public static void main(String[] args) {
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String data = null;
System.out.println("输入:");
try {
data = buf.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(data);
}
}
---------- Windows Phone 7手机开发、.Net培训、期待与您交流! ----------