46 Java中的IO流技术.docx
《46 Java中的IO流技术.docx》由会员分享,可在线阅读,更多相关《46 Java中的IO流技术.docx(23页珍藏版)》请在冰豆网上搜索。
46Java中的IO流技术
Java中的IO流技术
1.IO流(Input&OUtput)用来处理设备之间的数据传输,IO系统的主要目的是对数据进行读写操作。
2.Java对数据的操作是通过流的方式,输入流和输出流都是对象。
3.Java中用于操作流的对象都存在于IO包中。
4.IO流按照操作数据分为两种:
字节流和字符流。
5.IO流按照流向分为:
输入流和输出流。
输入需要读read方法,输出需要写write方法。
注意:
输入和输出是基于Java程序而言的,而Java程序一般又是在内存中运行,所以也可以看做是基于内存而言的,IO系统的数据流向是以Java程序为参照物。
将外设的数据读入内存称为读,即输入;将内存中数据写到外设中,称为写,即输出。
6.Java的I/O:
(1)I/O操作的目的:
从数据源(多种多样,如文件、键盘、网络等等)当中读取数据,以及将数据写入到数据目的地(如文件、屏幕、网络等等)当中;
(2)I/O的流向:
方向需要参照物,相对而言,对于java程序本身而言,需要程序读取,即输入流,需要写到文件里,则就是输出流;
(3)流的概念:
输入流,输出流,就像水流一样。
就像管道一样,是一点一点的进行的传输;在数据源与目的地之间建立了一个管道;
(4)I/O的分类:
①输入流与输出流;②字节流与字符流;③节点流与处理流;
7.以前只存在字节流,其实字节流可以读取任何文件。
但是后来为了国际化统一,推出了字节流。
由于不同的国家有不同的文字,同时又有自己的文字编码表,为了国际统一化,推出了国际统一编码Unicode编码。
8.字符流的由来:
字节流读取文字字节数据后,不直接操作,而是先查询指定的编码表,获取对应的文字,再对这个文字进行操作。
所以,简单地说,字符流就是字节流+编码表。
字符流是以字符为处理单位的。
9.字节流的两个顶层父类(抽象基类):
InputStream和OutputStream。
10.字符流的两个顶层父类(抽象基类):
Reader和Writer。
11.对上述四个基类加以说明:
由这四种基类派生出来的子类名称都是以父类的名称作为子类名称后缀的。
如InputStream的子类FileInputStream;Reader的子类FileReader等。
而且这些子类的前缀都代表了这些子类的功能。
12.I/O的核心类:
InputStream和OutputStream这两个都是抽象类,父类;
所有的字节输入流的类都是InputStream的子类,所有的字节输出流都是OutStream的子类。
其中两个常用的子类是FileInputStream和FileOutputStream;这些类都是属于java.io.*;包的,使用前需要导入此包,importjava.io.*;子类FileInputStream是用来读取硬盘中文件的数据,子类FileOutputStream是用来向硬盘中的文件写入数据。
(5)read会返回一个读取字节的个数,调用时有三个参数,当没有读到数据时,返回-1;write也是三个参数。
(6)byte[]b是比特类型的数组,off是偏移量,len是读取的最大长度。
13.如果要操作文字数据,建议优先考虑字符流,因为字符流就是基于这个目的出现的。
大文件读写,利用循环即可,判断依据是read方法的返回值,如果返回-1说明读取结束。
14.字符流:
字符输入流Reader和字符输出流Writer;Reader和Writer都是抽象类,就是用来让其他类继承的,但是都有几个构造方法,抽象类的构造方法是为子类创建对象初始化用的。
子类是FileReader与FileWriter;
调用方法如同字节流,只是数组是字符数组了,如
Intread(char[]c;intoff;intlen);字符流与字节流操作特别类似,只不过是字节数组和字符数组,读写方法的不同(-er)。
注意在读写之后要关闭读写方法。
15.实验:
将内存中的数据写到硬盘中指定的文件里。
(1)硬盘数据的基本体现就是文件,所以找到一个处理文件的类即可。
(2)创建一个可以向文件中写入字符数据的字符输出流对象;既然写数据,就必须在创建对象时就指定某个文件(用于存储数据的目的地),也就是说这个输出流类不能有空参数的构造方法。
(3)利用Writer对象的write方法,写入数据。
将数据写入到临时存储缓冲区中。
利用flush方法进行刷新,可以将数据写到文件中。
close方法关闭流和关闭资源执行时,先进行刷新,将缓冲区中的数据写入到文件中。
flush和close就相当于保存命令和关闭命令,关闭命令执行之前会提醒是否保存。
16.对文件操作时,如果文件不存在,就会创建此文件;如果文件存在,就会覆盖原来的数据(首先将原来数据清空,再写入新的数据)。
如果需要续
写原文件,可以在构造方法中加入true。
实现续写:
FileWriter(String fileName)
ConstructsaFileWriterobjectgivenafilename.
FileWriter(String fileName,boolean append)
ConstructsaFileWriterobjectgivenafilenamewithabooleanindicatingwhetherornottoappendthedatawritten.
17.实现换行:
staticfinalStringLINE_SEPARATOR=System.getProperty("line.separator");
18.字符流的使用方法:
相对于字节流,字符流也是有两个父类:
字符输入流Reader和字符输出流Writer。
其中常用的两个子类是:
FileReader和FileWriter。
这两个子类又有两个比较重要的方法:
read()和write();这两个方法与字节流的两个方法完全相似,差别仅在于输入参数一个是字节数组,一个是字符数组。
intread(char[]c,intoff,intlen);
voidwrite(char[]c,intoff,intlen);
19.IO流都需要抛出异常信息,而try{}又是闭合的,所以一般都是在try{}catch{}之外创建一个空引用,如FileWriterfw=null;然后在try{}括号内对引用进行赋予对象。
一般在finally{}语句中加入close方法,但是close方法需要单独再次try{}catch{},以防关闭此文件时出现异常。
20.读取文件。
找到了类FileReader。
(1)创建一个读对象,注意在生成读对象时,一定要指定一个要读取的文件,确实存在才可以,否则出现异常。
(2)read方法有几个,可以单个字符单个字符的读取,返回int类型的数,如果读完,则返回-1;还有个read方法读取字符串,返回读取字符个数,一次读取几个可以由字符数组的大小或者文件中是否生育多余字符决定。
21.节点流与处理流之间的关系:
处理流是用来装饰节点流的,给节点流添加新的功能的。
节点流就是被装饰者,而处理流就是装饰者。
如BufferedReader就可以用来装饰FileReader的,不仅可以装饰FileReader,而且可以装饰键盘读入,网络读入等等。
22.
23.Java中io系统中使用最多的就是装饰着模式。
24.“装饰者”模式:
装饰者和被装饰者,装饰者是给被装饰者添加新的功能的。
25.处理流:
ButteredReader,方法readLine,读取一行,当读到尾部的时候返回null。
26.BufferedReader介绍:
publicStringreadLine()throwsIOException//这是个读取一行的方法
生成BufferedReader对象的方法:
BufferedReaderin=newBufferedReader(newFileReader(“文件路径”));注:
接收的是一个Reader类型的对象。
27.大文件的读写方法:
实例一字节流:
//类的导入
importjava.io.*;
classTest6{
publicstaticvoidmain(String[]args){
//声明输入输出流的引用
FileInputStreamfil=null;
FileOutputStreamfos=null;
FileOutputStreamfos2=null;
try{
//生成代表输入输出流的对象
fil=newFileInputStream("g:
/javalianxi/io/from.txt");
fos=newFileOutputStream("g:
/javalianxi/io/to.txt");
fos2=newFileOutputStream("g:
/javalianxi/io/to2.txt");
//生成一个字节数组
byte[]buffer=newbyte[100];
while(true){
inttemp=fil.read(buffer,0,buffer.length);
if(temp==-1){
break;
}
fos.write(buffer,0,temp);
fos2.write(buffer,0,temp);
}
//fos.write(buffer,0,temp);
//Strings=newString(buffer);//把字节型数组转换成字符串
//s=s.trim();
//System.out.println(s);
/*for(inti=0;iSystem.out.println(buffer[i]);
}*/
}
catch(Exceptione){
System.out.println(e);
}
finally{
try{
fil.close();
fos.close();
}
catch(Exceptione){
System.out.println(e);
}
}
}
}实例二字符流:
importjava.io.*;
classTest7{
publicstaticvoidmain(String[]args){
FileReaderfr=null;
FileWriterfw=null;
try{
fr=newFileReader("g:
/javalianxi/io/from.txt");
fw=newFileWriter("g:
/javalianxi/io/to2.txt");
char[]buffer=newchar[1024];
while(true){
inttemp=fr.read(buffer,0,buffer.length);
if(temp==-1){
break;
}
fw.write(buffer,0,temp);
}
}
catch(Exceptione){
System.out.println(e);
}
finally{
try{
fr.close();
fw.close();
}
catch(Exceptione){
System.out.println(e);
}
}
}
}
28.作业:
将c盘中的一个文本文件复制到d盘中。
复制原理:
读取数据,粘贴:
写数据。
连读带写。
思路:
(1)读取数据源;
(2)将读取的源数据写到指定位置。
(1)读取一个写一个:
(2)用数组作为缓冲区
FileReaderfr=null;
FileWriterfw=null;
try{
fr=newFileReader("text1.txt");
fw=newFileWriter("copy2.txt");
//创建一个容器,用于缓存读取到的数据
char[]buf=newchar[BUFFER_SIZE];
//定义一个变量,存取读取到的数据的字节数
intlen=0;
for(;(len=fr.read(buf))!
=-1;){
fw.write(buf,0,len);
}
}catch(IOExceptione){
thrownewRuntimeException("读写失败");
}
finally{
if(fr!
=null)
try{
fr.close();
}catch(IOExceptione){
e.printStackTrace();}}
if(fw!
=null)
try{
fw.close();
}catch(IOExceptione){
e.printStackTrace();}
(3)复制文本文件图解:
flush方法可以把数据从缓冲区送入文件中。
close方法可以完成flush方法的功能。
29.字符流缓冲区:
BufferedReader和BufferedWriter
为了提高效率,引入了字符流的缓冲区。
缓冲区一定要有被缓冲的对象,故构造方法都不是空参数的。
(1)BufferedReader:
是类Reader的子类;
1构造方法:
2成员方法:
3特有方法:
readLine()方法
FileReaderfr=newFileReader("text2.txt");
BufferedReaderbr=newBufferedReader(fr);
Stringstr=null;
while((str=br.readLine())!
=null)
System.out.println(str);
④缓冲区BufferedReader中的read方法与父类Reader类中read方法的区别:
缓冲区BufferedReader中的read方法是重写了父类Reader类中read方法,前者是从缓冲区中读取数据,而后者是直接从内存中读取。
到了这一步,就可以直接操作缓冲区中的数据了,例如实现一行一行的读取。
4对于readLine方法,就是使用了读缓冲区中的read方法,将读取到的字符进行缓冲,(可以利用StringBuffer或StringBuilder来实现),并判断是否到了换行标记,将换行符前的缓冲数据(不包括换行符)变成字符串返回。
(2)BufferedWriter:
是类Writer的子类。
1构造方法:
2成员方法:
3特有方法:
newLine()方法就是把下面的语句进行了封装。
但是此方法只有在此对象中有。
下面的语句在任何地方都可以使用。
publicstaticfinalStringLINE_SEPARATOR=System.getProperty("line.separator");
System.out.print(LINE_SEPARATOR);//词句与System.out.println();功能相同。
(3)
30.自定义读取缓冲区:
packagesone.November29.am;
importjava.io.FileReader;
importjava.io.IOException;
publicclassMyBufferedReader{
privateFileReaderr;
privateintpos;
privateintcount;
privatechar[]buf=newchar[1024];
publicMyBufferedReader(FileReaderr){
super();
this.r=r;
}
publicintmyRead()throwsIOException{
if(count==0){
count=r.read(buf);
pos=0;
}
if(count<0)
return-1;
charch=buf[pos++];
count--;
returnch;
}
publicStringmyReadLine()throwsIOException{
StringBuildersb=newStringBuilder();
intch=0;
while((ch=myRead())!
=-1){
if(ch=='\t')
continue;
if(ch=='\n')
returnsb.toString();
sb.append((char)ch);
}
if(sb.length()!
=0)//防止最后一行读取不到,因为如果判断不到‘\n'就不会返回字符串
returnsb.toString();
returnnull;
}
publicvoidmyClose()throwsIOException{
//下午7:
38:
27
r.close();
}
}
31.装饰设计模式:
对一组对象的功能进行进行增强时,就可以是使用该模式进行问题的解决。
装饰和继承的区别:
相同点:
都可以对功能进行扩展;
不同点:
装饰比继承更为灵活。
装饰类和被装饰类必须同属于同一个接口或者父类。
被装饰类以参数传进装饰类即可。
如果对一个体系的任何类都需要进行功能的扩展,都要去创建一个子类,就会使体系变得十分的臃肿,这样显然不好。
如果这些类需要拓展的功能都是一样的,利用继承,是使这功能与具体的类相结合,但是可以从另外一个角度想,将这种需要拓展的功能进行单独的封装,哪个类需要拓展这样的功能,就把这个类和此功能进行关联。
例如:
BufferedWriter是装饰类,而Writer就是被装饰类。
BufferedReader是装饰类,而Reader就是被装饰类。
32.(了解即可)LineNumberReader类:
是BufferedReader的子类,对Reader进行装饰。
33.对四个掌握要好:
FileWriter、FileReader、BufferedWriter、BufferedReader。
34.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
35.字节流:
FileOutputStream的write方法,直接把数据写到目的地,不需要flush刷新方法,但是close方法是需要的。
FileInputStream类:
中有个方法available(),可以返回此文件可读的字节数目,使用时要慎用,一般适用于小文件。
36.字节流的练习:
复制一个MP3文件。
(1)自定义缓冲区:
FileInputStreamfis=newFileInputStream("e:
\\G.E.M.邓紫棋-泡沫.mp3");
FileOutputStreamfos=newFileOutputStream("e:
\\G.E.M.邓紫棋-泡沫2.mp3");
byte[]buf=newbyte[1024];
intlen=0;
while((len=fis.read(buf))!
=-1)
fos.write(buf,0,buf);
fis.close();
fos.close();
(2)利用缓冲区类:
BufferedInputStream和BufferedOutputStream
FileInputStreamfis=newFileInputStream("e:
\\G.E.M.邓紫棋-泡沫.mp3");
BufferedInputStreambufis=newBufferedInputStream(fis);
FileOutputStreamfos=newFileOutputStream("e:
\\G.E.M.邓紫棋-泡沫3.mp3");
BufferedOutputStreambufos=newBufferedOutputStream(fos);
intch=0;
while((ch=bufis.read())!
=-1){
bufos.write(ch);
}
bufis.close();
bufos.close();
(3)不利用循环,一次读取一次写入(创建一个很大的数组)
FileInputStreamfis=newFileInputStream("e:
\\G.E.M.邓紫棋-泡沫.mp3");
FileOutputStreamfos=newFileOutputStream("e:
\\G.E.M.邓紫棋-泡沫4.mp3");
byte[]buf=newbyte[fis.available()];//最好不要这样,因为文件很大时,创建的数组过大。
fis.read(buf);
fos.write(buf);
fis.close();
fos.close();
(4)速度特别慢:
读一个字节写一个字节,速度特别慢。
(千万不要使用这种方式)
FileInputStreamfis=newFileInputStream("e:
\\G.E.M.邓紫棋-泡沫.mp3");
FileOutputStreamfos=newFileOutputStream("e:
\\G.E.M.邓紫棋-泡沫5.mp3");
intch=0;
while((ch=fis.read())!
=-1)
fos.write(ch);
fis.close();
fos.close();
37.字符流不能操作媒体文件。
38.演示键盘录入:
需求:
读入键盘录入的数据,并打印在控制台上。
键盘本身就是一个标准的输入设备,对于java而言,这种设备有对应的对象。
InputStreami