java中io流详细整理
Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable。掌握了这些就掌握了Java I/O的精髓了。
Java I/O主要包括如下3层次:
- 流式部分——最主要的部分。如:OutputStream、InputStream、Writer、Reader等
- 非流式部分——如:File类、RandomAccessFile类和FileDescriptor等类
- 其他——文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要类如下:
- File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
- InputStream(字节流,二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
- OutputStream(字节流,二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
- Reader(字符流,文本格式操作):抽象类,基于字符的输入操作。
- Writer(字符流,文本格式操作):抽象类,基于字符的输出操作。
- RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
I/O流
java.io包里有4个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流。
其他各种各样的流都是由这4个派生出来的。
按来源/去向分类:
- File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter
- byte[]:ByteArrayInputStream, ByteArrayOutputStream
- Char[]: CharArrayReader, CharArrayWriter
- String: StringBufferInputStream, StringReader, StringWriter
- 网络数据流:InputStream, OutputStream, Reader, Writer
InputStream
InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。 继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节(8bit);
InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.Inputstream类中的常用方法:
- 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( ) :使用完后,必须对我们打开的流进行关闭。
来看看几种不同的InputStream:
- FileInputStream把一个文件作为InputStream,实现对文件的读取操作
- ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用
- StringBufferInputStream:把一个String对象作为InputStream
- PipedInputStream:实现了pipe的概念,主要在线程中使用
- SequenceInputStream:把多个InputStream合并为一个InputStream
OutputStream
OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
- 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( ) : 关闭输出流并释放与流相关的系统资源。
几种不同的OutputStream:
- ByteArrayOutputStream:把信息存入内存中的一个缓冲区中
- FileOutputStream:把信息存入文件中
- PipedOutputStream:实现了pipe的概念,主要在线程中使用
- SequenceOutputStream:把多个OutStream合并为一个OutStream
Reader和InputStream类似;Writer和OutputStream类似。
有两个需要注意的:
- InputStreamReader : 从输入流读取字节,在将它们转换成字符。
- BufferReader :接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。
如何选择I/O流
- 确定是输入还是输出
输入:输入流 InputStream Reader
输出:输出流 OutputStream Writer - 明确操作的数据对象是否是纯文本
是:字符流 Reader,Writer
否:字节流 InputStream,OutputStream - 明确具体的设备。
- 文件:
读:FileInputStream,, FileReader,
写:FileOutputStream,FileWriter - 数组:
byte[ ]:ByteArrayInputStream, ByteArrayOutputStream
char[ ]:CharArrayReader, CharArrayWriter - String:
StringBufferInputStream(已过时,因为其只能用于String的每个字符都是8位的字符串), StringReader, StringWriter - Socket流
键盘:用System.in(是一个InputStream对象)读取,用System.out(是一个OutputStream对象)打印
- 文件:
- 是否需要转换流
是,就使用转换流,从Stream转化为Reader、Writer:InputStreamReader,OutputStreamWriter - 是否需要缓冲提高效率
是就加上Buffered:BufferedInputStream, BufferedOuputStream, BufferedReader, BufferedWriter - 是否需要格式化输出
一下面先说说FIle类:
FIle中常用的方法:
1.创建
boolean createNewFile();在指定路径创建文件,如果文件已经存在,则不创建,返回false.输出流
对象一旦创建,如果文件存在,则会覆盖。
boolean mkdir():创建一级文件夹
boolean mkdirs():创建多级文件夹
2.删除
boolean delete():删除失败返回false。如果文件正在使用,则删除不了返回false
void deleteOnExit():程序退出时删除文件
3.判断
boolean exists():判断文件是否存在
isFile();//测试此抽象路径名表示的文件是否是一个标准文
isDirectory();//是否是目录
isHidden();
4.获取信息
getName();
getPath();//获取路径
getAbsoluteFile();//获取绝对路径封装成文件对象
getAbsolutPath();//获取绝对路径
getParent();//该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null.
lastModified();
length();
例子:
创建一个新文件
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"text.txt";
File f=new File(filename);
if(!f.exists()){
f.createNewFile();
}
}
}
删除一个文件
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"text.txt";
File f=new File(filename);
if(f.exists()){
f.delete();
}else{
System.out.println("不存在此文件");
}
}
}
创建一个文件夹
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"hello";
File f=new File(filename);
f.mkdir();
}
}
列出指定目录的全部文件(包括隐藏文件):
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"hello";
File f=new File(filename);
if(!f.exists()){
f.createNewFile();
}
String[] fb=f.list();
for(String str:fb){
System.out.println(str);
}
}
}
运行结果:新建文本文档.txt
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"hello";
File f=new File(filename);
if(!f.exists()){
f.createNewFile();
}
File[] fhs=f.listFiles();
for(File fh:fhs){
System.out.println(fh);
}
}
}
运行结果:
E:\xie\hello\ddd
E:\xie\hello\新建文本文档.txt
判断一个指定的路径是否为目录:
package www.xxx.com;
import java.io.File;
import java.io.IOException;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"hello";
File f=new File(filename);
if(f.exists()){
f.createNewFile();
}
if(f.isDirectory()){
System.out.println("yes");
}else{
System.out.println("no");
}
}
}
运行结果:
yes
使用RandomAccessFile写入文件
package www.xxx.com;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws IOException {
String filename="E:"+File.separator+"xie"+File.separator+"Test.txt";
File f=new File(filename);
if(!f.exists()){
f.createNewFile();
}
RandomAccessFile dom=new RandomAccessFile(f,"rw");
dom.write("fdsfssdf多付费方式等".getBytes());
dom.writeBytes("dsafdas");
dom.writeChar('A');
dom.close();
}
}
运行结果:
打开文件有写入,不过是乱码
下面说说RandomAccessFile的简单用法
例子:在文件中写入
zhangsan,11
lisi,12
waner,15
package www.xxx.com;
import java.io.File;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws Exception {
String fp="E:"+File.separator+"xie"+File.separator+"Test.txt";
File f=new File(fp);
RandomAccessFile rdaf = null ; // 声明RandomAccessFile类的对象
rdaf=new RandomAccessFile(f,"rw");//读写,如果使用此模式,此文件不存在时,则会自动创建
String name=null;
int age=0;
name="zhangsan";//字符串的长度为8
age=11;
rdaf.writeBytes(name);//将名字写入文件中
rdaf.writeInt(age);//数字长度为4,将年龄写入文件中
name="lisi ";
age=12;
rdaf.writeBytes(name);
rdaf.writeInt(age);
name="wanger ";
age=15;
rdaf.writeBytes(name);
rdaf.writeInt(age);
rdaf.close();
}
}
读取文件:
package www.xxx.com;
import java.io.File;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws Exception {
String fp="E:"+File.separator+"xie"+File.separator+"Test.txt";
File f=new File(fp);
RandomAccessFile rdaf=null; // 声明RandomAccessFile类的对象
rdaf=new RandomAccessFile(f,"r");//只读
int age=0;
byte b[]=new byte[8];
String name=null;
//我们先读取第二个人信息
rdaf.skipBytes(12);//跳过第一个人的信息
for(int i=0;i<b.length;i++){
b[i]=rdaf.readByte();//读取一个字节
}
name=new String(b);//转化为字符串
age=rdaf.readInt();//读取年龄
System.out.println("第二个人的信息-->name:"+name+",age:"+age);
//读取第一个人的信息
rdaf.seek(0);//指针跳转到第一个人信息
for(int i = 0;i<b.length;i++){
b[i]=rdaf.readByte();
}
name=new String(b);
age=rdaf.readInt();
System.out.println("第一个人的信息-->name:"+name+",age:"+age);
//读取第三个人信息
rdaf.skipBytes(12);//跳过第二个人得信息
for(int i=0;i<b.length;i++){
b[i]=rdaf.readByte();
}
name=new String(b);
age=rdaf.readInt();
System.out.println("第三个人的信息-->name:"+name+",age:"+age);
rdaf.close();
}
}
运行结果:
第二个人的信息-->name:lisi ,age:12
第一个人的信息-->name:zhangsan,age:11
第三个人的信息-->name:wanger ,age:15
二:File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter
package www.xxx.com;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileInputStream fis=new FileInputStream(path);
int len=fis.available();
byte[] bt=new byte[len];
fis.read(bt);
String str=new String(bt);
System.out.println(str);
fis.close();
}
}
FileOutputStream写数据:
package www.xxx.com;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileOutputStream fos=new FileOutputStream(path);
String content="张三123";
byte[] bt=content.getBytes();////将字符串转成字节数组
fos.write(bt);//将参数bt中的字节写到输出流
fos.flush();//将数据缓冲区中数据全部输出,并清空缓冲区。
fos.close();
}
}
3,FileReader类
1,构造方法
FileReader fr = new FileReader(String fileName);//使用带有指定文件的String参数的构造方法。创建该输入流对象。并关联源文件。
2,主要方法
int read(); // 读取单个字符。返回作为整数读取的字符,如果已达到流末尾,则返回 -1。
int read(char []cbuf);//将字符读入数组。返回读取的字符数。如果已经到达尾部,则返回-1。
void close();//关闭此流对象。释放与之关联的所有资源。
FileReader 读取文件例子:
package www.xxx.com;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.RandomAccessFile;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileReader fr=new FileReader(path);
int ch=0;
while((ch=fr.read())!=-1){
System.out.print((char)ch);
}
fr.close();
}
}
4,FileWriter类(字符输出流类)
构造方法:FileWriter fw = new FileWriter(String fileName);//创建字符输出流类对象和已存在的文件相关联。文件不存在的话,并创建。
如:FileWriter fw = new FileWriter("C:\\demo.txt");
FileWriter fw = new FileWriter(String fileName,boolean append);//创建字符输出流类对象和已存在的文件相关联,并设置该该流对文件的操作是否为续写。
如:FileWriter fw = new FileWriter("C:\\demo.txt",true); //表示在fw对文件再次写入时,会在该文件的结尾续写,并不会覆盖掉。
主要方法: void write(String str) //写入字符串。当执行完此方法后,字符数据还并没有写入到目的文件中去。此时字符数据会保存在缓冲区中。
此时在使用刷新方法就可以使数据保存到目的文件中去。
viod flush() //刷新该流中的缓冲。将缓冲区中的字符数据保存到目的文件中去。
viod close() //关闭此流。在关闭前会先刷新此流的缓冲区。在关闭后,再写入或者刷新的话,会抛IOException异常。
例子:
package www.xxx.com;
import java.io.File;
import java.io.FileWriter;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileWriter fw=new FileWriter(path,true);
String str="字符串12343";
fw.write(str);
fw.flush();//刷新该流中的缓冲。将缓冲区中的字符数据保存到目的文件中去。
fw.close();
}
}
FileInputStream类与FileReader类的区别:
FileInputStream:以字节流方式读取;FileReader:把文件转换为字符流读入;
InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。用Reader读取出来的是char数组或者String ,使用InputStream读取出来的是byte数组。
Reader类及其子类提供的字符流的读取char(16位,unicode编码),inputStream及其子类提供字节流的读取byte(8位),所以FileReader类是将文件按字符流的方式读取,FileInputStream则按字节流的方式读取文件;InputStreamReader 可以将读如stream转换成字符流方式,是reader和stream之间的桥梁
最初Java是不支持对文本文件的处理的,为了弥补这个缺憾而引入了Reader和Writer两个类。
FileInputStream类以二进制输入/输出,I/O速度快且效率搞,但是它的read()方法读到的是一个字节(二进制数据),很不利于人们阅读。
而FileReader类弥补了这个缺陷,可以以文本格式输入/输出,非常方便;比如可以使用while((ch = filereader.read())!=-1)
另补充:
循环来读取文件;可以使用BufferedReader的readLine()方法一行一行的读取文本。
当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader, InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader,它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。
FileReader与InputStreamReader涉及编码转换(指定编码方式或者采用os默认编码),可能在不同的平台上出现乱码现象!而FileInputStream以二进制方式处理,不会出现乱码现象.
使用BufferedReader的readLine()方法读取文件:
package www.xxx.com;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileInputStream fis=new FileInputStream(path);
InputStreamReader isr=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);
String data=null;
while((data=br.readLine())!=null){
System.out.println(data);
}
br.close();
}
}
一般文件的读取形式:
1) File file = new File ("hello.txt");
FileInputStream in=new FileInputStream(file);
2) File file = new File ("hello.txt");
FileInputStream in=new FileInputStream(file);
InputStreamReader inReader=new InputStreamReader(in);
BufferedReader bufReader=new BufferedReader(inReader);
3) File file = new File ("hello.txt");
FileReader fileReader=new FileReader(file);
BufferedReader bufReader=new BufferedReader(fileReader);
数组:
byte[ ]:ByteArrayInputStream, ByteArrayOutputStream
char[ ]:CharArrayReader, CharArrayWriter
package www.xxx.com;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
FileInputStream fis=new FileInputStream(path);
InputStreamReader isr=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);
String data=null;
while((data=br.readLine())!=null){
System.out.println(data);
}
br.close();
}
private static void charArray() throws IOException {
//字符数组流/内存流
//字符数组输出流:程序----->内存
CharArrayWriter cw =new CharArrayWriter();
cw.write("欢迎学习!");
char[] content=cw.toCharArray();
//字节数组输入流:内存----->程序
CharArrayReader reader=new CharArrayReader(content);
int len=-1;
char[] ch=new char[1024];
while((len=reader.read(ch))!=-1){
System.out.println(new String(ch,0,len));
}
cw.close();
reader.close();
}
private static void byteArray() throws Exception {
//字节数组流/内存流
//字节数组输出流:程序----->内存
ByteArrayOutputStream out=new ByteArrayOutputStream();
out.write("大家好啊!".getBytes());
byte[] bye=out.toByteArray();
//字节数组输入流:内存----->程序
ByteArrayInputStream in=new ByteArrayInputStream(bye);
byte[] buffer=new byte[1024];
int len=-1;
while((len=in.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
out.close();
in.close();
}
}
缓冲提高效率BufferedInputStream, BufferedOuputStream, BufferedReader, BufferedWriter
package www.xxx.com;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
String writepath="E:"+File.separator+"xie"+File.separator+"text1.txt";
InputStream is=new FileInputStream(path);
BufferedInputStream bis=new BufferedInputStream(is);
OutputStream os=new FileOutputStream(writepath);
byte[] c=new byte[20];
int len=0;
while((len=bis.read(c))!=-1){
//把每次装入桶中的内容写入到文件中,每次写入0到len,因为len是每次读取到的实际内容个数
os.write(c, 0, len);
}
os.flush();
os.close();
is.close();
System.out.println("成功");
}
}
文件复制
package www.xxx.com;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
public class Hello {
public static void main(String[] args) throws Exception {
String path="E:"+File.separator+"xie"+File.separator+"text.txt";
String writepath="E:"+File.separator+"xie"+File.separator+"text1.txt";
Reader fiReader=new FileReader(path);
BufferedReader bReader=new BufferedReader(fiReader);
Writer fiw=new FileWriter(writepath);
BufferedWriter bWriter=new BufferedWriter(fiw);
String line=null;
while((line=bReader.readLine())!=null){
System.out.println("line:"+line);////上面返回的line中的readLine方法中不包含换行符
bWriter.write(line);
bWriter.newLine();////因为每次是读取一行内容,所以显示一行后就得换行
bWriter.flush();
}
bWriter.close();
fiReader.close();
}
}