java IO(File类、字节流与字符流、字节字符转换流)

时间:2022-01-21 23:17:48
 

File类

在整个io包中,唯一表示与文件本身有关的类就是File类。使用File类可以进行创建或删除文件等常用操作,要想使用File类,则首先要观察File类的构造方法,此类的常用构造方法如下

public File(String pathname)实例化File类的时候,必须设置好路径根据路径找到文件

File类中的主要方法和常量

方法或常量

类型

描述

public static final String pathSeparator

常量

表示路径的分隔符(windows:‘;’)

public static final String separator

常量

表示路径分隔符(windows:‘\’)

public File(String pathname)

构造

创建File类对象,传入完整的路径

public boolean createNewFile() throws IOException

普通

创建新文件

public boolean exists()

普通

判断文件是否存在

public boolean delete()

普通

删除文件

public boolean isDirectory()

普通

判断给定的路径是否是一个目录

public long length()

普通

返回文件的大小

public String[] list()

普通

列出指定目录的全部内容,只是名称

public File[] listFiles()

普通

列出指定目录的全部内容,会列出路径。

public boolean mkdir()

普通

创建一个目录

public boolean renameTo(File dest)

普通

为已有的文件重命名

代码示例:

import java.io.*;
public class FileDemo01
{
public static void main(String args[]){
File file=new File("d:"+File.separator+"test.txt");
System.out.println("file.pathSeparator:"+file.pathSeparator);//调用静态变量
System.out.println("file.separator:"+file.separator);//调用静态变量
if(file.exists()){//判断当前文件是否存在
file.delete();//存在就删除
}
try{
file.createNewFile();//删除后重新创建
}catch(IOException e){
e.printStackTrace();
}
System.out.println("文件的大小:"+file.length());//输出新创建文件的大小
}
}

代码示例2:

import java.io.*;
public class FileDemo02
{
public static void main(String args[]){
File file=new File("d:"+File.separator+"test");
file.mkdir();//创建新的文件夹
File f=new File("d:"+File.separator+"test.txt");
f.renameTo(new File("d:"+File.separator+"test1.txt"));//为已知的文件重命名
}
}

案例:列出指定目录的全部文件

import java.io.File ;
import java.io.IOException ;
public class FileDemo03{
public static void main(String args[]){
File my = new File("d:" + File.separator) ;// 操作路径
print(my) ;
}
public static void print(File file){// 递归调用
if(file!=null){// 判断对象是否为空
if(file.isDirectory()){// 如果是目录
File f[] = file.listFiles() ;// 列出全部的文件
if(f!=null){// 判断此目录能否列出
for(int i=0;i<f.length;i++){
print(f[i]) ;// 因为给的路径有可能是目录,所以,继续判断
}
}
}else{
System.out.println(file) ;// 输出路径
}
}
}
};

字节流与字符流

在java.io包中操作文件内容的主要有两大类:字节流、字符流。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使用的是InputStream,在字符流中输出主要是使用Writer类完成,输入主要是使用Reader类完成。

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存 起来的时候,就要使用输出流完成。

操作流程

在java中IO操作也是有相关步骤的,以文件操作为例,主要的操作流程如下:

•A、使用File类打开一个文件
•B、通过字节流或字符流的子类,指定输出的位置
•C、进行读\写操作
•D、关闭输入\输出

字节流

字节流主要是操作byte类型数据,也byte数组为准,主要操作类就是

·字节输出流:OutputStream

·字节输入流:InputStream

字节输出流:OutputStream

OutputStream类是整个io包中字节输出流的最大父类,此类的定义如下:

public abstract class OutputStream extends Object implements Closeable, Flushable
•Closeable:表示可以关闭的操作,因为程序到最后肯定要关闭。
•Flushable:表示刷新,清空内存中的数据。

从以上类的定义中可以发现,此类是一个抽象类,如果要想使用此类的话,则首先必须通过子类实例化对象,那么如果现在要操作一个文件,则可以使用FileOutputStream类。通过向上转型之后,可以为OutputStream实例化。

OutputStream类中的常用方法:

方法描述
public void close() throws IOException关闭输出流
public void flush() throws IOException刷新缓冲区
public void write(byte[] b) throws IOException将一个byte数组写入数据流
public void write(byte[] b,int off,int len)throws IOException将一个指定范围的byte数组写入数据流
public abstract void write(int b) throws IOException将一个字节数据写入数据流

要想使用以上的方法,必须使用子类进行实例化,此时使用FileOutputStream子类,此类的构造方法如下:

public FileOutputStream(File file) throws FileNotFoundException

代码示例:创建文件并写入字符

import java.io.*;
public class OutputStreamDemo01
{
public static void main(String args[])throws Exception{
//1、使用File类指定一个文件名
File file=new File("d:"+File.separator+"test.txt");
//2、创建OutputStream类,并为此实例化对象
OutputStream out=new FileOutputStream(file);
//3、执行写入操作
String str="Hello world";
byte b[]=str.getBytes();
out.write(b);
//4、关闭输入流
out.close();
}
}

