1. InputStream和OutputStream
1.1 字节输入流:InputStream
java.io.InputStream
抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
-
public int read()
: 从输入流读取一个字节。返回读取的字节值。虽然读取了一个字节,但是会自动提升为int类型。如果已经到达流末尾,没有数据可读,则返回-1。 -
public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。每次最多读取b.length个字节。返回实际读取的字节个数。如果已经到达流末尾,没有数据可读,则返回-1。 -
public int read(byte[] b,int off,int len)
:从输入流中读取一些字节数,并将它们存储到字节数组 b中,从b[off]开始存储,每次最多读取len个字节 。返回实际读取的字节个数。如果已经到达流末尾,没有数据可读,则返回-1。 -
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。
说明:close()方法,当完成流的操作时,必须调用此方法,释放系统资源。
1.2 字节输出流:OutputStream
java.io.OutputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
-
public void write(int b)
:将指定的字节输出流。虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。 -
public void write(byte[] b)
:将 b.length字节从指定的字节数组写入此输出流。 -
public void write(byte[] b, int off, int len)
:从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 -
public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。 -
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。
说明:close()方法,当完成流的操作时,必须调用此方法,释放系统资源。
2 FileInputStream 与 FileOutputStream
2.1 FileInputStream
java.io.FileInputStream
类是文件输入流,从文件中读取字节。
-
FileInputStream(File file)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 -
FileInputStream(String name)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
举例:
//read.txt文件中的内容如下:
abcde
读取操作
public class FISRead {
//注意:应该使用try-catch-finally处理异常。这里出于方便阅读代码,使用了throws的方式
@Test
public void test() throws IOException {
// 使用文件名称创建流对象
FileInputStream fis = new FileInputStream("read.txt");
// 读取数据,返回一个字节
int read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
// 读取到末尾,返回-1
read = fis.read();
System.out.println(read);
// 关闭资源
fis.close();
/*
文件内容:abcde
输出结果:
a
b
c
d
e
-1
*/
}
@Test
public void test02()throws IOException{
// 使用文件名称创建流对象
FileInputStream fis = new FileInputStream("read.txt");
// 定义变量,保存数据
int b;
// 循环读取
while ((b = fis.read())!=-1) {
System.out.println((char)b);
}
// 关闭资源
fis.close();
}
@Test
public void test03()throws IOException{
// 使用文件名称创建流对象.
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
// 定义变量,作为有效个数
int len;
// 定义字节数组,作为装字节数据的容器
byte[] b = new byte[2];
// 循环读取
while (( len= fis.read(b))!=-1) {
// 每次读取后,把数组变成字符串打印
System.out.println(new String(b));
}
// 关闭资源
fis.close();
/*
输出结果:
ab
cd
ed
最后错误数据`d`,是由于最后一次读取时,只读取一个字节`e`,数组中,
上次读取的数据没有被完全替换,所以要通过`len` ,获取有效的字节
*/
}
@Test
public void test04()throws IOException{
// 使用文件名称创建流对象.
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
// 定义变量,作为有效个数
int len;
// 定义字节数组,作为装字节数据的容器
byte[] b = new byte[2];
// 循环读取
while (( len= fis.read(b))!=-1) {
// 每次读取后,把数组的有效字节部分,变成字符串打印
System.out.println(new String(b,0,len));// len 每次读取的有效字节个数
}
// 关闭资源
fis.close();
/*
输出结果:
ab
cd
e
*/
}
}
2.2 FileOutputStream
java.io.FileOutputStream
类是文件输出流,用于将数据写出到文件。
-
public FileOutputStream(File file)
:创建文件输出流,写出由指定的 File对象表示的文件。 -
public FileOutputStream(String name)
: 创建文件输出流,指定的名称为写出文件。 -
public FileOutputStream(File file, boolean append)
: 创建文件输出流,指明是否在现有文件末尾追加内容。
举例:
package com.atguigu.fileio;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
public class FOSWrite {
//注意:应该使用try-catch-finally处理异常。这里出于方便阅读代码,使用了throws的方式
@Test
public void test01() throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 写出数据
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节
fos.write(99); // 写出第3个字节
// 关闭资源
fos.close();
/* 输出结果:abc*/
}
@Test
public void test02()throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
fos.write(b,2,2);
// 关闭资源
fos.close();
}
//这段程序如果多运行几次,每次都会在原来文件末尾追加abcde
@Test
public void test03()throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt",true);
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
fos.write(b);
// 关闭资源
fos.close();
}
//使用FileInputStream\FileOutputStream,实现对文件的复制
@Test
public void test05() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1. 造文件-造流
//复制图片:成功
// fis = new FileInputStream(new File("pony.jpg"));
// fos = new FileOutputStream(new File("pony_copy1.jpg"));
//复制文本文件:成功
fis = new FileInputStream(new File("hello.txt"));
fos = new FileOutputStream(new File("hello1.txt"));
//2. 复制操作(读、写)
byte[] buffer = new byte[1024];
int len;//每次读入到buffer中字节的个数
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
// String str = new String(buffer,0,len);
// System.out.print(str);
}
System.out.println("复制成功");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//3. 关闭资源
try {
if (fos != null)
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (fis != null)
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3. 练习
**练习:**实现图片加密操作。
提示:
public class FileSecretTest {
/*
* 图片的加密
* */
@Test
public void test1(){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File file1 = new File("pony.jpg");
File file2 = new File("pony_secret.jpg");
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
//方式1:每次读入一个字节,效率低
// int data;
// while((data = fis.read()) != -1){
// fos.write(data ^ 5);
// }
//方式2:每次读入一个字节数组,效率高
int len;
byte[] buffer = new byte[1024];
while((len = fis.read(buffer)) != -1){
for(int i = 0;i < len;i++){
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer,0,len);
}
System.out.println("加密成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 图片的解密
* */
@Test
public void test2(){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File file1 = new File("pony_secret.jpg");
File file2 = new File("pony_unsecret.jpg");
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
//方式1:每次读入一个字节,效率低
// int data;
// while((data = fis.read()) != -1){
// fos.write(data ^ 5);
// }
//方式2:每次读入一个字节数组,效率高
int len;
byte[] buffer = new byte[1024];
while((len = fis.read(buffer)) != -1){
for(int i = 0;i < len;i++){
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer,0,len);
}
System.out.println("解密成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}