黑马程序员——Java基础——IO输入与输出_1

时间:2021-09-01 13:18:59

IO流

作用:

  • 利用Java语言中的IO流技术处理设备上的数据(硬盘上的文件,内存中驻留的数据)

分类:

  • 按流向:
    • 输入流
    • 输出流
  • 按数据:
    • 字节流
    • 字符流

抽象基类:

  • 字符流:Reader、Writer
  • 字节流:InputStream、OutputStream

字符流

FileWriter对象:

  1. 创建一个FileWriter对象,该对象一开始被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该文件目录下已经有同名文件,则该文件将被覆盖。
  2. 调用write方法,将字符串写入到流中。
  3. 调用flush方法,刷新流对象中的缓冲中的数据,将数据刷到目的地中。
  4. 调用close方法,关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
  5. close和flush方法的区别,flush刷新后,流可以继续使用,close刷新后,会将流关闭。
import java.io.*;

class FileWriterDemo
{

public static void main(String[] args)
{
FileWriter fw = new FileWriter("目录");
//FileWriter("目录", true);传递true参数,为续写文件(文件存在续写,不存在创建)
fw.write("abcdef");
fw.close();
}
}

FileReader对象:

import java.io.*;

class FileReaderDemo
{
public static void main(String[] args)
{
FileReader fr1 = new FileReader("目录");
/*
while(true)
{
//读取一个字符,返回对应的ACSII值,当读取到结尾的时候返回-1;
int ch = fr1.read();
if(ch == -1)
break;
}
*/

//读取单个字符;
int ch = 0;
while((ch = fr1.read()) != -1)
{
System.out.println((char)ch);
}
fr.colse();

//将字符读入数组,返回读取个数;
FileReader fr2 = new FileReader("目录");
char[] buf = new char[1024];
int num = 0;
while((num = fr2.read(buf)) != -1)
{
System.out.println(new String(buf, 0, num));
}
fr2.close();
}
}

IO异常的处理方式:

import java.io.*;
class IoExceptionDemo
{
public static void main(String[] args)
{
//在外部初始化,在内部定义;
FileWriter fw = null;
try
{
fw = new FileWriter("目录");
fw.write("abcdef");
//windows换行为:/r/n
//linux换行为 :/n
}
catch(IoException e)
{
System.out.println(“catch1:”+e.toString());
}
finally
{
try
{
if(fw != null)
fw.close();
}
catch(IoException e)
{
System.out.println(“catch2:”+e.toString());
}
}
}
}

字符流拷贝文本文件:(练习)

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyText {
public static void main(String[] args){
CopyText ct = new CopyText();
ct.copyFile("d:/test/reader.txt", "d:/test/copy_reader.txt");
}
public void copyFile(String src, String dest){
FileReader fr = null;
FileWriter fw = null;
int num = 0;
char[] buf = new char[1024];
try {
fr = new FileReader(src);
fw = new FileWriter(dest);
while((num = fr.read(buf)) != -1){
fw.write(buf, 0, num);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fw != null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fw != null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

字节流的缓冲区:

作用:

  1. 缓冲区技术提高了对数据的读写效率
  2. 缓冲区要结合流才可以使用
  3. 在流的基础上对流的功能进行了增强

字节流缓冲区对应类

  • BufferedWriter
  • BufferedReader

BufferedWriter:

import java.io.*;
class BufferedWriterDemo
{

//创建一个字符写入流对象
FileWriter fw = new FileWriter("文件.txt";)
//为了提高字符写入流的效率,加入了缓冲技术
BufferedWriter bufw = new BufferedWriter(fw);
bufw.write("abcde");
bufw.newLine();
//使用缓冲区,就要做刷新动作
bufw.flush();
//关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();
}

BufferedReader:

该类提供一次读取一行的方法readLine(),当返回null,表示读到文件末尾
readLine()方法不返回每一行的换行符

import java.io.*;   
class BufferedReaderDemo
{

public static void main(String[] args)
{
//创建一个读取流对象和文件相关联
FileReader fr = new FileReader("文件.txt");

//加入字符读取缓冲流
BufferedReader bufr = new BufferedReader(fr);

String line = null;
while((line = bufr.readLine()) != null)
{
System.out.println(line);
}
bufr.close();
}
}

字符流缓冲区拷贝文本文件:(练习)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTextBuffered {
public static void main(String[] args){
CopyTextBuffered ctb = new CopyTextBuffered();
ctb.copyFile("d:/test/reader.txt", "d:/test/copy_buffered_reader.txt");
}
public void copyFile(String src, String dest){
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
bufr = new BufferedReader(new FileReader(src));
bufw = new BufferedWriter(new FileWriter(dest));
String line = null;
while((line = bufr.readLine()) != null){
bufw.write(line);
bufw.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(bufw != null)
try {
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(bufr != null)
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

装饰设计模式:

目的:当想要对已有的对象进行功能增强时
做法:定义类,将已有对象传入,基于已有的功能,并提供加强功能
结果:该定义类称为装饰类,装饰类通常会通过构造方法,接受被装饰的对象。并基于被装饰对象的功能,提供更强的功能

装饰类和继承的区别:

  • 装饰模式比继承要灵活,避免了继承体系臃肿。降低了类与类之间的类。
  • 装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。
  • 所以装饰类和被装饰类通常都属于同一个体系中。

自定义字符缓冲区读取流MyBufferedReader类:

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class MyBufferedReader extends Reader{
private Reader r;
MyBufferedReader(Reader r){
this.r = r;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return r.read(cbuf, off, len);
}
@Override
public void close() throws IOException {
r.close();
}
public String myReadLine() throws IOException{
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = r.read()) != -1){
if(ch == '\r')
continue;
if(ch == '\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length() != 0)
return sb.toString();
return null;
}
public void myClose() throws IOException{
r.close();
}
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("d:/test/doc.txt");
MyBufferedReader mbufr = new MyBufferedReader(fr);
String line = null;
while((line = mbufr.myReadLine()) != null){
System.out.println(line);
}
mbufr.myClose();
}
}

LineNumberReader:(已知子类、包装类)

  • 跟踪行号缓冲字符输入流
  • getLineNumber();
  • setLineNumber(int);/默认从零行开始。设定100,从101行开始/
  • readLine();

MyLineNumberReader:

import java.io.*;
class MyLineNumberReader
{
pirvate Reader r;
private int lineNumber;

MyLineNumberReader(Reader)
{
this.r = r;
}
public String myReaderLine() throws IOException
{
lineNumber++;
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = r.read()) != -1)
{
if(ch == '/r')
continue;
if(ch == '/n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length() != 0)
return sb.toString();
return null;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
public void myClose()
{
r.close();
}
}

MyLineNumberReader优化:

import java.io.*;
class MyLineNumberReader extends MyBufferedReader
{

private int lineNumber;
MyLineNumberReader(Reader r)
{
super(r);
}
public String myReaderLine() throws IOException
{
lineNumber++;
return super.myReadLine();
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
}