------Java培训、Android培训、期待与您交流! -------
一、IO流概述
IO流,即输入输出流,指应用程序对内存设备的数据输入与输出,将外部设备的数据读取到内存中为输入,将内存中的数据写入到外部设备中为输出。JAVA 语言定义了许多类负责各种方式的输入输出,这些类都被放在 java.io 包中。
IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式。流按操作数据的不同分为:字节流和字符流。
二、字节流和字符流
1、概述
字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字。再对这个文字进行操作。简单说:字节流+编码表。
字节流的抽象基类: InputStream,OutputStream。
字符流的抽象基类: Reader,Writer。
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。如: InputStream的子类FileInputStream、Reader的子类FileReader。
2、字符流之FileReader和FileWriter
2.1 FileWriter
该类用于在文件中写入字符并将文件写入硬盘上。
步骤:a. 创建FileWriter对象,明确文件;
b.调用Writer对象中write方法,写入数据;
c. 调用flush方法进行刷新,将数据写入目的地;
d. 调用close方法关闭流。
范例:
//FileWriter类演示
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) {
/*
* 创建FileWriter对象并明确该文件。 如果文件不存在,则会自动创建。 如果文件存在,则会被覆盖。
* 如果构造函数中加入true,可以实现对文件进行续写
*/
FileWriter fw = null;
/*
* IO流的异常处理方式: 为防止代码异常导致流无法关闭, 因此在finally中对流进行关闭。
*/
try {
fw = new FileWriter(" demo. txt");
/*
* 调用Writer对象中的write(string)方法, 写入数据到临时存储缓冲区中。
*/
fw.write(" abcde");
/*
* 进行刷新,将数据直接写到目的地中。
*/
fw.flush();
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
/*
* 关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地。
*/
fw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败");
}
}
}
}
2.2 FileReader
该类用于从硬盘上的文件中读取字符。
步骤:a. 创建FileReader对象,明确要读取的文件;
b.调用read()方法,有两种读取方式;
c. 调用close方法关闭流。
范例:
//FileReader演示
import java.io.FileReader;
import java.io.IOException;
class FileReaderDemo {
public static void main(String[] args) throws IOException {
// 第一种读取方式
singleCharReader();
// 第二种读取方式
arrayCharReader();
}
// 第一种读取方式,单个字符读取
public static void singleCharReader() throws IOException {
/*
* 创建读取字符数据的流对象。 在创建读取流对象时, 必须要明确被读取的文件。一定要确定该文件是存在的。 用一个读取流关联一个已存在文件。
*/
FileReader fr = new FileReader("demo.txt");
int ch = 0;
// 读取字符数据
while ((ch = fr.read()) != -1) {
System.out.println((char) ch);
}
// 关闭读取流资源
fr.close();
}
// 第二种读取方式,通过字符数组进行读取
public static void arrayCharReader() throws IOException {
FileReader fr = new FileReader("demo.txt");
// 定义一个字符数组,用于临时存储读取的字符
char[] buf = new char[1024];
int len = 0;
while ((len = fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
fr.close();
}
}
3、字符流缓冲区之BufferedWriter、BufferedReader
3.1 BufferedWriter
与FileWriter结合使用,提高字符写入效率。
步骤:a. 创建FileWriter对象;
b. 创建BufferedWriter对象,与流对象关联;
c. 调用writer方法写入数据;
d. 关闭缓冲区。
3.2 BufferedReader
与FileReader结合使用,提高字符读取效率。
步骤:a. 创建FileReader对象,与要读取文件相关联;
b. 创建BufferedReader对象,与流对象关联;
c. 调用readline方法读取数据;
d. 关闭缓冲区。
范例:
//使用缓冲流复制一个文本文件
import java.io.*;
public class BufferedDemo {
public static void main(String[] args) {
BufferedWriter bfw = null;
BufferedReader bfr = null;
try {
// 创建写缓冲区对象
bfw = new BufferedWriter(new FileWriter("Demo_copy.txt"));
// 创建读缓冲区对象
bfr = new BufferedReader(new FileReader("Demo.txt"));
// 利调用readLine方法读取缓冲区数据
String line = null;
while ((line = bfr.readLine()) != null) {
bfw.write(line);// 写入指定文件中
bfw.newLine();// 写入换行
bfw.flush();// 将缓冲区数据刷到指定文件中
}
} catch (IOException e) {
throw new RuntimeException("文件copy失败");
} finally {
if (bfw != null)
try {
bfw.close();// 关闭写入流
} catch (IOException e) {
throw new RuntimeException("写入流关闭失败");
}
if (bfr != null)
try {
bfr.close();// 关闭读取流
} catch (IOException e) {
throw new RuntimeException("读取流关闭失败");
}
}
}
}
3、字节流
3.1 概述
字节流基本操作与字符流类相同,但它不仅可以操作字符, 还可以操作其他媒体文件。字节流类以InputStream(输入字节流)和OutputStream(输出字节流)为顶层。
3.2 字节流之FileInputStream、FileOutputStream
字节流读取和写入文件操作步骤基本与字符流相同,但是不需要进行刷新动作,因为字节流操作的是字节数据,可以直接写入。
范例:
//字节流之图片复制
import java.io.*;
public class CopyImageTest {
public static void main(String[] args) throws IOException {
// 创建流对象,明确操作文件
FileInputStream fis = new FileInputStream("c:\\1.png");
FileOutputStream fos = new FileOutputStream("c:\\2.png");
// 定义数组读写字节数据
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
// 关闭资源
fos.close();
fis.close();
}
}
3.3 字节流缓冲区
使用的类为BufferedInputStream和BufferedOutputStream,可以提高字节流的读写效率。
范例:
//字节流缓冲区演示
import java.io.*;
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
//创建流对象和字节流缓冲区对象,并与指定文件对象关联
FileInputStream fis = new FileInputStream("c:\\1.png");
BufferedInputStream bufis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("c:\\2.png");
BufferedOutputStream bufos = new BufferedOutputStream(fos);
//对字节不断读写
int ch = 0;
while ((ch = bufis.read()) != -1) {
bufos.write(ch);
}
//关闭资源
bufos.close();
bufis.close();
}
}
三、键盘录入和转换流
1、键盘录入
为了支持标准输入输出设备, Java 定义了两个特殊的流对象: System.in 和
System.out。 System.in 对应键盘输入数据,是 InputStream 类型的; System.out 对应显示器输出数据,是 PrintStream 类型的, PrintStream是 OutputStream 的一个子类。键盘可以被当作一个特殊的输入流,显示器可以被当作一个特殊的输出流。
范例:
//键盘录入演示
import java.io.IOException;
import java.io.InputStream;
//获取用户键盘录入的数据,并将数据显示到控制台上,如果用户输入over,技术键盘录入
public class KeyboardDemo {
public static void main(String[] args) throws IOException {
// 1,创建容器。
StringBuilder sb = new StringBuilder();
// 2,获取键盘读取流。
InputStream in = System.in;
// 3,定义变量记录读取到的字节,并循环获取。
int ch = 0;
while ((ch = in.read()) != -1) {
// 在存储之前需要判断是否是换行标记 ,因为换行标记不存储。
if (ch == '\r')
continue;
if (ch == '\n') {
String temp = sb.toString();
if ("over".equals(temp))
break;
System.out.println(temp.toUpperCase());
sb.delete(0, sb.length());
} else
// 将读取到的字节存储到StringBuilder中。
sb.append((char) ch);
}
}
}
2、转换流
转换流是字符流与字节流之间的桥梁,方便了字符流与字节流之间的操作
当字节流中的数据都是字符时,转成字符流操作更高效。
什么时候使用转换流呢?
a. 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁,提高对文本操作的便捷。
b. 一旦操作文本涉及到具体的指定编码表时,必须使用转换流。
转换流类:
InputStreamReader: 字节到字符的桥梁, 解码。
OutputStreamWriter: 字符到字节的桥梁, 编码。
范例:
//转换流演示
import java.io.*;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {
// 读取键盘输入,字节流转换为字符流
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
// 输出到控制台,字符流转换为字节流
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(
System.out));
// 将读到的字符数据进行转换输出
String line = null;
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
// 刷新输出,默认的输入和输出系统不需要关, 它会随着系统的结束而消失
bufw.flush();
}
}
}
四、流的操作规律总结
1、明确体系:
数据源:InputStream ,Reader
数据目的:OutputStream,Writer
2、明确数据:分两种:字节,字符。
数据源:是否是纯文本数据
是:Reader
否:InputStream
数据目的:是否是纯文本数据
是:Writer
否:OutputStream
到这里就可以明确具体要使用哪一个体系了。
剩下的就是要明确使用这个体系中的哪个对象。
3、明确设备:
数据源:
键盘:System.in
硬盘:FileXXX
内存:数组。
网络:socket socket.getInputStream();
数据目的:
控制台:System.out
硬盘:FileXXX
内存:数组
网络:socket socket.getOutputStream();
4、明确额外功能:
需要转换?是,使用转换流。InputStreamReader OutputStreamWriter
需要高效?是,使用缓冲区。Buffered
范例:
//流的规律演示
import java.io.*;
/*需求: 按照指定编码写字符到指定文件中。
*
* 1、目的:OutputStream、Writer
* 2、是纯文本:Writer
* 3、设备:硬盘 FileXXX
* 4、额外功能:需求中已经明确指定了编码表,不可使用FileWriter, 因为FileWriter内部使用的默认的本地码表。
* 所以只能使用其父类 OutputStreamWriter。
* OutputStreamWriter接收一个字节输出流对象, 既然是操作文件, 那么该对象应该是FileOutputStream。
* OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName);
* 并且需要高效:BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName));
*/
public class TransStreamDemo1 {
public static void main(String[] args) throws IOException {
// 键盘读取字符输入
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
// 将读到的字符以uft-8编码格式写入到a.txt文件中
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("a.txt"), "utf-8"));
String line = null;
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
}
------Java培训、Android培训、期待与您交流! -------