字节流:处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据。所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?
因为字符每个国家都不一样。所以涉及到了字符编码问题。那么GBK编码的中文用unicode编码解析是有问题的。所以需要获取中文字节数据的同时+指定的编码表才可以解析正确数据。为了方便于文字的解析。所以将字节流和编码表封装成对象。这个对象就是字符流。这就是字符流的由来。只要操作的字符数据,优先考虑使用字符流体系。
import java.io.*;
class Demo
{
public static void main(String[] args) throws IOException
{
//创建一个输出流对象,用于操作文件。该对象一建立,必须明确数据存储的位置
FileWriter fw = new FileWriter("demo.txt");//FileNotFoundException
//调用java中的write方法写入字符串。其实写入并未写入到目的地中而是写入到 内存的缓冲区中
fw.write("abcde");
//刷新缓冲区,将数据刷新到目的地中
fw.flush();
//关闭流资源,其实关闭流资源是java调用了底层的资源,关闭之前会刷新流
fw.close();
}
}
import java.io.*;
class Demo
{
public static void main(String[] args) throws IOException
{
//创建一个输出流对象,用于操作文件。该对象一建立,必须明确数据存储的位置
FileWriter fw = new FileWriter("demo.txt");//FileNotFoundException
//调用java中的write方法写入字符串。其实写入并未写入到目的地中而是写入到 内存的缓冲区中
fw.write("abcde");
//刷新缓冲区,将数据刷新到目的地中
fw.flush();
//关闭流资源,其实关闭流资源是java调用了底层的资源,关闭之前会刷新流
fw.close();
}
}
//演示IO流异常处理
class Demo2
{
public static void main(String [] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("demo.txt");
fw.write("avddd");
}
catch (IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if (fw!=null)
{
fw.close();
}
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
//演示文件的续写
import java.io.*;
class Demo
{
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("demo.txt",true);
fw.write("nihao\r\nxiexie");
fw.close();
}
}
//演示读取文件方法一
import java.io.*;
class Demo3
{
public static void main(String[] args) throws IOException
{
//创建一个读取流,并将要读取的文件与流相关联
FileReader fr = new FileReader("demo.txt");
//调用read方法读取文件中的内容
int ch = 0;
while ((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
fr.close();
}
}
//演示读取文件方法二
import java.io.*;
class Demo4
{
public static void main(String[] args) throws IOException
{
//创建一个读取流,并将要读取的文件与流相关联
FileReader fr = new FileReader("demo.txt");
//调用read方法读取文件中的内容
//创建一个数组,用于存储读取到的数据
char[] buf = new char[1024];
int num = 0;
while ((num = fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
}
}
//需求:将指定目录中的文本文件复制到另一个目录中。
//复制文件的原理:
//1,在D盘创建一个文件用于存储C盘中的数据
//2,定义一个读取流与c盘中的数据相关联
//3,不断进行读写
//4,关闭流资源
import java.io.*;
class Demo4
{
public static void main(String[] args) throws IOException
{
}
public static void copy_1()
{
FileWriter fw = null;
FileReader fr = null;
try
{
//创建目的地
fw = new FileWriter("demo_copy.txt");
//创建一个读取流与C盘中的文件相关联
fr = new FileReader("demo.txt");
char[] buf = new char[1024];
int num=0;
while ((num = fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
}
catch (IOException e)
{
System.out.println("复制失败");
}
finally
{
if (fw!=null)
{
try
{
fw.close();
}
catch (IOException e)
{
System.out.println("写入关闭失败");
}
}
if (fr!=null)
{
try
{
fr.close();
}
catch (IOException e)
{
System.out.println("读取关闭失败");
}
}
}
}
}
缓冲区的出现是为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符。
newLine();
import java.io.*;
class Demo5
{
public static void main(String[] args) throws IOException
{
//创建一个字符流对象
FileWriter fw = new FileWriter("demo.txt");
//为了提高字符流写入效率,加入缓冲区技术
//只需要把要提高效率的流对象作为参数传递到缓冲区构造函数中
BufferedWriter bufw = new BufferedWriter(fw);
for (int i=0;i<5 ;i++ )
{
bufw.write("abcde");
bufw.newLine();
//关闭缓冲区之前一定要刷新
bufw.flush();
}
//关闭的实际上是字符流对象 所以不用再关闭fw了
bufw.close();
}
}
//该缓冲区提供了一行一行读取的方法readLine
//当返回为null的时候表示读到文件末尾
import java.io.*;
class Demo6
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象
FileReader fr = new FileReader("demo.txt");
//为了提高字符流读取效率,加入缓冲区技术
//只需要把要提高效率的流对象作为参数传递到缓冲区构造函数中
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while ((line=bufr.readLine())!=null)
{
System.out.println(line);
}
//关闭的实际上是字符流对象 所以不用再关闭fw了
bufr.close();
}
}
//需求:通过缓冲区复制一个.java文件
import java.io.*;
class Demo6
{
public static void main(String[] args)
{
BufferedWriter bufw=null;
BufferedReader bufr = null;
try
{
bufw = new BufferedWriter(new FileWriter("demo_copy.java"));
bufr = new BufferedReader(new FileReader("demo.java"));
String line = null;
while ((line = bufr.readLine())!=null)
{
System.out.println(line);
}
}
catch (IOException e)
{
throw new RuntimeException("复制失败");
}
finally
{
try
{
if (bufw!=null)
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
try
{
if (bufr!=null)
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
}
}
}
readLine方法的原理
无论是读一行,获取读取多个字符。其实最终都是在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。
“abcde”
//自定义缓冲区
import java.io.*;
class MyBufferReader
{
private FileReader r;
MyBufferReader(FileReader r)
{
this.r = r;
}
public String MyreadLine() throws IOException
{
StringBuilder sb = new StringBuilder();
int line = 0;
while ((line = r.read())!=-1)
{
if (line=='\r')
continue;
if (line=='\n')
{
return sb.toString();
}
else
sb.append(line);
}
if (sb.length!=0)
{
return sb.toString();
}
return null;
}
public void myclose()
{
r.close();
}
}
class MyBufferReaderDemo throws IOException
{
FileReader fr = new FileReader("demo.java");
MyBufferReader mybuf = new MyBufferReader(fr);
String line = null;
while ((line=mybuf.readline())!=null)
{
System.out.println(line);
}
mybuf.close();
}
装饰设计模式:
当想要对已有的对象进行功能增强时,
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。
*/
class Person
{
public void chifan()
{
System.out.println("吃饭");
}
}
class SuperPerson
{
private Person p ;
SuperPerson(Person p)
{
this.p = p;
}
public void superChifan()
{
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根");
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
//p.chifan();
SuperPerson sp = new SuperPerson(p);
sp.superChifan();
}
}
装饰和继承的区别
以前是通过继承将每一个子类都具备缓冲功能。
那么继承体系会复杂,并不利于扩展。
现在优化思想。单独描述一下缓冲内容。
将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
这样继承体系就变得很简单。优化了体系结构。
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。
LineNumber
class Demo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("demo.java");
LineNumberReader lnr = new LineNumberReader(fr);
String line =null;
while ((line=fr.readLine())!=null)
{
System.out.println(lnr.getLineNumber()+"..."+line);
}
lnr.close();
}
}