IO:主要用来处理设备之间的数据传输(如硬盘上的文件,内存中的数据),java对数据的操作是通过流的方式,
java操作流的对象存在IO包中,流按数据分为两种,字节流和字符流。
字符流的数据字节流其实都能处理,因为无论什么在计算机上最后都是以字节存在的,但是其中有一部
分数据它是以文本形式存在的,所以为了方便有了字符流,字符流里融合了编码表,而只有文字用到了
编码表,所以字符流用来处理文本形式的数据。
按方向分的话有输入流和输出流之分。
字符流: 字节流:
Writer Reader InputStream OutputStream
这四个基类的子类名称都是以父类的名称为后缀,如FileReader,FileInputStream,
在写有关IO流程序的时候,首先要注意:
1.要注意一定要记得导包,import java.Io.*;
2.记得要进行异常处理,和IO流有关的都会抛异常,原因:例如FileWrite("C:\\abc.txt");
因为括号里的文件名会有可能出错,比如写成(K:\\abc.txt)
3.最后一定要进行关闭流的操作。因为它底层调用的其实是window资源,所以要关闭。
---------------------------------------------------------------------------------------------
下面是IO异常处理方式:
例如;
FileWriter fw = null;//2.所以一般在外面定义引用在try内初始化,这样fw就作用于整个程序中, try { //1.因为会抛异常所以要进行try处理,但是如过把下面这句放在try代码块里面定义fw,那么 //在别的代码块里会访问不到(比如finaly里关流的时候) //FileWriter fw = new FileWriter(c:\\abc.txt); fw = new FileWriter(c:\\abc.txt); // 代码1 fw.Write("abcdef"); //代码2 } catch(IOException e), { //异常处理 } finaly { try {//一定要对关闭的流对象进行判断是否为空 if(fw != null)//写这句的原因:因为如果“代码1”处出现异常被处理了,那么代码里面fw里面也就 //没有被写进东西,所以fw为空。 fw.close();//如果为空的话则不能调用这句,所以要进行下是否为空判断 } catch(IOException e), { //异常处理 } }
字符流:writer(写)
根据以往经验,要想了解一个体系,是不是都要先从最顶端的开始了解啊?字符流写的方法最顶端的
父类就是writer,它里面有append(),close(), write() 等方法,可以知道它的子类中肯定也都具有
这些功能。既然是字符流,那么它操作的最基本数据就是字符, FileWriter 里的主力方法就是write
方法,就是往文件里写数据的方法,既然是操作字符了,那肯定忘里写单个字符啊字符数组啊,字符串
啊都行。
字符流---创建文件 异常处理如上:
FileWriter fw = new FileWriter("Demo.txt");// 在此目录下创建一文件,如果已经存在会被覆盖掉。
FileWriter fw = new FileWriter("Demo.txt",true);//不覆盖原文件,在末尾处添加
fw.write("abcdefg");//调用write()方法,其实是存在了流(内存)中
fw.flush();//将流对象中缓冲区里的刷新数据至目的地中
fw.close();// close()特点:刷新一次数据然后关闭流
其实,我们不用java也能创建一个文件往里写数据,也就是说windows系统本身就具有这个动作,java能往
windows的文件系统中写入数据,是不是代表着java在调用windos中那个写的动作?这个就是我们所说的流
资源。其实java本身是不能往硬盘里写数据的,我们知道windows和linux系统它们写数据的方式是不是不一
样啊?所以java得靠系统本身的方式来完成对数据的书写。总的来说就是java写数据什么的是不是在调用
windows的系统资源用完了要怎么办?是不是要释放出来,所以close动作是一定要做的。
文件的续写:
建个文件往里面写数据,但是那个文件里已经有数据了该怎么往里续写数据呢?写一次刷新一次,通过
查看API我们发现FileWriter类有一种构造函数
FileWriter(String fileName, boolean append)
参数: fileName - 一个字符串,表示与系统有关的文件名。
append - 一个 boolean 值,如果为 true,则将数据写入文件末尾处,而不是写入文件开始处。
---------------------------------------------------------------------------------------------
字符流 Reader(读)
说完写该说读了,查看API发现Reader类里也有很多和Writer方法,如close()等,但是它里面没有flush();
另外它里面有一群读的方法(read),如读单个字符,或把数据读入到一个数组,另外读文件的话是不是先把
文件传给他啊,所以在创建对象的时候要把指定文件与它相关联。如果不存在会发生文件未找到异常。
字符流---读取文件1 下面是没有进行异常处理的
FileReader fr = new FileReader("Demo.txt");//文件不存在会抛异常
int x = fr.read();//一次读一个会自动往下读,如果在调用一次read方法和打印方法,打印的则是下一个
System.out.println(char(x));//因为返回的是int型,所以要进行类型转换。
//一个文件里面显然不会只有一个字符,像上面所说读一个重写一次方法,会很麻烦,所以会想到循环,如下:
int x = 0;
while((x=fr.read()) != -1)//文件读取到末尾如果没有的话会返回-1
{
System.out.println((char)x);
}
字符流---读取文件2 通过字符数组进行读取,下面是没有进行异常处理的
FileReader fr = new FileReader("Demo.txt");//创建一个文件读取流对象和指定文件相关联
//定义一个字符数组
char[] ch = new char[1024]//一般数组大小会定为1024的整数倍
int num = fr.read(ch);//将读取到的文字存放在数组中,则返回的是字符里面的个数
System.out.println(new String(ch));//将数组变成字符串打印
fr.close();//这一步没有刷新数据,读取文件不用刷新
文件读取2的完整代码:
FileReder fr = null try { fr = new FileReade(); char[] ch = new char[1024]; int num = 0; while((num = fr.read(ch))!=-1) { //打印数组中的有效位,如果数组中只有三个字符,就没必要把1024个全打印出来 System.out.println(new String(buf,0,len)); } } catch (IOException e) { //异常处理 } finally { try { if (fr !=null) { fw.close(); } } catch (IOException e) { //异常处理 } }
注意:
定义文件路径时,可以用“/”或者“\\”。?
在创建一个文件时,如果目录下有同名文 件将被覆盖。 ?
在读取文件时,必须保证该文件已存在, 否则出异常。
练习:复制文件
部分代码:
FileWriter fw = new FileWriter("copy.txt");//向目的文件中写入数据 FileReader fr = new FileReader("Demo.java");//读取文件中的数据写入流中 char[] buf = new char[1024]; int len = 0; while((len=fr.read(buf))!=-1) { fw.write(buf,0,len); }
---------------------------------------------------------------------------------------------
字符流的缓冲区: BufferedWriter BufferedReader
字符流中的读写,如上面方法的话,都是一个一个的读或写,为了提高效率出现了缓冲区,就像
用杯子接水滴,等接满了一杯再喝会比接一滴喝一滴舒服。
像迅雷,BT这些软件它们在下载过程中都有自己的缓冲区,比如它们在服务器下载东西,每次下
载一次性两兆再写到硬盘上从,比每次从服务器下载一点就往硬盘上写一点快吧。这边一顿狂读,
这后到这边再一顿狂写,省的磁头来回的切换,这样效率就提升了很多。
缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符。newLine();
我们创建一个流对象之后,然后把它当参数传给缓冲区的构造函数,因为缓冲区已经和流相关联了,
所以然后直接用缓冲区的方法就可以了。
字符写入流缓冲区: BufferedWriter
既然缓冲区是为了提高流的效率,那么它存在的前提是要有流。
例如:
FileWriter fw = new FileWriter("Demo.txt");
//只需将需要被提高效率的流当参数传入给缓冲区的构造函数即可
BufferedWriter bfw = new BufferedWriter(fw);
//然后下面就可以用缓冲区的方法了(BufferedWriter也是Write的子类,所以也能用它的方法)
bfw.write("abcde");
bfw.flush();//只要用到缓冲区就要刷新
bfw.close();//关闭缓冲区其是就是关闭了流对象,所以fw.close()就不用再写了
缓冲区有一个新的方法:newLine()这个方法是跨平台的,在window上"\r\n"是换行而在linux上"\n"是换行
只有用到缓冲区对象的时候才能用newLine()方法
例如:
for(intx =0;x<5;x++)
{
bfw.write("abcde");
bfw.newLine();
//为什么要写一次刷新一次? 因为在写的过程中可能会出现一些状况如停电,如果在写好多的情况下
// 停电了没刷新那么文件里面一点也不会有
bfw.flush();
}
---------------------------------------------------------------------------------------------
字符读取流缓冲区: BufferedReader
该缓冲区提供了一次读一行的方法:readLine()因为一行有很多字符。所以它返回的是字符串,读到流的
末尾返回的是null,readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
readLine()方法最终都是从硬盘上一个一个的读取所以最终使用的还是read方法一个一个的读的。
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("Demo.txt");
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bfr = new BufferedReader(fr);
//下面使用BufferedReader的方法
String s = null;
while((s=bfr.readLine()) !=null)
{
System.out.print(s);
}
bfr.close();
缓冲区特点:
缓冲区的出现提高了对数据的读写效率。?
缓冲区要结合流才可以使用。?
在流的基础上对流的功能进行了增强。
---------------------------------------------------------------------------------------------
装饰设计模式:
一个类的功能如果需要加强,可以在定义一个类来写加强的功能,然后将需要被加强的类
当参数传入加强类,通过构造方法来接收被加强的类。如BufferedReader(FlieRader fr).
模式例如:
class OldMethod //1. { public void fuction { //原有的功能 } } class SuperMethod //2. { private OldMethod om; SuperMethod(OldMethod om) { this.om = om; } public void superFuction { //基于原有而加强的功能 //如果有用到原来的东西,直接调用:om.fuction() } }
---------------------------------------------------------------------------------------------
疑问:为什么类2不继承类1呢?
例如下面类OldMethod有三个子类,比如在开发的过程中我们发现这三个子类里面的功能效率有点低我
们想要重写个类来加强一下它们的功能,这时会想到用缓冲技术,那么如果要用继承的话,就会像下
面这样,在后期OldMethod可能还会再增加好多子类,那么在这样写的话整个体系就会显得非常臃肿,所
以要进行优化。
OldMethod
|--OneMethod
|--OneBufferMethod
|--TwoMethod
|--TwoBufferMethod
|--ThreeMethod
|--ThreeBufferMethod
怎么优化呢?既然它们都需要缓冲,所用的技术也都一样,那么就没必要一个一个的写缓冲类来继承了,可以
专门定义一个缓冲类,OldMethod的哪个子类需要缓冲就把哪个当参数传进来。如下:
class MyBufferMethod
{
MyBufferMethod(OneMethod one)
{
}
MyBufferMethod(TwoMethod two)
{
}
MyBufferMethod(ThreeMethod three)
{
}
......//但是这样扩展型还是不太好
}
这时可以发现,无论是哪个类需要缓冲,他们都是OldMethod的子类,这样就想到了多态,我们可以这样定义
一个类来继承.
class MyBufferMethod extends OldMethod//既然MyBufferMethod里的功能和只是那三个子类功能的加强,
{ //所以它也应该属于OldMethod参看下面的(看这里)
MyBufferMethod(OldMethod old)//多态,技能传OneMethod也能传TwoMethod...
{
}
}
最后这个体系就变成了这样:
OldMethod
|--OneMethod
|--TwoMethod
|--ThreeMethod
|--MyBufferMethod
---------------------------------------------------------------------------------------------
我们可以看出装饰模式比继承更灵活,降低了类与类之间的关系
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了加强功能。所以装饰类
和被装饰类属于同一个体系就像BufferedReader与FileReader同是Reader的子类
---------------------------------------------------------------------------------------------
LineNumberReader: 也是一个装饰类,BufferedReader的子类,所以它也有readLine()方法,
另外还有setLineNumber()和getLineNumber(),意为设置和获取行号。
使用方法如下(没有进行异常处理):
FileReader fr = new FileReader("Demo.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String s = null;
lnr.setLineNumber(10);//可以设置行号的起始值
while((x=lnr.readLine()) != null)
{
System.out.println(lnr.getLineNumber()+"::"+x);
}
---------------------------------------------------------------------------------------------
字节流:基本操作与字符流差不多,别说它里面的write,read方法和字符流里的基本一样,它也能一个一个
的往文件里写数据,也能把数组中的数据一下写到文件中,既能一个一个的读,也能把数据读入到一个数组
中,唯一的区别是字符流写进的是char[],而字节流是往byte[]数组中读或写。另外字节流不仅操作字符,
还可以操作其他媒体文件
基类 InputStream读 OutputStream写
字节流--文件写入,与字符流一样也要处理异常。
FileOutputStream fos = new FileOutputStream("Test.txt");//创建一个字节写入流,与文件相关联
//里面要么写单个字节,要么写字节数组,写字符串的话要把它转成字节类型的
fos.write("abcde".getBytes());//不需要刷新,因为是直接对字节最小单位操作,中间不需要任何转换
fos.close();//关闭流
字节流--文件读取1,一个一个的打印
FileInputStream fis = new FileInputStream("Test.txt");
int ch = 0;//调用read()方法返回的是整数,流末尾返回的是-1;
while((ch=fos.read())!=-1)
{
System.out.println(char(ch));//因为返回的是整数,所以要把它转成字符型打印
}
fos.close();
字节流--文件读取2,将数据读进一个字节数组
FileInputStream fis = new FileInputStream("Test.txt");
byte[] buf = new Byte[1024];
int len = 0;
while((flen=os.read(buf))!=-1)
{
//把数组转换为字符串,按范围打印出来
System.out.println(new String(buf,0,len));
}
字节流--文件读取3,这一种是字节流特有的
FileInputStream fis = new FileInputStream("Test.txt");
//int num = fis.available();调用这个方法可以算出文件中的字符数
byte[] buf = new Byte[fis.available()];//所已就可以定义一个刚刚好的数组了,也就不用循环了
fos.read(buf);//读取文件中的字节存在数组buf中
System.out.println(buf);//不用循环,直接把数组里面的全打印出来
fis.close();
---------------------------------------------------------------------------------------------
注意:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
---------------------------------------------------------------------------------------------
字节流缓冲区
//例:通过字节流的缓冲区来完成 Mp3的复制:
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by=0;
while((by=bufis.read())!=-1)
{
fos.write(by);//把从文件中读取的数据写进目的文件
}
fos.close();//有多少流就关多少流
fis.close();
自定义字节流缓冲区:
字节流缓存区的原理是,把一些数据先存进一个数组中,然后在一下取出来。自定义缓冲区的话,思路
就是:要先定义一个数组,然后再把数组中的数据一个一个往外取。用到了数组,怎么往里存呢?我们
知道read(arr)返回的是数组里元素的个数,
那取的时候read方法
是一个一个的往下读的,所以就用到了指针,那什么时候停呢?就是取到数组末尾的时候,就是count=0的时候,
那怎么往数组里面存呢?
class MyBufferInputStream extends { private InputStream ips;//定义一个InputStream引用 private byte[] buf = new byte[1024*4]; private int pos = 0,count = 0;//定义一个指针和数据个数的变量 MyBufferInputStream(InputStream ips)//把需要缓存的文件当参数传给缓冲器的构造函数 { this ips = ips; } //要对外提供一个read方法,就像BufferInputStream,一次读一个字节(从缓冲区即字符数组中读取) public int myRead()throws IOException//进行异常处理 { //通过in对象读取硬盘上数据,并存储buf中。 if(count==0)//5.所以当数组中元素为0的时候,是先存再取 { count = ips.read(buf);//1.把数据读取到数组中,返回的是数组里元素的个数 if(count<0)// return -1; pos = 0;// byte b = buf[pos];//2.往数组里存满了是不是就该把数组里的数据取出来放缓冲区里啦 count--;//3.把数组里的数据往缓冲区里装的时候是不是装一个,数组里就少一个啊? pos++;//4.一个一个的把数组里的取出来,是不是就是指针越来越往后移啊 return b&255; } else if(count>0)//6.而当数组里有数据的时候直接取 { byte b = buf[pos]; count--; pos++; return b&0xff; } return -1; } }
读取键盘录入:
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。in 是标准输入流对应的是InputStream,所以能用read()等方法
例如:
InputStream in = System.in;//System调用in方法之后返回的是一个字节读取流
int by = in.read();//读取一个字节字符流字节流读取一个数据返回的都是int型
System.out.println(by);//控制台将会等待输入运行代码
部分代码:
import java.io.*; class IODemo { public static void main(String[] args) throws IOException { InputStream ins = System.in; StringBuilder sb = new StringBuilder(); while(true) { int ch = ins.read(); if(ch=='\r') continue; if(ch=='\n') { String s = sb.toString(); //sb.delete(0,sb.length()); if("over".equals(s)) break; System.out.println(s.toUpperCase()); sb.delete(0,sb.length()); } else sb.append((char)ch); } } }然后发现以上代码与我们自定义 BufferedReader时写的ReaderLine代码差不多,这时就考虑能不能
直接拿过来用呢?但是 BufferedReader是字符流,而InputStream是字节流,它是字节流要用字符流
的东西,怎么办?是不是要看看有没有能把字节流转为字符流的东西啊?通过查看java API发现,还
真有个转换流,下面请看java io(2)。
相关推荐
黑马程序员_毕向东_Java基础视频教程第18天-14-IO流(拷贝文本文件图例).zip
黑马程序员__移动商城项目实战 包括黑马程序员乐淘商城实战和慕课React+Antd
公式指标,黑马起爆,有助于判断什么时候可以入手
黑马程序员_毕向东_Java基础视频教程第18天-09-IO流(文件的续写)
JavaWeb是Java编程领域中的一个重要组成部分,主要涉及Web应用程序的开发和实现。黑马程序员是一家知名的IT教育机构,他们提供的Javaweb教材源码是为了帮助学员深入理解和实践Web开发技术。下面将详细介绍JavaWeb的...
本教程《黑马程序员_毕向东_Java基础视频教程第18天-13-IO流(拷贝文本文件)》专注于讲解如何利用IO流来实现文本文件的复制操作。这个过程涉及到了对文件读取、数据缓冲以及写入等基础知识,对于初学者来说是理解和...
在这个“黑马程序员_毕向东_Java基础视频教程第18天-12-IO流(文本文件读取练习)”中,毕向东老师将深入讲解如何使用Java IO流来读取文本文件。Java IO流提供了多种类和方法,使得开发者可以灵活高效地处理输入和输出...
本文将深入探讨2016年黑马程序员发布的Hibernate框架开发课程的第二天内容。Hibernate,一个强大的Java持久化框架,简化了数据库操作,为开发者提供了对象关系映射(ORM)解决方案。在Day02的学习中,我们将重点关注...
标题中的“heima_ugo_xiaochengxu_黑马训练营_微信小程序_小程序支付_VantWeapp商城”揭示了这是一个关于微信小程序开发的项目,由黑马训练营提供教学支持,特别关注了商城功能、微信登录和微信支付的集成,并且使用...
Java的输入/输出(IO)系统是编程中的一个重要部分,特别是在开发服务器端应用程序、文件处理以及数据传输场景中。"IO-黑马程序员Java学习笔记"这个压缩包包含了关于Java IO的详细教程,可以帮助我们深入理解这个...
在本教程“黑马程序员_毕向东_Java基础视频教程第18天-11-IO流(文本文件读取方式二)”中,主讲人毕向东将深入讲解如何使用Java有效地读取文本文件,特别是第二种常用的方法。以下是关于Java IO流和文本文件读取的...
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
"黑马旅游网项目_java_web_基础" 这个标题表明这是一个关于Java Web开发的项目,特别强调了基础部分。这意味着它可能是针对初学者或中级开发者的一个教学项目,旨在帮助他们掌握Java Web开发的基础知识。在这个项目...
本资料包“Java-IO流高级-例题 & 例题源码 & PPT教学文档(黑马程序员详细版).rar”提供了一个深入学习Java IO流的全面资源,包含实例题目、源代码以及PPT教学材料,适合对Java IO有进阶需求的开发者。 1. **Java ...
1. **电商系统架构**:学员可能学习到如何构建一个完整的电商平台,包括前端展示、后台管理、数据库设计、支付接口集成等。 2. **Web开发技术**:可能涉及HTML、CSS、JavaScript等前端技术,以及Java、Python、PHP...
暗示这门课程可能包含一系列视频教程,首个文件"01_黑马程序员_张孝祥_Java基础加强_课程价值与目标介绍.avi"很可能是课程的开篇,详细阐述了课程的价值、目标以及教学计划,帮助学员了解学习路径和预期收获。...
【青橙电商前台开发02】课程主要涵盖了电商网站前端开发的相关知识,是黑马教育机构推出的borns8e系列课程之一。在这个课程中,你将深入学习如何构建一个功能完善的电商平台前端界面,提升你的前端开发技能。以下是...
重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip
总结来说,"黑马程序员_毕向东_Java基础源码.rar"为初学者提供了一个深入学习Java编程的宝贵平台。通过学习和实践这些源代码,不仅可以巩固Java基础知识,还能培养良好的编程习惯和思维模式,为成为专业Java开发者...
6.1 案例分析:结合黑马程序员的day1至day4的讲义和笔记,深入理解在实际项目中如何应用Hibernate,解决具体问题。 总结,Hibernate作为强大的ORM框架,为Java开发者提供了便利,通过理解并熟练掌握其核心概念、...