流:
流分为输入输出流,流的作用就是设备之间的数据交换的一种方式,所谓的输出流(写功能)指的就是从内存中往其他地方写数据的流,输入流(读)就是从其他地方往内存中读取数据的流。
流分为字节流和字符流,这里的字符流其实就是字节流加上编码表,字节流有InputStream和OutputStream这两个类都是抽象的类,具体的详细用法参见后面的实例,字符流有Reader和Writer这里更加的明显的体现了输入流是读取数据,而输出流是写入数据的过程,这两个类也是抽象的,输入输出流的子类结尾一般都是以各自的父类来显示的,在实际的开发中最常用的就是FileWriter(String file)这个输出流了,注意这个流是没有无参的构造函数的,因为这里往一个文件中写入东西,必须的指定具体的文件名或者路径(其他的构造函数)
public class File{
public static void main(String []args) throws IOException{
FileWriter fw = new FileWriter("aa.txt");//这里如果当前的路径中没有这个文件就新建一个文件,如果有了就覆盖之前的,还是相当于重新建一个
fw.writer("HelloWorld");//这个方法是Writer类中的方法,用于向文件中写入一个字符串
fw.flush();//这个方法的作用就是刷新当前的流,用于将缓冲区中的数据写入文件中,否则上面的文件中是没有内容的
//fw.close();这个方法的作用和flush的作用是一样的,都可以讲缓冲区的数据写入文件中,但是当关闭了一个流之后就不能再这个流中写了,但是flush之后还可以继续写的
}
}
理解:在实际的操作记事本的时候,实际上也是一种流的操作,当打开记事本写东西的时候实际上就是以输出流的形式来往本地文件中写入东西的
(2016/01/13)晚上加班刚回来,时间有点晚了,今晚的学习任务很少
FileWrite类的构造函数,FileWriter(String file,true),注意这里的true表示的就是是不是可以在原文本的基础之上增加内容的,如果不是true(默认的也是false)当使用FileWriter来调用对象的Writer()方法的时候会新建一个文件来写,但是如果为true的话就会在源文件的基础之上来增加内容的。
FileWriter fw = null;
try{
fw = new FileWriter("G\\tt.txt");----------------------------------1,如果这里找不到相应的位置就会抛出异常,而且下面2处的代码也不会执行的(没有if(fw!=null)条件),因为这里没有找到文件,就不会的创建这个对象,为null的对象是没有clsoe方法的,所以就会抛出空指针的异常。
fw.writer("abc");
}
catch(IOException e){
Sysout.out.println("1234");
}
finally{
if(fw!=null){
try{
fw.close();-----------------------------------------2t
}
catch(Exception e){
e.message();
}
}
}
有上面的空指针异常,今天的开发中遇到了一个问题,之前一直不是很理解这个问题,但是今天调试代码的时候对这点还算有这比较深入的理解,就是equals方法的使用,在平时的使用中建议将常量放在前面,而变量放在后面作为被比较的对象,这样就会抛出空指针异常的一种情况:
if(("常量").equals(tt)){
这里使用常量在前的写法就回避了tt为空的一种情况,如果将tt写在前面的话,如果tt为null的话就会报空指针的,因为null是没有这个方法的。注意这点,养成一个良好的编写代码的习惯。
}
(2016/01/14)输入流(用于读取数据的操作流)
FileReader(String file)在这个类的对象中有两个方法,分别为reader()这个方法是一个个字符来读取的,reader(char[] char)是以一个字节数组来读取的,这两个方法的返回值都是Int类型的,reader()方法返回的是读取的字节数,为当前的阿斯科码表,当读到文件的结尾的时候返回值为-1(这是Java虚拟机在内部实现的),reader(char[] char)方法返回的是实际读取的当前的字节数。注在计算中中的任何信息都是以二进制文件的形式存储在计算中的。
eg:比如当前目录中有个文件,文件的名为demo.txt,文件中有adcde,内容。
public class FileReaderDemo{
public static void main(String []args){
FileReader fr = new FileReader("demo.txt");
int ch = fr.read();
Sysout.out.println(ch)//输出97,因为这里文件中的a是以二进制的形式保存在硬盘中的,所以在计算机中会输出97
Sysout.out.println((char)ch)//输出a
int ch1 = fr.read();
Sysout.out.println(ch1);//输出98,这里更加的体现了read()方法每次只读取一个字符的
//==========================================等同于上面代码==================================================
while((int ch = fr.read())!=-1){
Sysout.out.println(ch);
}
fr.close();//这里的只是简单的实例性的代码,前面还应该抛出异常
//========================================================================================================
}
}
字符数组的读取:
public class FileReaderDemo{
public static void main(String []args){
FileReader fr = new FileReader("demo.txt");
char [] cha = new Char[4];//表示的就是每次以四个字符来读取
int ch = fr.read(cha);
Sysout.out.println(ch)//输出4
Sysout.out.println((char)ch)//输出abcd
int ch1 = fr.read(cha);//输出1
Sysout.out.println(ch1);//ebcd,因为已经读完了把前面的替换之后,后面的就不会再去替换了
int ch2 = fr.read(cha) //输出-1
Sysout.out.println(ch2)//输出ebcd
//==========================================等同于上面代码==================================================
Int m = fr.read(cha);
while((m!=-1){
Sysout.out.println(m);
}
fr.close();//这里的只是简单的实例性的代码,前面还应该抛出异常
//========================================================================================================
}
}
实例代码(将一个文件中的内容复制到另一个文件中)
在这里首先的考虑到使用的是文件,所以使用字符流,在字符流中读取的操作和写入的操作有两个方法,分别为read(),和read(char []),其中第二种的效率高:
class Demo{
public static void main(String []args) throws IOException{
FileReader fr = new FileReader("demo.txt");//在这里是源文件
FileWriter fw = new FileWriter("copy_demo.txt");//这里也必须要有这个参数,这个参数就相当于写到那个文件中的
Int ch = fr.read();//这里的ch就相当于输入和输出流之间的一个桥梁
while(ch!=-1){
fw.writer();//在这里就是相当于读一个字符然后就写一个字符。
}
//此时读取的内容也许还在缓冲区中要将缓冲区的内容刷新到文件中,就要使用flush()方法或者close()方法来实现。
fw.close();
fr.close();
}
}
class Demo1{
public static void main(String[]args){
FileWriter fw = null;
FileReader fr = null;
try{
fw = new FileWriter("demo.txt");
fr = new FileReader("copydemo.txt");
Char [] buffer = new Char[1024];
int length = 0;
while((length= fw.reader(buffer))!=-1){
fw.writer(buffer,0.length);//这个表示的就是缓存中buffer中读取了多少就往文件copydemo.txt中写入多少,这里如果这接的写fw.writer(buffer)就会出现多读文件的情况存在。
}
}
catch(Exceptiion e){
}
finally{
if(fw!=null){
fw.close();//这里要判断是不是为空的,关闭的时候还是要捕获异常的
}
if(fr!=null){
fr.close();
}
}
}
}
缓冲流的作用:
缓冲流就是为了提高读写的效率,这里要注意缓冲流还是相对于每个流而言的实例如下:
FileReader fr = new FileReader("demo.txt");
BufferedReader bfw = new BufferedReader(fr);//这里使用了BufferedReader来包装了fr,然后可以使用BufferedReader 类的一些方法来读数据,这里可以使用read(),还可以使用readerline()方法,其中readline方法来读取一行的文本,返回的为String类型。
FileReader fr = new FileReader("demo.txt");
BufferedReader bfw = new BufferedReader(fr);
String line - bfw.readline();
while(line!=null){
System.out.println(line);
}
写入流的效果和读取流的作用是一样的,都是为了提高效率,BufferedWriter有一个方法newline()表示的是换行。其他的用法都是类似的,注意BufferedReader中的read()方法和Reader类中的read()方法的区别,前者是读取缓冲区的字符的方法,操作的是缓冲区,而后者是操作硬盘中的文件的。BufferedReader是重写了Reader类中的方法的
BufferedReader这里使用了一种常用的设计模式,装饰模式:增强一个类的功能实现(这一点和继承的作用是类似的,这两者的区别将在后面说明)eg:
public class StudentDemo{
public static void main(String []args){
CommoStudent cs = new CommoStuden
cs.study();
NowStudent ns = new NowStudent(cs);//这里使用了装饰模式将CommoStudent功能增强了
ns.study();
NowStudent2 ns2 = new NowStudent();//使用继承也能实现功能增强的功能
ns2.study();
}
}
class CommoStudent{
public void study(){
Sysout.out.println("从书本中获取知识")
}
}
class NowStudent{
private CommoStudent student;
public NowStudent(CommoStudent student){
this.student = student;
}
public void study(){
student.study();
Sysout.out.println("从网络中获取知识");
}
}
public NowStudent2 extends CommoStudent{
public void study{
super.study();
Sysout.out.println("从网络中获取知识");
}
}
字节流:
1)字节流用于读取非文本文件的,常见的有视频文件,音频文件等,常用的字节流有FileInputStream,FileOutputStream,BufferFileInputStream,BufferFileOutStream,他们的父类分别为InputStream和OutputStream(这两个类是抽象的类),这里的用法和字符流的用法都是类似的。视屏文件和音频文件也要使用FileInputStream,其中他的read()方法有每个字节读取的,(这种不建议使用,如果读取的文件较大的话这种读取的速度是非常慢的),read(b)这时事先定义一个字节数组(这里和字符流的写法不同byte[] b =new byte[1024],char [] cha = new Char[4];字符流的),这里只是传递的参数不一样,但是返回值都是一样的都是Int类型的。
2)如果要将一个字符串通过字节流的形式写入文件中则要将字符串转化为字节数组的形式才行通过方法getByte()实现。
3)在实际的开发中如果读取的文件较大的话,建议使用buffer类型的读取,不要读取一个字节在写入一个字节,这样的效率很低的。eg:
01)FileInputStream fs = new FileInputStream("C:\\1.mp3");
FileOutStream fos = new FileOutputStream("C:\\2.mp3");
int by = fs.read();//这里是读取一个字节
while(by!=-1){
fos.write(by);//这里就是读取一个字节然后写入一个字节,这种效率是很低的,在实际的开发中不建议使用。
}
//关闭流操作,注意字节流没有必要使用flushI()方法,直接的读入到文件的,在底层的实现也是一个空的方法
02)
FileInputStream fs = new FileInputStream("C:\\1.mp3");
FileOutStream fos = new FileOutputStream("C:\\2.mp3");
byte [] byt = new byte[1024];//这里的1024是随便定义的。
int len = 0;
while((len = fs.read(byt))!=-1){//这里的read(byt)参数一定要写的,不然会进入死循环的,导致不断的读取数据,最终会导致服务崩掉
fos.write(byt,0,len);//在实际的开发中这种的效率是相对于较高的,建议使用这种,这里定义的byt是一个字节数组,有类似缓存的作用,都会提高读写的效率的
}
//关闭流操作,注意字节流没有必要使用flushI()方法,直接的读入到文件的,在底层的实现也是一个空的方法
转化流:所谓的转化流就是字节流和字符流之间的一种转化的过程,其中字节流转化为字符流为解码的过程,字符流转化为字节流为编码的过程,简单的理解就是往计算集中存储东西的时候就是编码的过程(比如存入的文本,在键盘中输入存入的内容,然后存储到硬盘中,在硬盘中是以二进制的形式来存储的,是看不懂的,所以是编码的过程),读数据的时候就是相当于将二进制文件转化为文本的形式,就是存读不懂的东西到看懂的东西,这就是解码的一个过程。
将字节流转化为字符流的类(不懂到懂,读取数据,对应的就是输入流)InputStreamReader(参数)这里的参数要是一个字节输入流的对象,如InputStreamReader(System.in)其中System.in是一个监视键盘输入内容的。
将字符流转化为字节流的流(懂到不懂,写入数据,对应的就是输出流)OutPutStreamWriter(参数)这里的参数是一个字节输出流的对象,如OutputStreamWriter(System.out)
其中这里的System.out是一个往控制台打印信息的。
BufferReader br = new BufferReader(new InputStreamReader(System.in))//这里的BufferReader对象要一个字符流的对象作为构造函数的参数,这里的InputStreamReader表示的就是一个字符流,然而这个转化的字符流需要一个字节流对象作为构造函数,这里的System.in表示的就是一个字节流对象。这句代码的作用就是监视用户的键盘输入内容。
BufferWriter bw = new BufferWriter(new OutputStreamReader(System.out))//需要的参数和上面的是一样的,这句代码的作用就是讲读取到的内容打印到控制台中的。
如果将上面的两行代码合起来表示的就时候讲用户键盘输入的内容打印到控制台中。如果要将一个文件纵的内容复制到另一个文件中,在这里只要将System.in换成相应的文件字节输入流,将System.out换成相应的文件字节输出流就可以实现。注意文件的输入输出流都是要有参数的,要么是当前文件的文件名,要么是具体路径下的文件名。
流的加深理解:为什么使用FileWriter就能内容写入到硬盘中呢?
因为这里的OutputStreamWriter 就是FileWriter父类,这里已经的将字符流转化为字节流,所以才能存入计算机硬盘中的,童谣的FileReader的原理是一样的。这里的转化流也是一个字符流。
转化流的编码和解码:
在输入输出流中,只有转化流才能指定编码的方式,其余的流对象都是不行的,字符流(这里指的是转化流)的实质是一个字节流加编码表形式的流。指定具体的编码的格式调用其构造函数就行比如InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_1.txt"),"UTF-8");这里就是指定了具体的以utf-8的编码来读取数据的,注意这里的FileWriter不能指定具体的编码,这里是默认的系统的编码,如果是简体中文的系统则默认的是gbk的编码
输出流:OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gg.txt"),"gbk");这里简单的要注意的一点就是指定具体的编码只有转化流才有的功能,其他的流是没有这个功能的。
File类的使用:File类的作用就是可以操作文件夹和文件属性的一个类,这里的文件属性指的就是文件名,创建时间等的一些具体的信息,常用的一个方法就是separator()表示的就是目录的分隔符,在windows中的是\\在Linux中是/.注意这个方法是一个静态的方法。File file = new File("c:\\a.txt");这句代码表示的含义就是讲c盘下的a.txt文件封装成一个File对象。
注意这里的File file = new File("c:\\a.txt");file.createNewFile();表示的就是创建一个文件(如果这个文件存在就不去在创建,不存在的话就去创建了)这里和IO流中的不一样的。注意在Windows中删除文件是从里面往外面删除的,如果里面有文件的话,外面的目录是删除不了的file.delete();这个方法就会返回的是false,File类还可以创建目录的,在使用的过程中File dir = new File("abc");表示的就是在相对文件下创建一个abc的目录,如果有的话就不去创建了(使用方法file.mkdir())如果想创建多级目录的话就要使用file.mkdirs();中的删除的时候就是先出最里面的一层,因为这个file对象封装的就是最里面的,外层都是父类。