字符流FileWriter,FileReader、缓冲区,BufferReader,BufferWriter,IO的简单异常处理

输入流和输出流相对于内容设备而言

将外设中的数据读取到内存中:输入

将内存的数写入到外设中:输出


字符流的由来:

字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。

再对这个文字进行操作。简单说:字节流+编码表

字节流的两个顶层父类:

1 InputStream 2 OutputStream 

字符流的另个顶层父类:

1 Reader 2 Writer 

体系的子类几乎都以父类名作为后缀

Io的输出 和换行:

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("fileWriter.txt",true);//明确fileWriter.txt的文件
/*调用Writer中的方法 write 写入数据,写入字符串
* 其实是写入到临时存储缓冲区中
*/
 
fw.write("dsad"+LINE_SEPARATOR+"asda");//换行


//进行刷新,将数据直接写到目的地中
fw.flush();
//关闭流,关闭资源。在关闭前会调用flush刷新缓冲区的数据到目的地
fw.close();
//fw.write("haha");//如果不能续写的话,会发生Exception in thread "main" java.io.IOException: Stream closed
}
}

io的简单异常处理:


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("fileWriter.txt");
fw.write("dsad" + LINE_SEPARATOR + "asda");
fw.close();
} catch (Exception e) {

}
finally{
if(fw!=null)
try{
fw.close();
}
catch(IOException e){
//code....
throw new RuntimeException("关闭失败");
}
}
}
}


读取的两种方式:

public class FileReaderDemo {
public static void main(String[] args) throws IOException {
/*1 创建读取字符数据的流对象
* 明确被读取的文件是存在的
* 用一个读取流关联一个已存在文件
* */
FileReader fr = new FileReader("fileWriter.txt");


//用read方法读取
/*int ch = fr.read();//读取第一个字符
System.out.println(ch);
int ch1 = fr.read();
System.out.println(ch1);//读取第二个 以此类推
fr.close();*/


int ch = 0;
while((ch = fr.read())!=-1){//-1为数据读取结束时的值
System.out.println((char)ch);
}

//使用read(char[])读取
char[] buf = new char[3];
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}


/*
int num = fr.read(buf);//读取到的数据先存储的数组buf中。
System.out.println(num+":"+new String(buf));
int num1 = fr.read(buf);
System.out.println(num1+":"+new String(buf));
int num2 = fr.read(buf);
System.out.println(num2+":"+new String(buf));

*/


fr.close();
}
}

练习:
 * 把一个文本文件复制到另一个中
 * 思路:
 * 先读取要复制的文件,一个一个读,读的同时写入到另一个文件中

public class CopyTextTest {
public static void main(String[] args) throws IOException {
//1 创建要复制的文件
FileReader fr = new FileReader("yuan.txt");
//2 创建复制后的文件
FileWriter fw = new FileWriter("copy.txt");
//3 读的同时写入

int ch = 0;
while((ch = fr.read())!=-1)
{
fw.write(ch);
}
//
fw.close();
fr.close();
}
}

第二种方式:

FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("yuan.txt");

fw = new FileWriter("copy2.txt");

char[] buf = new char[1024];
int len = 0;
while((len = fr.read(buf))!=-1){
fw.write(buf,0,len);
}
   
} catch (Exception e) {

throw new RuntimeException("读写失败");
}
finally{
if(fr!=null)
try {
fr.close();
} catch (IOException e) {

e.printStackTrace();
}
if(fw!=null)
try {
fw.close();
} catch (IOException e) {

e.printStackTrace();
}

缓冲区:BufferedReader BufferedWriter


BufferedReader
public class BufferdeWriterDemo {

public static void main(String[] args) throws IOException {
//使用缓冲区是为了提高效率
FileWriter fw = new FileWriter("buf.txt");
//是缓冲区与字符写入流相关联
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区的写入,刷新,关闭方法
bufw.write("dasdas");
//缓冲区的换行方法
bufw.newLine();
bufw.write("hahha");
bufw.flush();
bufw.close();
}
}

BufferedReader


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;
//readLLine()方法为读一行
while((line = bufr.readLine())!=null){
System.out.println(line);
}
fr.close();
bufr.close();
}

}

自定义缓冲区:


/*自定义缓冲区,其实就是模拟一个BufferedReader
 * 分析:
 * 缓冲区无非就是封装了一个数组。
 * 并对外提供方法对数组进行访问
 * 其实这些方法最终操作的都是数组的角标
 * 
 * 缓冲原理:
 * 其实就是从源中获取一批数据装进缓冲区中。
 * 在从缓冲区中不断的取出一个一个数据
 * 
 * 在此次取完后,在从源中取一批数据进缓冲区。
 * 当源中的数据取光时,用-1作为结束标记
 * */


public class MyBufferReader {
private FileReader r;
MyBufferReader(FileReader r) {
this.r = r;
}


// 封装的一个数组
char[] buf = new char[1024];
// 定义一个变量记录数组的角标
int pos = 0;
// 定义一个变量记录数组中的个数
int count = 0;
public int myRead() throws IOException {
if (count == 0) {
count = r.read(buf);
pos = 0; // 每次重新获取后,角标置为0
}
if (count < 0)
return -1;
char ch = buf[pos++];
count--;
return ch;

}

public String myReadLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch = 0;
while ((ch = myRead()) != -1) {
if (ch == '\r')
continue;// 不添加'\r'
if (ch == '\n')
return sb.toString();
sb.append((char) ch);
}
if (sb.length() != 0)
return sb.toString();// 解决最后一行的读取问题(可能回车符紧更着最后一行)
return null;
}


public void myClose() throws IOException {
r.close();
}


}


缓冲区使用了装饰设计模式,模式特点:装饰类和被装饰类都必须所属同一个接口或者父类。(最好装饰一组)

LineNumberReader用于读行号


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34123420/article/details/51510646
个人分类: IO
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