在较深入学习Java IO后,给出常用的字符流和字节流的示例代码。通过示例进一步了解和学习Java IO的整体架构和设计思想,并将其应用到实际开发中。
Java中I/O操作主要是指使用Java进行输入、输出操作。机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。简而言之:数据流是包括输入流和输出流的一组有序的有起点和终点的字节的数据序列。
当程序需要读取数据的时候,就会建立一个通向数据源的连接,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会建立一个通向目的地的连接。
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。Java中的流分为两种:
(1) 字节流:数据流中最小的数据单元是字节 。
(2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
1、基于字节的输入输出流
比较常用的基于字节的输入流有FileInputStream、ByteArrayInputStream 、BufferedInputStream;基于字节的输出流有FileOutputStream 、ByteArrayOutputStream 、BufferedOutputStream 。
/**
* 将文件作为流进行读写
*/
@Test
public void fileStreamTest() {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\test1.txt");
fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test2.txt");
byte[] bytes = new byte[1024];
while (fileInputStream.read(bytes) != -1) {
fileOutputStream.write(bytes);
}
System.err.println("fileStreamTest: " + fileOutputStream.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 内存中缓冲区作为流进行读写
*/
@Test
public void byteArrayStreamTest() {
ByteArrayInputStream byteArrayInputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
String testStr = "Test the byte array stream!";
byte[] bytes = new byte[1024];
try {
byteArrayInputStream = new ByteArrayInputStream(testStr.getBytes());
byteArrayOutputStream = new ByteArrayOutputStream();
while (byteArrayInputStream.read(bytes) != -1) {
byteArrayOutputStream.write(bytes);
}
System.err.println("byteArrayStreamTest: " + byteArrayOutputStream.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 带有缓冲的流输入输出
*
*/
@Test
public void bufferStreamTest(){
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
byte[] bytes = new byte[1024];
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\test1.txt"));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test2.txt"));
while (bufferedInputStream.read(bytes) != -1) {
bufferedOutputStream.write(bytes);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、基于字符的输入输出流
比较常用的基于字符的输入流有FileReader 、InputStreamReader 、StringReader;基于字符的输出流有FileWriter 、OutputStreamWriter 、StringWriter 。
/**
* 基于文件的字符流
*/
@Test
public void fileReader2WriterTest() {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
fileReader = new FileReader("C:\\Users\\Administrator\\Desktop\\test1.txt");
fileWriter = new FileWriter("C:\\Users\\Administrator\\Desktop\\test2.txt");
char[] chars = new char[1024];
while (fileReader.read(chars) != -1) {
fileWriter.write(chars);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
if (fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 字节流和字符流间的转换 InputStreamReader、OutputStreamWriter
*/
@Test
public void inputStreamReader2WriterTest() {
InputStreamReader inputStreamReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
//多种实现
// inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\Administrator\\Desktop\\test1.txt"));
// inputStreamReader = new InputStreamReader(new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\test1.txt")));
inputStreamReader = new InputStreamReader(new ByteArrayInputStream(new String("I am just test inputStreamReader2WriterTest").getBytes()));
// outputStreamWriter = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test2.txt")));
// outputStreamWriter = new OutputStreamWriter(new ByteArrayOutputStream());
outputStreamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test2.txt"));
char[] chars = new char[1024];
while (inputStreamReader.read(chars) != -1) {
outputStreamWriter.write(chars);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 对字符串进行读写的字符流
*/
@Test
public void stringReader2WriterTest() {
StringReader stringReader = null;
StringWriter stringWriter = null;
try {
stringReader = new StringReader("I am just test stringReader2WriterTest");
stringWriter = new StringWriter();
char[] chars = new char[1024];
while (stringReader.read(chars) != -1) {
stringWriter.write(chars);
}
System.out.println(stringWriter.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stringReader != null) {
stringReader.close();
}
if (stringWriter != null) {
stringWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、总结
本文给出了常用字节流和字符流代码示例。可以看出各种流之间可相互包装,还可以将字节流转换为字符流。这也正好对应着Java I中的两种经典设计模式:装饰者模式和适配器模式。感兴趣的读者可以自行研究下源码,我想你也会有所收获的。另需注意:流使用完后一定要记得关闭!!!