IO流:input output
1、概念:输入输出流:负责数据的传输
2、划分:
按照流向分:
输入流:就是在读取外围设备上的数据
输出流:就是往外围设备上写入数据
按照数据分:
字节流:
字符流:专门用来处理字符数据的流对象,其实这些对象的内部使用的还是字节流
因为文字最终也是字节数据,只不过通过字节流读取了对象的字节数,没有对这些字节直接操作,而是去查了指定的编码表。
简单说字符流:就是字节流+编码表。
3、IO流常见积累:
字节流的抽象基类:
InputStream(读字节)OutputStream(写字节)
字符流的抽象基类:
Reader Writer
4、读写操作:
文件是硬盘对数据的体现单元。
Flush():要通过刷新才能将数据写到指定的目的地,流还可以继续使用。
Close():在写数据的时候是在调用windows中的资源,当写入完成之后要关闭资源,close具备刷新和关闭的功能,先刷新后关闭,因为流对象最终使用的是本地系统的资源完成写入后要对锁使用的系统资源进行释放,所以close工作必须得有。
注意:在关闭资源后再往目的地写数据时,发生异常,不能再写入。
void close(){
flush();
Close code...
}
异常怎么处理?
final String LINE=System.getProperty("line");//换行
fileWriter fw=null;
try{
fw=new FileWriter("d:\\Demo.txt");
fw.write("hhe"+LINE+"jaja");
}catch(IOException e){
(e.toString()+"....");
}finally{
If(fw!=null)
try{
fw.close();
}catch(IOException e){
e.printStackTrace();
}
}
想要完成对已有文件的续写,只要在构造函数中多加一个boolean来的参数true即可。
1、Reader:读是不需要关闭资源的。
同样没有空参数构造函数,因为必须要有东西才能读取,查阅API.找到字符读取流Reader中的用于读取字符文件的对象FileReader:对该对象以创建必须在构造时,指定要被读取的数据源文件,其实创建FileReader,就是创建流对象并和指定源相关联。读到最后结尾有一个结束标记,返回-1.
2、reader(char[])读取的不是字符值而是字符数。
实现代码:
FileReader fr=newFileReader("c:\\Demo.txt");
char[] buf=newchar[4096];//一般定义存储单元长度为4096;
int len=0;
while((len=fr.read(buf))!=-1){
System.out.println(len+""+new String(buf));
}
这种方式比第一种方法效率要高。
需求:对文件进行复制
实现代码:
FileReader fr=null;
FileWriter fw=null;
try{
//创建一个字符读取流读写和源数据关联
fr=newFileReader("c:\\httpdownload.txt");
//创建一个存储数据的目的地。
fw=newFileWriter("C:\\1.txt");
/*第一种方式
int ch=0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
*/
//第二种方式:
char[] buf=newchar[1024];
int len=0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);//读到几个写几个。
}
}catch(IOException e){}
finally{
try{
fr.close();
}catch(IOExceptione){
e.printStackTrace();
}
try{
fw.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
IO流的操作规律:
1、明确体系:
数据源:InputStreamReader
数据汇:OutputStreamWriter
2、明确数据:
数据源:是否为纯文本数据
是:Reader
否:InputStream
数据汇:
是:Wirter
否:OutputStream
从上就可以明确具体要使用哪一个体系了,剩下的就是要明确使用这个体系中的哪个对象
3、明确设备:
数据源:
键盘:System.in
硬盘:FileXXX
内存:数组
网络:socket
数据汇:
键盘:System.out
硬盘:FileXXX
内存:数组
网络:socket
4、额外功能:
1、需要转换?
是:使用转换流:InputStreamReader OutputStreamWriter
2、需要高效?
是:缓冲区:Buffered
练习:
1、复制一个文本文件
1、明确体系:
源:InputStream Reader
目的:OutputStream Write:
2、明确数据:
源:是纯文本:Reader
目的:是纯文本:Writer
3、明确设备:
源:硬盘上的一个文件。FileReader
目的:硬盘上的一个文件。FileWriter
4、额外功能:
需要高效:使用BufferedReader
BufferedReader bufr=new BufferedReader(newFileReader("a.txt"));
BufferedWriter bufw=new BufferedWriter(newFileWriter("b.txt"));
2、读取键盘录入,将数据存储到一个文件中
1、明确体系:
源:InputStream Reader
目的:OutputStream Writer
2、明确数据:
源:是纯文本 Reader
目的:是纯文本:Writer
3、明确设备:
源:键盘System.in
目的:硬盘文件:FileWriter
InputStream in=System.in;
FileWriter fw=new FileWriter("a.txt");
4、额外功能:
需要:因为源明确的体系为Reader,可是源设备是键盘,所以为了方便与操作文本数据,将源转成字符流,需要转换流InputStreamReader;
Eg:
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fw=new FileWriter("a.txt");
高效:需要Buffered
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new FileWriter("a.txt"));
3、读取一个文本文件,将数据展现在控制台上
1、明确体系:
源:InputStream Reader
目的:OutputStream Writer
2、明确数据:
源:是纯文本文件Reader
目的:不是纯文本文件OutputStream
3、明确设备:
源:硬盘文件FileReader
目的:控制台System.out
FileReader fr=new FileReader("a.txt");
OutputStream out=System.out;
4、额外功能:
需要:因为源明确是Reader.确定的是Writer体系,可是目的设备是控制台
所以为了方便操作字符数据,需要字符流,将目的转成字节,需要转换流。
同时需要高效
BufferedReader bufr=new BufferedReader(newFileReader("a.txt"));
BufferedWriter bufw=new BufferedWriter(newOutputStreamWriter(System.out));
4、读取键盘录入将数据展现在控制台上
1、明确体系:
源:InputStream reader
目的:OutputStream
2、明确数据:
源:是纯文本Reader
目的:是纯文本Writer
3、明确设备:
源:键盘:System.in
目的:控制台:System.out
InputStream in=System.in;
OutputStream out=System.out;
4、额外功能:
因为处理的数据是文本数据,同时确定是字符流体系,为了方便操作字符数据可以将源和母的都转成字符流,使用转换流。为了提高效率。使用buffer
BufferedReader bufr=new BufferedReader(newInputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(newOutputStreamWirter(System.out));
5、读取一个文本文件将文件按照指定的编码表UTF-8进行存储,保存到另外一个文件中
1、明确体系:
的:OutputStream Writer
2、明确数据:
源:是纯文本文件 Reader
目的:纯文本文件Writer(不懂
3、明确设备:
源:硬盘:FileReader
目的:硬盘:FileWriter
FileReaderfr=new FileReader("a.txt");
FileWriterfw=new FileWriter("b.txt");
4、额外功能:
因为目的中虽然是一个文件,但是需要指定编码表,而直接操作文本文件的FileWriter本身是内置的本地默认编码表,无法明确具体的指定码表。
这时需要转换功能,OutputStreamWriter,而这个转换需要接受一个字节输出流,而且对应的目的是一个文件,这时就使用字节输出流中的操作文件的流对象。
FileOutputStream
FileReaderfe=new FielReader("a.txt");
OutputStreamWriterosw=new OutputStreamWriter(
NewFileOutputStream("b.txt"),"UTF-8");
BufferedReaderbufr=new BufferedReader(new FileReader("a.txt"));
BufferedWriterbufe=new BufferedWriter(new OutputStreamWriter(newFileOutputStream("b.txt"),"UTF-8"));
3、File类:
作用:用于将文件或者文件夹封装成对象。
由来:流的功能貌似很强大,但是流有局限性,只能操作文件中的数据;但是对于文件,比如说文件大小等是流不能操作的,还有流不能操作文件夹,File不仅代表文件、也代表文件夹。
1、构造方法:
File创建的封装的文件或者文件夹是可以存的,也可以不存的,流是必须有源文件的。
实现代码:
File f1=newFile("c:"+File.separator+"a.txt");
File f2=newFile("c:\\","a.txt");
File f=newFile("c:\\");\\把目录封装对象作为父目录
File f3=newFile(f,"a.txt");
2、一般方法:
1、创建:
BooleancreateNewFile();
如果该文件不存在,则创建,如果已存在、则不创建、不会像输出流一样覆盖
Dir();创建文件夹
2、删除:
Booleandelete();java删除是不走回收站的
DeleteOnExit();当JVM退出时删除,不是立马删除
文件在却删不了,只要流和文件相关联,只要流不断,就不能删除,比如说播放DVD时,正在播放的文件是不能被删除的,系统级文件也是不能删除的。
3、获取:
getAbsolutePath();获取绝对路径
getPath();获取路径
getParent();获取父目录
getName();获取文件名
lastModified();获取最后一次修改时间
Long length();长度说
4、判断:
Exists();判断文件是否存在
isDirectory();目录是否存在,不存在时为假
isFile();文件是否存在,也就说必须选它的先存在
compareTo();复制剪切
listRoots();获取根目录。也就是盘符
getFreeSpace();获取剩余空间
getTotalSpace();总容量
getUsableSpace();获取可用空间。
5、比较重要的方法:
a) List();当前目录下文件和文件夹的名称,包含创建文件或者文件夹
Eg:
File dir=new File("c:\\");
String[] names=dir.list();
for(String name:names){
Sop(name);
}
b) listFiles();拿到当前目录下所有的文件对象。
Eg:
File dir=new File("c:\\");
File[] files=dir.listFiles();
for(File f:files){
Sop(f.toSttring());
}
c) 过滤器:
Eg:
public class FilterBySuffix imlements FilenameFilter(){
private String suffix;
public FilterBySuffix(String suffix){
super();
this.suffix=suffix;
}
public boolean accept(File dir,String name){
return name.endsWith(suffix);
}
}
d) 递归:函数自身直接或者间接的调用自身就是递归,当一个功能被重复使用而且使用过程中参与运算的数据不断在发省着变化,这时候可以使用递归这种手法来解决该问题。
前提:1、必须要定义条件,否则会栈溢出。
2、要控制递归次数
这两个前提,那个出现了问题,都会导致栈内存溢出。
练习:删除一个带内容的目录:
publics static void main(String[] args){
File dir=newFile("");
removeDir(dir);
}
public static void removeDir(File dir){
File[]files=dir.listFiles();
for(File f:files){
If(f.isDirectory())
removeDir(f);
else
Sop(f.delete());
}
Sop(dir+""+dir.delete);
}
3、Properties:(重点、必须会)
用于存储键值的map集合中的Hashtable的子类,表示一个持久的属性集。
特点:
1、它没有泛型
2、它里面的键和值都是固定的类型----字符串
3、它自己有特有的存储和取出的动作。
4、它有和IO流相关的方法。
5、它经常用于简单配置文件的解析。
实现代码:
privatestatic void method4() throws IOException {
Properties prop=new Properties();
//从持久化的设备将指定格式的键值信息加载到Properties集合中
FileInputStream fis=newFileInputStream("info.properties");
prop.load(fis);
//将集合当中的某些数据进行改动
prop.setProperty("06", "wangca");//将06键对应的改为旺财,但是此时硬盘中文件还没改
FileOutputStream fos=newFileOutputStream("info.properties");
prop.store(fos,"");//将修改后的内容持久化存储。
prop.list(System.out);
fis.close();
fos.close();
}
privatestatic void method3() throws IOException {
Properties prop=new Properties();
prop.setProperty("01", "zhangsan");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("02", "lisi");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("06", "wangwu");
/*
* 将集合中的键值信息进行持久化存储
* */
FileOutputStream fos=newFileOutputStream("info.properties");
prop.store(fos,"haha");//注释信息
fos.close();
}
privatestatic void method2() throws FileNotFoundException {
Propertiesprop=new Properties();
prop.setProperty("01","zhangsan");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("02","lisi");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("06","wangwu");//
prop=System.getProperties();//获取系统信息
prop.list(newPrintStream("sys.txt"));//将系统信息转到指定的文件当中
}
publicstatic void method1(){
Properties prop=new Properties();
prop.setProperty("01", "zhangsan");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("02", "lisi");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
prop.setProperty("06", "wangwu");//不能用put,因为put可以存储任意类型的。而它只能存字符串。
Set<String>keySet=prop.stringPropertyNames();
for(String key:keySet){
Stringvalue=prop.getProperty(key);
System.out.println(key+":"+value);//键相同值覆盖
}
}
练习:一个应用软件运行的次数
参考:PropertiesTest.java
/**
* @param args
* 记录应用程序使用次数
* 如果满足5次,要给出提示:软件使用次数已到请注册!
* 思路:
* 1、其实需要一个计数器,count
* 2、这个计数器,不能仅仅存储在内存中、需要持久化
* 3、每次软件启动都要读取该文件中已有的次数,并取出对其进行自增,再重新存回去。
* 4、为了保证文件中存储的数据有意义,需要给数据起个名字,出现了键值对
* 5、该数据还在硬盘上,需要使用IO技术,还需要map集合,最好的集合就是properties
* @throws IOException
*/
publicstatic void main(String[] args) throwsIOException {
//将配置文件封装成file对象,为什么?因为可以调用方法去判断。
File confFile=newFile("time.properties");
if(!confFile.exists())
confFile.createNewFile();//自己创建可能没有数据
FileInputStream fis=newFileInputStream(confFile);
//创建Properties集合
Properties prop=new Properties();
//加载流中的数据
prop.load(fis);
//创建一个计数器
intcount=0;
Stringvalue=prop.getProperty("time");//在这里有没有数据都没关系因为下面有判断。
if(value!=null){
count=Integer.parseInt(value);
if(count>=5){
System.out.println("您的试用次数已到,请注册!");
return;//
}
}
count++;
prop.setProperty("time",count+"");
FileOutputStream fos=newFileOutputStream(confFile);
prop.store(fos,"");
}
}