注:

1、  在操作的时候如果文件本身不存在,则会为用户自动创建新文件。

2、  如果要追加的内容需要换行,则在内容中加入“\r\n”就可以了。

以上的操作在写入数据之后,文件之前的内容已经不存在了,因为在IO操作中默认的情况是将其进行覆盖的,如果现在想执行追加的功能,则必须设置追加的操作,此时可以通过FileoutputStream向文件中追加内容:其另外的一个构造方法:

FileOutputStream(File file, boolean append)

在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容。

OutputStream out=new FileOutputStream(file,true);

字节输入流:InputStream

既然程序可以向文件中写入内容,则就可以通过InputStream从文件中把内容读取进来,首先来看InputStream类的定义:

public abstract class InputStream extends Object implements Closeable

和OutputStream一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,子类肯定是FileInputStream。构造方法:

public FileInputStream(File file) throws FileNotFoundException
InputStream类的常用方法:方法描述public int available() throws IOException可以取得输入文件的大小public void close() throws IOException关闭输入流public abstract int read() throws IOException读取内容,以数字的方式读取public int read(byte[] b) throws IOException将内容读到byte数组之中,同时返回个数

示例代码:

import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo01{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ;// 准备好一个输入的对象
input = new FileInputStream(f) ;// 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ;// 所有的内容都读到此数组之中
input.read(b) ;// 读取内容
// 第4步、关闭输出流
input.close() ;// 关闭输出流
System.out.println("内容为:" + new String(b)) ;// 把byte数组变为字符串输出
}
};

以上代码对文件中的内容读取了出来,但是数组开辟的空间远远要大于文件实际占用的空间,则此时可以根据读取文件的大小来开辟数组空间:

import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo03{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ;// 准备好一个输入的对象
input = new FileInputStream(f) ;// 通过对象多态性,进行实例化
// 第3步、进行读操作
// byte b[] = new byte[input..available()] ; 跟使用下面的代码是一样的
byte b[] = new byte[(int)f.length()] ;// 数组大小由文件决定
int len = input.read(b) ;// 读取内容
// 第4步、关闭输出流
input.close() ;// 关闭输出流\
System.out.println("读入数据的长度:" + len) ;
System.out.println("内容为:" + new String(b)) ;// 把byte数组变为字符串输出
}
};

另一种读取方法:

import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo05{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ;// 准备好一个输入的对象
input = new FileInputStream(f) ;// 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ;// 数组大小由文件决定
int len = 0 ;
int temp = 0 ;// 接收每一个读取进来的数据
while((temp=input.read())!=-1){
// 表示还有内容,文件没有读完
b[len] = (byte)temp ;
len++ ;
}
// 第4步、关闭输出流
input.close() ;// 关闭输出流\
System.out.println("内容为:" + new String(b,0,len)) ;// 把byte数组变为字符串输出
}
};

以上的读取方式在都是比较常见的。

字符流

在程序中一个字符等于2个字节,那么java提供了Reader、Writer两个专门操作字符流的类。

·字符输出流:Writer

·字符输入流:Reader

字符输出流:Writer

Writer本身是一个字符流的输出类,此类的定义如下:

public abstract class Writer extends Object implements Appendable, Closeable, Flushable

此类本身也是一个抽象类,如果要想使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,所以应该使用FileWriter子类。构造方法如下:

public FileWriter(File file) throws IOException

Writer类的常用方法:

方法或常量描述
public abstract void close() throws IOException关闭输出流
public void write(String str) throws IOException将字符串输出
public void write(char[] cbuf) throws IOException将字符数组输出
public abstract void flush() throws IOException强制性清空缓存

示例代码:(字符流可以直接输出字符串,不需要转换为字节)

import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo01{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ;// 准备好一个输出的对象
out = new FileWriter(f) ;// 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ;// 准备一个字符串
out.write(str) ;// 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ;// 关闭输出流
}
};

此时如果是想追加内容,与FileInputStream的格式是一样的,添加appemd属性为true;

字符输入流:Reader

Reader本身是一个字符流的输入类,此类的定义如下:

public abstract class Reader extends Object implements Closeable, Readable;

此类本身也是一个抽象类,如果要想使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,所以应该使用FileReader子类。构造方法如下:

public FileReaderr(File file) throws IOException

Writer类的常用方法:

方法或常量描述
public abstract void close() throws IOException关闭输出流
public int read() throws IOException读取单个字符
public int read(char[] cbuf) throws IOException将内容读到字符串数组中,返回读入的长度

示例代码:(以字符数组的形式读取出数据)

import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo01{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
Reader input = null ;// 准备好一个输入的对象
input = new FileReader(f) ;// 通过对象多态性,进行实例化
// 第3步、进行读操作
char c[] = new char[1024] ;// 所有的内容都读到此数组之中
int len = input.read(c) ;// 读取内容
// 第4步、关闭输出流
input.close() ;// 关闭输出流
System.out.println("内容为:" + new String(c,0,len)) ;// 把字符数组变为字符串输出
}
};

