本人小白一枚,欢迎大家一起讨论学习,如有错误,还望大家指教。
简述:
IO(Input Output)流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式。Java用于操作流对象都在IO包中,流按操作数据分为两种:字节流、字符流。流按流向分为两种:输入流、输出流。
Java中的字节流处理的最基本单位为单个字节,它通常用来处理二进制数据,如媒体文件。
Java中的字符流处理的最基本单位为Unicode码元(大小2字节),它通常用来处理文本数据。
对于刚开始学习JavaIO流,我对输入输出流的概念总是混淆,后来看了看大家对他们的理解,我似乎也明朗了不少。大概的意思就是如下,这里我们把程序当做第一人称来进行理解。
将数据从外存中读取到内存中的称为输入流。
将数据从内存中写入到外存中的称为输出流。
字符流
FileWriter(File file, boolean append)
:根据给定的 File 对象构造一个 FileWriter 对象。该方法传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写,如果没有该文件,则创建该文件。
字符流两个基类:Reader
(字符输入流) Writer
(字符输出流)
输出流案例
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
// 创建一个FileWriter对象,初始化就要必须明确被操作的文件。
// 如果该目录下已有同名文件,将被覆盖。
fileWriter = new FileWriter("demo.txt");
// 将字符串写入流中,我们需要流对象中的缓冲数据,即fileWriter.flush(),如果不刷新流,数据将不会写入到文件
fileWriter.write("喜气洋洋!!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileWriter != null) {
try {
// 关闭流资源,会自动刷新流。关闭与刷新区别:flush刷新后流还未关闭,可以继续使用,close反之。
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
操作成功,文件存在并成功写入特定字符串
输入流案例
读取输入流的两种方式
public static void main(String[] args) {
FileReader fileReader = null;
try {
fileReader = new FileReader("demo.txt");
// 一个一个字符读取
int ch = 0;
while((ch = fileReader.read()) != -1) {
System.out.print((char) ch);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
FileReader fileReader = null;
try {
fileReader = new FileReader("demo.txt");
// 通过字符数据进行读取
char[] chars = new char[1024];
int num = 0;
while((num = fileReader.read(chars)) != -1) {
System.out.print(new String(chars, 0, num));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
喜气洋洋!!!
字符流缓冲区
简述:缓冲区的出现提高了对数据的读写效率。对应类:BufferedWriter
、BufferedReader
。缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强。
对缓冲区的简单理解:在对文件进行读写操作时,如果是边读边写就会很慢,也伤硬盘。而缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似数据库的批量操作,这样效率比较高。
字符读取流缓冲区:该缓冲区提供了一个一次读一行的方法 readLine()
,方便于对文本数据的获取。当返回null时,表示读到文件末尾。readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符,返回值String。
public static void main(String[] args) {
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileWriter = new FileWriter("writer.txt");
bufferedWriter = new BufferedWriter(fileWriter);
for (int i = 1;i <= 5;i++) {
bufferedWriter.write("abcdefg" + i);
bufferedWriter.newLine();
}
bufferedWriter.flush();
fileReader = new FileReader("writer.txt");
bufferedReader = new BufferedReader(fileReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对于我们学习上面的字符流和字符缓冲区,我们可以扩展一下设计模式— 装饰设计模式
当我们想要对已有的对象功能进行增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强的功能。那么自定义的类就称为装饰类。装饰类通常会通过构造器接收被装饰的对象,并基于被装饰对象的功能,提供更强的功能。例如,BufferedReader类中的readLine()就是对FileReader类中read()方法加强,该方法就用到了这种设计模式。
字节流
字节流:InputStream
字节输入流,OutputStream
字节输出流
字节缓冲区:BufferedInputStream
,BufferedOutputStream
案例:复制一张图片
public static void main(String[] args) {
// 字节输入流
FileInputStream inputStream = null;
// 字节输入缓冲区
BufferedInputStream bufferedInputStream = null;
// 字节输出流
FileOutputStream outputStream = null;
// 字节输出缓冲区
BufferedOutputStream bufferedOutputStream = null;
try {
// 字节流一共有三种取出方式,除了一个一个字节取出和字节数组方式外,还有另一种方式
inputStream = new FileInputStream("test.jpg");
bufferedInputStream = new BufferedInputStream(inputStream);
outputStream = new FileOutputStream("demo.jpg");
bufferedOutputStream = new BufferedOutputStream(outputStream);
// 定义一个刚刚好的缓冲区,不用在进行循环了
byte[] bytes = new byte[bufferedInputStream.available()];
bufferedInputStream.read(bytes);
bufferedOutputStream.write(bytes);
bufferedOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}