1、概述
(1)JAVA对数据的操作是通过流的方式,JAVA用于操作流的对象都在IO包中,流按操作数据分为两种,即字节流和字符流,流按流向也分为两种,即输入流和输出流。
(2)IO流常用抽象基类:
-字节流的抽象基类:InputStream和OutputStream
-字符流的抽象基类:Reader和Writer
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
2、Writer类
(1)Writer类是写入字符流的抽象类。
(2)Writer类主要方法:
-void writer(char[] cbuf):写入字符数组。
-abstract void writer(char[] cbuf,int off,intlen):写入字符数组的某一部分。
-void writer(int c):写入单个字符。
-void writer(String str):写入字符串。
-void writer(String str,int off,int len):写入字符串的某一部分。
-abstract void flush():刷新该流的缓冲。
-abstract void close():关闭此流,但要先刷新它。
3、FileWriter类
(1)FileWriter是用来写入字符文件的便捷类。
(2)FileWriter构造函数:
-FileWriter(File file):根据给定的 File 对象构造一个 FileWriter 对象。如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它抛出IOException。
-FileWriter(String filename):根据给定的文件名构造一个 FileWriter 对象。如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它抛出IOException。
-FileWriter(String filename,Boolean append):根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。append如果为true
,则将数据写入文件末尾处,而不是写入文件开始
(3)FileWriter对象特点:创建一个FileWriter对象时,该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖,其实该步就是在明确数据要存放的目的地。该对象可以调用write方法将字符串写入到流中,再flush方法可以刷新流对象中的缓冲中的数据并将数据刷到目的地中。该对象调用close方法可以关闭流资源,但是关闭前会刷新一次内部的缓冲中的数据将数据刷到目的地中。close方法和flush方法的区别是flush刷新后流可以继续使用,而close刷新后会将流关闭。
(4)示例:
import java.io.*;
public class FileWriterDemo
{
public static void main(String[]args)throws IOException
{
FileWriter fw=null;//建立文件输出流
try
{
fw=newFileWriter("Demo.txt");//实例化文件输出流
fw.write("abcd");//写数据
fw.flush();//刷新流
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fw!=null)
fw.close();//关闭流资源
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
4、Reader类
(1)Reader类是用于读取字符流的抽象类。
(2)Reader类主要方法:
-abstract void close():关闭该流并释放与之关联的所有资源。
-int read():读取单个字符,一次读一个字符,且会自动往下读。返回作为整数读取的字符,如果已到达流的末尾,则返回 -1
-int read(char[] cbuf):将字符读入数组。返回读取的字符数,如果已到达流的末尾,则返回 -1
-abstract int read(char[] cbuf,int off, int len)
:
将字符读入数组的某一部分。返回读取的字符数,如果已到达流的末尾,则返回 -1
-void reset():重置该流。
5、FileReader类
(1)FileReader类用来读取字符文件的便捷类。
(2)FileReader构造函数:
-FileReader(File file):在给定从中读取数据的 File 的情况下创建一个新 FileReader对象。
-FileReader(String filename):在给定从中读取数据的文件名的情况下创建一个新 FileReader。
(3)FileReader类FileReader方法可以创建一个文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在,会发生异常。
(4)FileReader第一种读取方式(read()方法)示例:
import java.io.*;
public class FileReaderDemo1
{
public static void main(String[] args)
{
FileReader fr=null;//创建字符读取流
try
{
fr=newFileReader("Demo.txt");//实例化读取流
int ch=0;
//读数据
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fr!=null)
fr.close();//关闭流资源
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
(5)FileReader第二种读取方式(read(char[])方法)示例:
import java.io.*;
public class FileReaderDemo2
{
public static void main(String[] args)
{
FileReader fr=null;//创建读取流
try
{
fr=newFileReader("Demo.txt");//实例化流对象
char[] ch=newchar[1024];
int num=0;
//读数据
while((num=fr.read(ch))!=-1)
{
System.out.println(newString(ch,0,num));
}
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fr!=null)
fr.close();//关闭流资源
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
5、文件读写练习
(1)复制文本文件
步骤:
-创建一个新文件,用于存储源文件中的数据。
-定义读取流和源文件关联。
-通过不断的读写完成数据存储。
-关闭资源。
import java.io.*;
public class FileCopyTest
{
public static void main(String[] args)
{
copy_1();
copy_2();
}
//第一种方式
public static void copy_1()
{
FileWriter fw=null;//创建写入流
FileReader fd=null;//创建读取流
try
{
fw=newFileWriter("FileReaderDemo1_copy.txt");
fd=newFileReader("FileReaderDemo1.java");
int ch=0;
//从原文件中读数据并写入到新文件中
while((ch=fd.read())!=-1)
{
fw.write(ch);
fw.flush();
}
}
catch(IOException e)
{
throw newRuntimeException("Copy fail");
}
finally
{
//关闭流资源
try
{
if(fw!=null)
fw.close();
}
catch(IOException e)
{
throw newRuntimeException("close fail");
}
try
{
if(fd!=null)
fd.close();
}
catch(IOException e)
{
throw newRuntimeException("close fail");
}
}
}
//第二种方式
public static void copy_2()
{
FileWriter fw=null;//创建写入流
FileReader fd=null;//创建读取流
try
{
fw=newFileWriter("FileReaderDemo1_copy2.txt");
fd=newFileReader("FileReaderDemo1.java");
char[] ch=newchar[1024];
int len=0;
//从原文件中读数据并写入新文件中
while((len=fd.read(ch))!=-1)
{
fw.write(ch,0,len);
fw.flush();
}
}
catch(IOException e)
{
throw newRuntimeException("copy fail");
}
finally
{
//关闭流资源
try
{
if(fw!=null)
fw.close();
}
catch(IOException e)
{
throw newRuntimeException("close fail");
}
try
{
if(fd!=null)
fd.close();
}
catch(IOException e)
{
throw newRuntimeException("close fail");
}
}
}
}
6、字符流缓冲区
(1)缓冲区的出现提高了对数据的读写效率,缓冲区要结合流才可以使用,且在流的基础上对流的功能进行了增强。
(2)字符流缓冲区对应类
-BufferedWriter
-BufferedReader
7、BufferedWriter类
(1)BufferedWriter类是Writer类的子类,提供对单个字符、数组和字符串的高效写入。
(2)主要方法:
-BufferedWriter(Writerout):创建一个使用默认大小输出缓冲区的缓冲字符输出流。
-BufferedWriter(Writerout,int sz):创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
-void close():关闭此流,但要先刷新它。
-void flush():刷新该流的缓冲。
-void newLine():写入一个行分隔符。
-void write(char[]ch,int off,int len):写入字符数组的某一部分。
-void write(int c):写入单个字符。
-void write(Strings,int off,int len):写入字符串的某一部分。
(3)示例:
import java.io.*;
public class BufferedWriterDemo
{
publicstatic void main(String[] args)
{
BufferedWriterbw=null;//创建缓冲区输出流
try
{
bw=newBufferedWriter(new FileWriter("Demo.txt"));
bw.write("BufferedWriterDemo");//写数据
bw.flush();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
finally
{
try
{
if(bw!=null)
bw.close();//关闭流资源
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
8、BufferedReader类
(1)BufferedReader类是Reader类的一个子类,可以从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
(2)主要方法:
-BufferedReader(Readerin):创建一个使用默认大小输入缓冲区的缓冲字符输入流。
-BufferedReader(Readerin,int sz):创建一个使用指定大小输入缓冲区的缓冲字符输入流。
-void close():关闭该流并释放与之关联的所有资源。
-int read(): 读取单个字符。返回作为一个整数读入的字符,如果已到达流末尾,则返回 -1。
-intread(char[] ch,int off,int len):将字符读入数组的某一部分。返回读取的字符数,如果已到达流末尾,则返回 -1
-String readLine():读取一个文本行。返回包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
(3)示例:
import java.io.*;
public class BufferedReaderDemo
{
publicstatic void main(String[] args)
{
BufferedReaderbr=null;//创建缓冲区读取流
try
{
br=newBufferedReader(new FileReader("BufferedWriterDemo.java"));
Stringline=null;
//读数据
while((line=br.readLine())!=null)
{
System.out.println(line);
}
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
finally
{
try
{
if(br!=null)
br.close();//关闭流资源
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
注意:readLine方法返回的时候只返回回车符之前的数据,并不返回回车符。
9、缓冲区练习:通过缓冲区复制一个文件。
import java.io.*;
public class BufCopyTest
{
publicstatic void main(String[] args)
{
//创建流
BufferedWriterbw=null;
BufferedReaderbr=null;
try
{
bw=newBufferedWriter(new FileWriter("BufferedWriterDemo_copy.txt"));
br=newBufferedReader(new FileReader("BufferedWriterDemo.java"));
Stringline=null;
//从原文件中读数据并写入到新文件中
while((line=br.readLine())!=null)
{
bw.write(line);
bw.newLine();
bw.flush();
}
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
finally
{
//关闭流资源
try
{
if(bw!=null)
bw.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
try
{
if(br!=null)
br.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
10、装饰设计模式
(1)装饰设计模式就是当想要对已有的对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的类就称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能提供更强的功能。
(2)装饰与继承的区别:装饰模式比继承要灵活,避免了继承体系过于臃肿。而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只是提供了更强的功能,所以装饰类和被装饰类通常都属于一个体系中。
(3)自定义包装类
可以自定义一个类中包含一个功能和readLine一致的方法来模拟一下BufferedReader。
import java.io.*;
public class MyBufferedReader extends Reader //自定义缓冲区读取流
{
privateReader r;
publicMyBufferedReader(Reader r)
{
this.r=r;
}
publicString myReadLine() throws IOException //定义读取一行数据的方法
{
Stringsb=new StringBuider();
intch=0;
while((ch=r.read()!=-1))
{
if(ch=='\r')
continue;
if(ch=='\n')
returnsb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
returnsb.toString();
returnnull;
}
publicint read(char[] cbuf,int off,int len)throws IOException
{
returnr.read(cbuf,off,len);
}
publicvoid close()throws IOException
{
r.close();
}
}
11、LineNumberReader类
(1)LineNumberReader类是BufferedReader类的一个子类,是可以跟踪行号的缓冲字符输入流。该类定义了setLineNumber(int)和getLineNumber()方法分别用于设置和获取当前行号。默认情况下,行编号从 0 开始。但要注意的是,setLineNumber(int)
不会实际更改流中的当前位置;它只更改将由getLineNumber() 返回的值。
12、OutputStream类
(1)OutputStream类是一个抽象类,是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
(2)主要方法:
-void close():关闭此输出流并释放与此流有关的所有系统资源。
-void flush():刷新此输出流并强制写出所有缓冲的输出字节。
-voidwrite(byte[] b):将b.length
个字节从指定的 byte 数组写入此输出流。
-voidwrite(byte[] int off,int len):将指定 byte 数组中从偏移量off
开始的len
个字节写入此输出流。
-abstractvoid write(int b):将指定的字节写入此输出流。
(3)常用子类:FileOutputStream
12、FileOutputStream类
(1)FileOutputStream类是OutputStream的一个子类,是用于将数据写入 File
或FileDescriptor
的字节输出流。
(2)主要方法:
-FileOutputStream(Filefile):创建一个向指定File
对象表示的文件中写入数据的文件输出流。
-FileOutputStream(Filefile,Boolean append):创建一个向指定File
对象表示的文件中写入数据的文件输出流。如果第二个参数为true
,则将字节写入文件末尾处,而不是写入文件开始处。
-FileOutputStream(Stringname): 创建一个向具有指定名称的文件中写入数据的输出文件流。
-FileOutputStream(Stringname,Boolean append):创建一个向具有指定name
的文件中写入数据的输出文件流。如果第二个参数为true
,则将字节写入文件末尾处,而不是写入文件开始处。
(3)示例:
import java.io.*;
public class FileOutputStreamDemo
{
public static voidmain(String[] args)
{
FileOutputStreamfos=null;//创建输出流
try
{
fos=newFileOutputStream("Demo.txt");
fos.write("aaaaaa".getBytes());//写数据
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fos!=null)
fos.close();//关闭流资源
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
13、InputStream类
(1)InputStream类是一个抽象类,是表示字节输入流的所有类的超类。
(2)主要方法:
-void close():关闭此输入流并释放与该流关联的所有系统资源。
-abstract intread(): 从输入流中读取数据的下一个字节。返回下一个数据字节;如果到达流的末尾,则返回-1
。
-intread(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组b
中。返回读入缓冲区的总字节数,如果因为已经到达流末尾而不再有数据可用,则返回-1
。
-intread(byte[] b,int off,int len):将输入流中最多len
个数据字节读入byte 数组。返回读入缓冲区的总字节数,如果因为已经到达流末尾而不再有数据可用,则返回-1
。
14、FileInputStream类
(1)FileInputStream类是InputStream类的一个子类,用于从文件系统中的某个文件中获得输入字节。
(2)主要方法:
-FileInputStream(Filefile):通过打开一个到实际文件的连接来创建一个FileInputStream
,该文件通过文件系统中的File
对象file
指定。
-FileInputStream(Stringname):通过打开一个到实际文件的连接来创建一个FileInputStream
,该文件通过文件系统中的路径名name
指定。
-intavailable():返回从此输入流读取(或跳过)的估计字节数。
(3)示例:
import java.io.*;
public class FileInputStreamDemo
{
publicstatic void main(String[] args)
{
FileInputStreamfis=null;//创建读取流
try
{
fis=newFileInputStream("Demo.txt");
byte[]buf=new byte[1024];
intlen=0;
//读数据
while((len=fis.read(buf))!=-1)
{
System.out.println(newString(buf,0,len));
}
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fis!=null)
fis.close();//关闭流资源
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
15、字节流练习:复制一个图片。
思路:
-用字节流读取流对象和图片关联。
-用字节写入流对象创建一个图片文件,用于存储取到的图片数据。
-通过循环读写,完成数据的存储。
-关闭资源。
import java.io.*;
public class PicCopy
{
public static voidmain(String[] args)
{
//创建输入输出流
FileInputStreamfis=null;
FileOutputStreamfos=null;
try
{
fis=new FileInputStream("Demo.jpg");
fos=newFileOutputStream("DemoCopy.jpg");
byte[]buf=new byte[1024];
int len=0;
//从原文件中读取数据并写入到新文件中
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
//关闭流资源
try
{
if(fis!=null)
fis.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
try
{
if(fos!=null)
fos.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
16、BufferedOutputStream类
(1)BufferedOutputStream类实现缓冲的输出流。
(2)主要方法:
-BufferedOutputStream(OutputStreamout):创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
-void flush():刷新此缓冲的输出流。
-voidwrite(byte[] b,int off,int len):将指定 byte 数组中从偏移量off
开始的len
个字节写入此缓冲的输出流。
-voidwrite(int b):将指定的字节写入此缓冲的输出流。
17、BufferedInputStream类
(1)BufferedInputStream类为另一个输入流添加一些功能,可以实现缓冲输入。
(2)主要方法:
-BufferedInputStream(InputStreamin):创建一个 BufferedInputStream
并保存其参数,即输入流in
,以便将来使用。
-intavailable():返回从此输入流读取(或跳过)的估计字节数。
-void close():关闭此输入流并释放与该流关联的所有系统资源。
-int read():参见 InputStream
的 read
方法的常规协定。
-intread(byte[] b,int off,int len):从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。返回读取的字节数;如果已到达流末尾,则返回-1
。
18、字节流缓冲区练习:复制一个图片文件。
import java.io.*;
public class BufStreamDemo
{
publicstatic void main(String[] args)
{
//创建输入输出流
BufferedInputStreambis=null;
BufferedOutputStreambos=null;
try
{
bis=newBufferedInputStream(new FileInputStream("Demo.jpg"));
bos=newBufferedOutputStream(new FileOutputStream("DemoCopy_1.jpg"));
byte[]buf=new byte[1024];
intlen=0;
//从原文件读取数据并写入到新文件中
while((len=bis.read(buf))!=-1)
{
bos.write(buf,0,len);
}
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
finally
{
//关闭流资源
try
{
if(bis!=null)
bis.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
try
{
if(bos!=null)
bos.close();
}
catch(IOExceptione)
{
System.out.println(e.toString());
}
}
}
}
19、读取键盘录入
System.in对应标准输入设备,是InputStream类型的,可以读取从键盘输入的数据。
示例:
通过键盘录入数据,当录入一行数据后就将该行数据进行打印。如果录入的是over那么就停止录入。
20、InputStreamReader类
(1)InputStreamReader类Reader类的一个子类,是字节流通向字符流的桥梁,可以将字节流转换为字符流。
(2)主要方法:
-InputStreamReader(InputStreamin):创建一个使用默认字符集的 InputStreamReader。
-intread(char[] c,int off,int len):将字符读入数组中的某一部分。
(3)示例:
读取键盘录入,将录入的数据打印。
import java.io.*;
public class ReadIn
{
public static voidmain(String[] args)throws IOException
{
BufferedReaderbr=new BufferedReader(new InputStreamReader(System.in));//创建用于读取键盘录入的流
Stringline=null;
//从键盘读取数据
while((line=br.readLine())!=null)
{
if("over".equals(line))
break;
System.out.println(line);
}
}
}
21、OutputStreamWriter类
(1)OutputStreamWriter类是Writer类的一个子类,是字符流通向字节流的桥梁,可以将字节流转换为字符流。
(2)主要方法:
-OutputStreamWriter(OutputStream out): 创建使用默认字符编码的OutputStreamWriter。
-void write(char[] c,int off,int len):写入字符数组的某一部分。
-void writer(int c):写入单个字符。
(3)示例:
从键盘录入数据,并将录入的数据输出到文件中。
import java.io.*;
public class ReadIn
{
publicstatic void main(String[] args)throws IOException
{
BufferedReaderbr=new BufferedReader(new InputStreamReader(System.in));//创建从键盘读取录入的流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Demo.txt")));//创建对文件写入数据的流
Stringline=null;
//读取键盘数据并写入文件
while((line=br.readLine())!=null)
{
if("over".equals(line))
break;
bw.write(line);
bw.newLine();
bw.flush();
}
//关闭流资源
br.close();
bw.close();
}
}
注意:通常涉及到字符编码转换时,需要用到转换流。
22、流操作基本规律
(1)明确源和目的
-源:输入流:InputStream,Reader
- 目的:输出流:OutputStream,Writer
(2)操作的数据若是纯文本用字符流,若不是用字节流。
23、File类
(1)File类是用来将文件或文件夹封装成对象,方便对文件或文件夹的属性信息进行操作,File对象可以作为参数传递给流的构造函数。
(2)主要方法:
-File(Stringpathname):通过将给定路径名字符串转换为抽象路径名来创建一个新File
实例。
-File(Fileparent,String child):根据 parent 抽象路径名和 child 路径名字符串创建一个新File
实例。
-File(Stringparent,String child):根据 parent 路径名字符串和 child 路径名字符串创建一个新File
实例。
-booleancanRead():测试应用程序是否可以读取此抽象路径名表示的文件。
-booleancanWrite():测试应用程序是否可以修改此抽象路径名表示的文件。
-booleancreateNewFile():在指定位置创建文件,若创建成功返回true,若文件已存在,则不创建返回false。和输出流不一样,输出流对象一建立就创建文件,且若文件已存在会覆盖。
-boolean delete():
删除此抽象路径名表示的文件或目录。当且仅当成功删除文件或目录时,返回true
。
-void deleteOnExit():在程序退出时删除指定文件。
-boolean exists():
测试此抽象路径名表示的文件或目录是否存在。
-StringgetAbsolutePath():返回此抽象路径名的绝对路径名字符串。
-StringgetName():返回由此抽象路径名表示的文件或目录的名称。
-StringgetParent():返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null
。
-StringgetPath():将此抽象路径名转换为一个路径名字符串。返回的是相对路径。
-booleanisAbsolute():测试此抽象路径名表示的文件是否是一个目录。
-booleanisDirectory():判断文件对象是否为目录,需先判断文件对象表示的文件或目录是否存在。
-booleanisFile():判断文件对象是否为文件,需先判断文件对象表示的文件或目录是否存在。
-String[]list():返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。调用该方法的file对象必须是封装了一个目录,且该目录必须存在。
-String[]list(FilenameFilter filter):返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。
-staticFile[] listRoots():列出可用的文件系统根。
-File[]listFiles():返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
-File[]listFiles(FileFilter filter): 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
-booleanmkdir():创建文件夹(目录)。只能创建一级目录。
-booleanmkdirs():可创建多级文件夹。
(3)递归:递归就是函数自已调用自己。使用递归时要限定条件,并且要注意递归的次数,尽量避免内存溢出。
当要列出指定目录下所有文件包括指定目录中的文件时,可以用递归。如以下程序是要获取D:\Test下的所有文件。
import java.io.*;
public class FileDemo2
{
public static void main(String[] args)
{
File file=newFile("D:\\Test");//创建文件对象
showDir(file);
}
public static void showDir(File file)//定义列出目录下所有文件的方法
{
File[] files=file.listFiles();
for(File f:files)
{
if(f.isDirectory())
showDir(f);
else
System.out.println(f);
}
}
}
(4)、练习:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,建立一个java文件列表文件。
思路:
-对指定的目录进行递归。
-获取递归过程中所有的java文件的路径。
-将这些路径存储到集合中。
-将集合中的数据写入到一个文本文件中。
import java.io.*;
import java.util.*;
public class FileTest
{
public static void main(String[] args)
{
File dir=newFile("D:/Test");//创建文件对象
List<File> list=newArrayList<File>();//创建集合用于存储文件对象
fileToList(list,dir);
File file=newFile("D:/Test/filelist.txt");
if(!file.exists())
{
try
{
file.createNewFile();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
writeToFile(list,file);
}
//定义将文件路径存入集合中的方法
public static void fileToList(List<File> list,File dir)
{
File[] files=dir.listFiles();
for(File f:files)
{
if(f.isDirectory())
fileToList(list,f);
else
{
if(f.getName().endsWith(".java"))
list.add(f);
}
}
}
//定义将文件路径从集合中取出并写入指定文件中的方法
public static voidwriteToFile(List<File> list,File file)
{
BufferedWriter bw=null;
try
{
bw=newBufferedWriter(new FileWriter(file));
for(File f:list)
{
Stringpath=f.getAbsolutePath();
bw.write(path);
bw.newLine();
bw.flush();
}
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(bw!=null)
bw.close();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
24、Properties
(1)Properties是hashtable的子类。其具备map集合的特点,而且它里面存储的健值对都是字符串,是集合中和IO技术相结合的集合容器,Properties
可保存在流中或从流中加载,其特点是可以用于键值对形式的配置文件。在加载数据时,需要数据有固定格式:键=值。
(2)主要方法:
-Properties():创建一个无默认值的空属性列表。
-ObjectsetProperty(String key,String value):设置元素。返回属性列表中指定键的旧值,如果没有值,则为null
。
-StringgetProperty(String key):用指定的键在此属性列表中搜索属性。返回属性列表中具有指定键值的值。
-Set<String>stringPropertyNames():返回此属性列表中的键集。
-voidload(InputStream in):从输入流中读取属性列表(键和元素对)。
-voidload(Reader r):按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
-voidlist(PrintStream out):将属性列表输出到指定的输出流。
-voidlist(PrintWriter out):将属性列表输出到指定的输出流。
-voidstore(OutputStream out,String comment):将此 Properties
表中的属性列表(键和元素对)写入输出流。
-voidstore(Writer w,String comment):将此Properties
表中的属性列表(键和元素对)写入输出流。
(3)示例:将指定文件中的属性列表读取到集合中,修改属性值后将修改结果保存回文件中。
import java.io.*;
import java.util.*;
public class PropDemo
{
public staticvoid main(String[] args)throws IOException
{
Properties pro=new Properties();//创建Properties对象
FileReader fr=new FileReader("D:/Test/Prop.txt");
pro.load(fr);//从流中获取数据
pro.setProperty("bb","1111");//修改数据
FileWriter fw=new FileWriter("D:/Test/Prop.txt");
pro.store(fw,"");//将修改后的数据保存回文件
fr.close();
fw.close();
}
}
25、打印流
(1)打印流包括PrintStream和PrintWriter两个类,分别为FileOutputStream和Writer的子类,打印流提供了打印方法,可以将各种数据类型的数据都原样打印。
(2)PrintStream:即字节打印流,其构造函数可以接收的参数类型可以是file对象,字符串路径和字节输出流。
(3)PrintWriter:即字符打印流,其构造函数可以接收的参数类型可以是file对象,字符串路径和字节输出流和字符输出流。
26、序列流
(1)序列流即SequenceInputStream,是InputStream的子类,可以对多个输入流进行合并。
(2)构造函数:
-SequenceInputStream(InputStreams1,InputStream s2)
-SequenceInputStream(Enumeration<?extends InputStream> e)
(3)示例:将多个文件的内容复制到一个文件
import java.io.*;
import java.util.*;
public class SeqDemo
{
public static void main(String[]args)throws IOException
{
Vector<FileInputStream>vec=new Vector<FileInputStream>();//创建集合
vec.add(newFileInputStream("D:/Test/Demo1.txt"));
vec.add(newFileInputStream("D:/Test/Demo2.txt"));
Enumeration<FileInputStream> en=vec.elements();
SequenceInputStream sis=newSequenceInputStream(en);//创建序列流并合并两个输入流
FileOutputStream fos=newFileOutputStream("D:/Test/Demo12.txt");//创建输出流
byte[] buf=new byte[1024];
int len=0;
//读取数据并写入新文件中
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
//关闭流资源
sis.close();
fos.close();
}
}
27、ObjectOutputStream
(1)ObjectOutputStream是OutputStream的一个子类,可以将 Java 对象的基本数据类型和图形写入 OutputStream,只能将支持 java.io.Serializable 接口的对象写入流中。可以使用 ObjectInputStream 读取(重构)对象。
(2)Serializable接口: Serializable 接口可以让实现其的类启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化
(3)构造方法:ObjectOutputStream(OutputStreamout):创建写入指定 OutputStream 的 ObjectOutputStream。
(4)特有方法:voidwriteObject(Object o):将指定的对象写入 ObjectOutputStream。
28、ObjectInputStream
(1)ObjectInputStream是InputStreamr的一个子类,可以对以前使用ObjectOutputStream 写入的基本数据和对象进行反序列化。
(2)构造函数:ObjectInputStream(InputStreamin):创建从指定 InputStream 读取的 ObjectInputStream。
(3)特有方法:ObjectreadObject():从 ObjectInputStream 读取对象。返回从流读取的对象。
(4)示例:将Person类对象存入一个文件,再从该文件读取Person对象。
import java.io.*;
public class ObjStrDemo
{
public static void main(String[]args)throws Exception
{
writeObj();
readObj();
}
public static void writeObj()throws Exception//定义将对象写入文件中的方法
{
ObjectOutputStream oos=newObjectOutputStream(new FileOutputStream("D:/Test/Obj.txt"));
oos.writeObject(new Person("zhangsan",22));
oos.close();
}
public static void readObj()throws Exception//定义从文件读取对象的方法
{
ObjectInputStream ois=newObjectInputStream(new FileInputStream("D:/Test/Obj.txt"));
Personp=(Person)ois.readObject();
System.out.println(p);
ois.close();
}
}
class Person implements Serializable//定义Person类实现Serializable
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String toString()
{
returnthis.name+"..."+this.age;
}
}
29、管道流
(1)管道流包括PipedInputStream和PipedInputStream,分别是InputStream和OutputStream的子类,输入输出可以直接进行连接,通过结合线程使用。是涉及到多线程的IO流技术。
(2)构造方法:
-PipedInputStream(PipedOutputSteam src)
-PipedOutputSteam(PipedInputStream p)
30、RandomAccessFile类
(1)随机访问文件,自身具备读写的方法,内部封装了一个数组,且通过指针对数组的元素进行打操作,可以通过getFilePointer获取指针位置。通过skipBytes(int x)和seek(int x)来达到随机访问。其完成读写的原理是内部封装了字节输入流和字节输出流。该类只能操作文件,且操作文件还有模式。若该类对象的构造函数中操作模式为只读(r),不会创建文件,会去读取一个已存在的文件,若文件不存在则会出现异常,若该类对象的构造函数中操作模式为读写(rw),若要操作的文件不存在则会自动创建,若文件不存在则直接使用不会覆盖。
(2)特点:该类不是IO体系中的子类,而是直接继承自Object。该类只能操作文件。操作文件有模式:r,rw,rws,rwd,分别表示:以只读方式打开,打开以便读取和写入,打开以便读取和写入,对于"rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备,打开以便读取和写入,对于"rw",还要求对文件内容的每个更新都同步写入到底层存储设备。
(3)构造方法:
-RandomAccessFile
(
File
file,
String
mode)
-
RandomAccessFile
(
String
name,
String
mode)
31、DateInputStream和DateOutputStream
(1)DateInputStream和DateOutputStream是可以用于操作基本数据类型的数据的流对象。
(2)构造方法:
-
DataInputStream
(
InputStream
in)
-
DataOutputStream
(
OutputStream
out)
32
、ByteArrayInputStream和ByteArrayOutputStream
(1)ByteArrayInputStream和ByteArrayOutputStream分别是InputStream和OutputStream的子类,是用于操作字节数组的流对象。ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。ByteArrayOutputStream
实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()
和toString()
获取数据。
(2)特点:
-ByteArrayInputStream在构造的时候,需要接收数据源,且数据源是一个字节数组。
-ByteArrayOutputStream在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长的字节数组,即数据目的地。
-因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行关闭流动作。
33
、字符编码
(1)编码:字符串变成字节数组。str.getBytes(charsetName),将字符串以指定编码表进行编码变成字节数组。
(2)解码:字节数组变成字符串。newString(byte[],charsetName),将指定字节数组以指定编码表变成字符串。