字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候使用到缓冲区的。

通过代码来验证字符流使用到了缓存。

import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo05{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ;// 准备好一个输出的对象
out = new FileOutputStream(f) ;// 实例化
// 第3步、进行写操作
String str = "Hello World!!!" ;// 准备一个字符串
byte b[] = str.getBytes() ;// 只能输出byte数组,所以将字符串变为byte数组
out.write(b) ;// 写入数据
// 第4步、关闭输出流
// out.close() ;// 关闭输出流 此处没有关闭输出流
}
};

在使用字节流操作中,即使没有关闭,最终也是可以输出的。

import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo03{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ;// 准备好一个输出的对象
out = new FileWriter(f) ;// 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ;// 准备一个字符串
out.write(str) ;// 将内容输出,保存文件
// 第4步、关闭输出流
// out.close() ;// 此时,没有关闭
}
};

以上的内容,没有输出任何的内容,也就是说,所有的内容都是保存在了缓冲区之中,而如果执行关闭输出流的话会强制性的刷新缓冲区,所以可以把内容输出。

如果现在假设,没有关闭的话,也可以手工强制性调用刷新方法:

public void flush() throws IOException

代码示例:

import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo04{
public static void main(String args[]) throws Exception{// 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ;// 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ;// 准备好一个输出的对象
out = new FileWriter(f) ;// 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ;// 准备一个字符串
out.write(str) ;// 将内容输出,保存文件
// 第4步、关闭输出流
out.flush() ;// 强制性清空缓冲区中的内容
// out.close() ;// 此时,没有关闭
}
};

在所有的硬盘保存文件或是进行传输的时候都是以字节的方式进行的。包括图片也是按字节完成,而字符只有在内存中才会形成。所以在开发中使用字节的操作是较多的。

范例:文件拷贝

通过执行该程序拷贝源文件到目标文件:

import java.io.* ;
public class Copy{
public static void main(String args[]){
if(args.length!=2){// 判断是否是两个参数
System.out.println("输入的参数不正确。") ;
System.out.println("例:java Copy 源文件路径 目标文件路径") ;
System.exit(1) ;// 系统退出
}
File f1 = new File(args[0]) ;// 源文件的File对象
File f2 = new File(args[1]) ;// 目标文件的File对象
if(!f1.exists()){
System.out.println("源文件不存在!") ;
System.exit(1) ;
}
InputStream input = null ;// 准备好输入流对象,读取源文件
OutputStream out = null ;// 准备好输出流对象,写入目标文件
try{
input = new FileInputStream(f1) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
try{
out = new FileOutputStream(f2) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
if(input!=null && out!=null){// 判断输入或输出是否准备好
int temp = 0 ;
try{
while((temp=input.read())!=-1){// 开始拷贝
out.write(temp) ;// 边读边写
}
System.out.println("拷贝完成!") ;
}catch(IOException e){
e.printStackTrace() ;
System.out.println("拷贝失败!") ;
}
try{
input.close() ;// 关闭
out.close() ;// 关闭
}catch(IOException e){
e.printStackTrace() ;
}
}
}
}

字节-字符转换流

OutputStreamWriter和InputStreamReader

在整个IO包中,实际上就是字节流和字符流,但是除了这两个流之外,还存在一组字节流-字符流的转换类。

•OutputStreamWriter:是Writer的子类,将输出的字符流转换为字节流。即:将一个字节流的输出对象变为字节流的输出对象
•InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即:将一个字节流的输入对象变为字符流的输入对象。

在OutputStreamWriter类中需要一个字节流的对象:public OutputStreamWriter(OutputStream out),例如:将字节的文件输出流,以字符的形式输出。

import java.io.*;
public class OutputStreamWriterDemo01
{
public static void main(String args[]) throws Exception{//所有异常抛出
File file=new File("d:"+File.separator+"test.txt");
Writer writer=null;//字符输出流
writer=new OutputStreamWriter(new FileOutputStream(file));//字节流变为字符流
String str="hello world!!!!";
writer.write(str);//使用字符流输出
writer.close();
}
}

读的时候,也可以使用字符流的形式读取字节流的文件。

import java.io.* ;
public class InputStreamReaderDemo01{
public static void main(String args[]) throws Exception{
File f = new File("d:" + File.separator + "test.txt") ;
Reader reader = null ;
reader = new InputStreamReader(new FileInputStream(f)) ;// 将字节流变为字符流
char c[] = new char[1024] ;
int len = reader.read(c) ;// 读取
reader.close() ;// 关闭
System.out.println(new String(c,0,len)) ;
}
};

对于FileWriter和FileReader的说明:

       从JDK文档中可知FileOutputStream是OutputStream的直接子类,FileInputStream也是InputStream的直接子类,但是在字符流文件的两个操作类却有一些特殊,FileWriter并不是Writer的子类,而是OutputStream的子类,而FileReader也不是Reader的直接子类,是InputStreamReader的子类。