IO流:
用来处理设备之间的数据传书。Java对数据的操作是通过流的方式。Java用于操作流的对象都在IO包中。流按操作数据分为两种:字节流和字符流。流按流向分为:输出流和输入流。
字符流的由来:
字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。在对这个文字进行操作。即:字节流+编码表。
字节流的两个顶层父类:InputStream,OutputStream
字符流的两个顶层父类:Reader,Writer
这些体系的子类都以父类名作为后缀。而且子类的前缀就是该对象的功能。
如果要操作文字数据,建议优先考虑字符流。而且要将数据从内存写到硬盘上,要使用字符流中的输出流--FileWriter。硬盘的数据基本体现是文件。若是读取则使用--FileReader。
FileWriterDemo:
//需求:将一些文字存储到硬盘一个文件中。
public class FileWriterDemo {
private static final String LINE_SEPARATOR=System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
// 创建一个可以往文件中写入字符数据的字符输出流对象。
/*
既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)。
如果文件不存在,则会自动创建。
如果文件存在,则会被覆盖。
如果构造函数中加入true,可以实现对文件进行续写!
*/
FileWriter fw=new FileWriter("demo.txt",true);
/*
调用Writer对象中的write(string)方法,写入数据。
其实数据写入到临时存储缓冲区中。
*/
fw.write("ABC"+LINE_SEPARATOR+"hahaha");
// fw.write("xixi");
/*
进行刷新,将数据直接写到目的地中。
*/
// fw.flush();
// 关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地。
// fw.close();
// fw.write("heha");// java.io.IOException: Stream closed
}
}
运行:IO异常的简单处理:
//line.separator换行,适用于Linux和Windows等操作系统
public class IOExceptionDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) {
FileWriter fw=null;
try{
fw=new FileWriter("demo.txt");
fw.write("abcd"+LINE_SEPARATOR+"haha");
}catch(IOException e){
System.out.println(e.toString());
}finally{
if(fw !=null)
try{
fw.close();
}catch(IOException e){
throw new RuntimeException("关闭失败");
}
}
}
}
FileReaderDemo:
//需求:读取一个文本文件。将读取到的字符打印到控制台。
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
// 1.创建读取字符数据的流对象。
/*
在创建读取流对象时,必须要明确被读取的文件。一定要确定该文件是存在的。
用一个读取流关联一个已存在文件
*/
FileReader fr=new FileReader("demo.txt");
int ch=0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
/*
用Reader中的read方法读取字符。
int ch=fr.read();
System.out.println((char)ch);
int ch1=fr.read();
System.out.println(ch1);
int ch2=fr.read();
System.out.println(ch2);
*/
fr.close();
}
}
运行:FileReaderDemo2:
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("demo.txt");
/*
使用read(char[])读取文本文件数据
先创建字符数组
*/
char[] buf=new char[1024];
int len=0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
/*
int num = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num+":"+new String(buf,0,num));
int num1 = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num1+":"+new String(buf,0,num1));
int num2 = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num2+":"+new String(buf));
*/
fr.close();
}
运行:字符流:Writer,Reader
FileReader
FileWriter
BufferedReader
BufferedWriter
将一些文字存储到硬盘一个文件中。
操作文字数据-->字符流(优先考虑)
从内存写到硬盘-->字符流中的输出流(Writer)
硬盘数据基本体现是文件-->FileWriter。
public class CopyTextTest {
public static void main(String[] args) throws IOException {
//1.读取一个已有的文本文件,使用字符读取流和文件相关联。
FileReader fr=new FileReader("IO流_2.txt");
//2.创建一个目的,用于存储读到的数据。
FileWriter fw=new FileWriter("copytext_1.txt");
//3.频繁的读写操作。
int ch=0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
//关闭流资源。
fw.close();
fr.close();
}
}
运行:创建字符数组存储读取到的数据--缓冲区。
public class CopyTextTest2 {
private static final int BUFFER_SIZE = 1024;
public static void main(String[] args) {
FileReader fr=null;
FileWriter fw=null;
try{
fr=new FileReader("IO流_2.txt");
fw=new FileWriter("copytext_2.txt");
//创建一个临时容器,用于缓存读取到的字符
char[] buf=new char[BUFFER_SIZE];//这是缓冲区。
//定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数)
int len=0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
}catch(Exception e){
// System.out.println("读写失败");
throw new RuntimeException("读写失败");
}finally{
if(fw!=null)
try{
fw.close();
}catch(IOException e){
e.printStackTrace();
}
if(fr!=null)
try{
fr.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
为了提高写入的效率。使用字符流的缓冲区。
public class BufferWriterDemo {
private static final String LINE_SEPARATOR=System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("buf.txt");
//为了提高写入的效率。使用了字符流的缓冲区。
//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
BufferedWriter bufw=new BufferedWriter(fw);
//使用缓冲区的写入方法将数据先写入到缓冲区中。
/*bufw.write("abcdfa"+LINE_SEPARATOR+"HAHA");
bufw.write("xixixi");
bufw.newLine();
bufw.write("hehe");*/
for(int x=1;x<=4;x++){
bufw.write("abcdgf"+x);
bufw.newLine();
bufw.flush();
}
//使用缓冲区的刷新方法将数据输入到目的地中。
// bufw.flush();
//关闭缓冲区。其实关闭的就是被缓冲的流对象。
bufw.close();
/*fw.write("hehe");
fw.close();*/
}
}
运行:读:
public class BufferReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("buf.txt");
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=bufr.readLine())!=null){
System.out.println(line);
}
/*
String line1=bufr.readLine();
System.out.println(line1);
String line2=bufr.readLine();
System.out.println(line2);
String line3=bufr.readLine();
System.out.println(line3);
String line4=bufr.readLine();
System.out.println(line4);
String line5=bufr.readLine();
System.out.println(line5);
*/
bufr.close();
}
/**
* @throws FileNotFoundException
* @throws IOException
*/
public static void demo() throws FileNotFoundException, IOException {
FileReader fr=new FileReader("buf.txt");
char[] buf=new char[1024];
int len=0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
}
}
运行:CopyTextByBufTest:
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("buf.txt");
BufferedReader bufr=new BufferedReader(fr);
FileWriter fw=new FileWriter("buf_copy.txt");
BufferedWriter bufw=new BufferedWriter(fw);
String line=null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
/*
int ch=0;
while((ch=bufr.read())!=-1){
bufw.write(ch);
}
*/
bufw.close();
bufr.close();
}
运行:自定义缓冲区原理:
缓冲区其实就是封装了一个数组,并对外提供了更多的访问数组的方法。而这些方法最终操作的都是数组的角标。
分析:从源中获取一批数据装进缓冲区中,再从缓冲区中不断取出一个一个数据。取完后,再从数据源中继续取出一批数据进缓冲区。取完时,用-1结束标记。
public class MyBufferedReader extends Reader{
private Reader r;
//定义一个数组作为缓冲区
private char[] buf=new char[1024];
//定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零
private int pos=0;
//定义一个计数器用于记录缓冲区的数据个数。当该数据减到0,就从源中继续获取数据到缓冲区中
private int count=0;
MyBufferedReader(Reader r){
this.r=r;
}
// 该方法从缓冲区中一次取一个字符
public int myRead() throws IOException{
if(count==0){
count=r.read(buf);
pos=0;
}if(count<0)
return -1;
char ch=buf[pos++];
count--;
return ch;
/*
//1.从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
if(count==0){
count=r.read(buf);
if(count<0)
return -1;
//每次获取数据到缓冲区后,角标归零
pos=0;
char ch=buf[pos];
pos++;
count--;
return ch;
}else if(count>0){
char ch=buf[pos];
pos++;
count--;
return ch;
}*/
}
public String myReadLine() throws IOException{
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=myRead())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
//将从缓冲区中读到的字符,存储到缓存行数据的缓冲区中。
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void myColse() throws IOException{
r.close();
}
@Override
public void close() throws IOException {
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 0;
}
}
public class MyBufferedReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("buf.txt");
MyBufferedReader bufr=new MyBufferedReader(fr);
String line=null;
while((line=bufr.myReadLine())!=null){
System.out.println(line);
}
bufr.myColse();
/*Collections.reverseOrder();
HashMap map=null;
map.values();*/
}
}
运行:装饰设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。
装饰和继承都能实现一样的特点:进行功能的扩展增强。
首先有一个集成体系。
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要缓冲技术。
Writer(继承体系)
|--TextWriter:用于操作文本
|--BufferTextWriter:加入缓冲技术操作文本对象
|--MediaWriter:用于操作媒体
BufferMediaWriter:
这个体系进行功能扩展,有了流对象。这时需要提高效率所以产生子类。就会发现只为提高功能进行的继承,导致继承
体系越来越臃肿。不够灵活。
装饰:
将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。
class Buffer{
Buffer(TextWriter w)
{}
Buffer(MediaWirter w)
{
}
}
class BufferWriter extends Writer{
BufferWriter(Writer w)
{
}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
|--BufferWriter:用于提高效率
装饰比继承灵活
特点:装饰类和被装饰类都必须所属同一个接口或者父类.
public class PersonDemo {
public static void main(String[] args) {
Person p=new Person();
// p.chifan();
NewPerson p1=new NewPerson(p);
p1.chifan();
NewPerson2 p2=new NewPerson2();
p2.chifan();
}
}
class Person{
void chifan(){
System.out.println("chifan");
}
}
//这个类的出现是为了增强Person而出现的
class NewPerson{
private Person p;
NewPerson(Person p){
this.p=p;
}
public void chifan(){
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
}
}
class NewPerson2 extends Person{
public void chifan(){
System.out.println("开胃酒");
super.chifan();
System.out.println("甜点");
}
}
LineNumberReader(加行号):
public class LineNumberReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("IO流_2.txt");
LineNumberReader lnr=new LineNumberReader(fr);
String line=null;
lnr.setLineNumber(100);
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
运行:字节流:InputStream,OutoutStream
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
public class ByteStreamDemo {
public static void main(String[] args) throws IOException {
demo_write();
demo_read();
}
private static void demo_write() throws IOException {
// 1.创建字节输出流对象。用于操作文件。
FileOutputStream fos=new FileOutputStream("bytedemo.txt");
// 2.写数据。直接写入到了目的地中。
fos.write("abcdfg".getBytes());
// fos.flush();
fos.close();//关闭资源动作要完成
}
private static void demo_read() throws IOException {
// 1.创建一个读取流对象。和指定文件关联。
FileInputStream fis=new FileInputStream("bytedemo.txt");
/*
System.out.println(fis.available());
byte[] buf=new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
// 建议使用这种读取数据的方式
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
int ch=0;
while((ch=fis.read())!=-1){
System.out.println((char)ch);
}
// 一次读取一个字节
int ch=fis.read();
System.out.println(ch);*/
fis.close();
}
}
运行:CopyMp3Test:
public class CopyMp3Test {
public static void main(String[] args) throws IOException {
copy_1();
copy_2();
copy_3();
copy_4();
}
//千万不要用,没有效率
private static void copy_4() throws IOException {
FileInputStream fis=new FileInputStream("c:\\0.mp3");
FileOutputStream fos=new FileOutputStream("c:\\4.mp3");
int ch=0;
while((ch=fis.read())!=-1){
fos.write(ch);
}
fos.close();
fis.close();
}
//不建议
private static void copy_3() throws IOException {
FileInputStream fis=new FileInputStream("c:\\0.mp3");
FileOutputStream fos=new FileOutputStream("c:\\3.mp3");
byte[] buf=new byte[fis.available()];
fis.read(buf);
fos.write(buf);
fos.close();
fis.close();
}
private static void copy_2() throws IOException {
FileInputStream fis=new FileInputStream("c:\\0.mp3");
BufferedInputStream bufis=new BufferedInputStream(fis);
FileOutputStream fos=new FileOutputStream("c:\\2.mp3");
BufferedOutputStream bufos=new BufferedOutputStream(fos);
int ch=0;
while((ch=bufis.read())!=-1){
bufos.write(ch);
}
bufos.close();
bufis.close();
}
private static void copy_1() throws IOException {
FileInputStream fis=new FileInputStream("c:\\0.mp3");
FileOutputStream fos=new FileOutputStream("c:\\1.mp3");
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
fis.close();
}
}