一切皆为字节
我们可以右键查看我们的每一个文件的属性,在常规那一栏,你会发现无论是什么文件他在硬盘的存储形式都是以字节形式存储。
大纲
因此java就提供了一种以字节流读取文件的类,但是,如果以字节流进行读取文件,对于不同的编码格式组成的字节是不一样的,容易出现乱码情况。比如:GBK编码和UTF-8编码,对于中文的编码一个是两个字节另外一个是三个字节。众所周知,对于所有的文字,英语字母都是以字符组成,因此在字节流的基础之上,java也提供了以字符流进行读取文件的方法。但这只是解决了基础的以字符解决,还没有满足到GBK和UTF-8编码格式之间的互转,因此java后面又推出了建立字符和字节之间的桥梁,可以通过他进行编码格式的转换。
图解大纲
字节流读取文件
读文件(未使用缓冲对)
FileInputStream
创建方法
方法 | 概述 |
---|
FileInputStream(File file) | 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名 |
常用方法
返回值 | 方法 | 概述 |
---|
int | read() | 从该输入流读取一个字节的数据 |
int | read(byte[] b) | 从该输入流读取最多 b.length个字节的数据为字节数组 |
void | close() | 关闭此文件输入流并释放与流相关联的任何系统资源 |
使用步骤
- 创建fileinputstream对象
- 接收数据
- 读完数据。关闭对象,释放资源
样例
package fileReadAndWrite;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("C:\\aaa\\a.txt");
int len ;
byte[] bytes = new byte[1024];
while((len = inputStream.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len));
}
inputStream.close();
}
}
写文件(未使用缓冲对)
FileOutputStream
创建方法
方法 | 概述 |
---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件 |
FileOutputStream(File file, boolean append) | 第二参数可设置是否追加写入 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件 |
FileOutputStream(String name, boolean append) | 第二参数可设置是否追加写入 |
常用方法
返回值 | 方法 | 概述 |
---|
void | write(int b) | 将指定的字节写入此文件输出流 |
void | write(byte[] b) | 将 b.length个字节从指定的字节数组写入此文件输出流 |
void | write(byte[] b, int off, int len) | 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流 |
void | close() | 关闭此文件输出流并释放与此流相关联的任何系统资源 |
使用步骤
- 创建fileoutputstream对象
- 开始向该路径写东西
- 写完数据。关闭对象,释放资源
样例
package fileReadAndWrite;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) throws IOException {
FileOutputStream outputStream = new FileOutputStream("C:\\aaa\\a.txt",true);
outputStream.write(97);
byte[] bytes = {97,98,99};
outputStream.write("\r\n".getBytes());
outputStream.write(bytes);
outputStream.close();
}
}
引入缓冲对的原因
- 为了进一步缓和CPU和I/O设备之间速度不匹配的矛盾。
- 加快输入输出速度
- 提高CPU和I/O设备之间的并行性
读文件(使用缓冲对)
BufferedInputStream
创建方法
方法 | 概述 |
---|
BufferedInputStream(InputStream in) | 创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用 |
BufferedInputStream(InputStream in, int size) | 创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用 |
常用方法
返回值 | 方法 | 概述 |
---|
int | read() | 从该输入流读取一个字节的数据 |
int | read(byte[] b) | 从该输入流读取最多 b.length个字节的数据为字节数组 |
void | close() | 关闭此文件输入流并释放与流相关联的任何系统资源 |
使用步骤
- 创建BufferedInputStream对象,传入一个fileinputstream对象
- 接受数据
- 读完数据。关闭对象,释放资源
样例
package fileReadAndWrite;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class BufferedInputStreamTest {
public static void main(String[] args) throws IOException {
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream("C:\\aaa\\a.txt"));
int len ;
byte[] bytes = new byte[1024];
while((len = inputStream.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len));
}
inputStream.close();
}
}
写文件(使用缓冲对)
BufferedOutputStream
创建方法
方法 | 概述 |
---|
BufferedOutputStream(OutputStream out) | 创建一个新的缓冲输出流,以将数据写入指定的底层输出流 |
BufferedOutputStream(OutputStream out, int size) | 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流 |
常用方法
返回值 | 方法 | 概述 |
---|
void | write(int b) | 将指定的字节写入此文件输出流 |
void | write(byte[] b) | 将 b.length个字节从指定的字节数组写入此文件输出流 |
void | write(byte[] b, int off, int len) | 从指定的字节数组写入 len个字节,从偏移 off开始到缓冲的输出流 |
void | close() | 关闭此文件输出流并释放与此流相关联的任何系统资源 |
void | flush() | 刷新缓冲输出流 |
使用步骤
- 创建BufferedOutputStream对象,传入一个fileoutputstream对象
- 使用write写入数据
- 刷新缓冲对里面的数据
- 读完数据。关闭对象,释放资源。也会自动刷新缓冲对数据,因此第三步可省略
样例
package fileReadAndWrite;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputStreamTest {
public static void main(String[] args) throws IOException {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream("C:\\aaa\\a.txt",true));
outputStream.write(97);
byte[] bytes = {97,98,99};
outputStream.write("\r\n".getBytes());
outputStream.write(bytes);
outputStream.write("你好".getBytes());
outputStream.flush();
outputStream.close();
}
}
字符流读取文件
读文件(未使用缓冲对)
FileReader
创建方法
方法 | 概述 |
---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File读取 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称 |
常用方法
返回值 | 方法 | 概述 |
---|
int | read() | 读一个字符 |
int | read(char[] cbuf) | 从该输入流读取最多 cbuf.length个字符 |
void | close() | 关闭此文件输入流并释放与流相关联的任何系统资源 |
使用步骤
- 创建FileReader对象,构造方法中绑定要读取的数据源
- 使用FileReader对象中的方法read读取文件
- 释放资源
样例
package fileReadAndWrite;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("C:\\aaa\\c.txt");
int len = 0;
char[] buf = new char[1024];
while((len = reader.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
reader.close();
}
}
写文件(未使用缓冲对)
FileWriter
创建方法
方法 | 概述 |
---|
FileWriter(File file) | 给一个File对象构造一个FileWriter对象 |
FileWriter(File file, boolean append) | 给一个File对象构造一个FileWriter对象 |
FileWriter(String fileName) | 构造一个给定文件名的FileWriter对象 |
FileWriter(String fileName, boolean append) | 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据 |
常用方法
返回值 | 方法 | 概述 |
---|
void | write(int c) | 写一个字符 |
void | write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void | write(String str, int off, int len) | 写一个字符串的一部分 |
void | flush() | 刷新流 |
void | close() | 关闭流,先刷新 |
使用步骤
- 创建FileWriter对象,构造方法中绑定要写入数据的目的地
- 使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
- 使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
- 释放资源(会先把内存缓冲区中的数据刷新到文件中)
样例
package fileReadAndWrite;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) throws IOException {
FileWriter writer = new FileWriter("C:\\aaa\\d.txt", true);
writer.write("你好");
writer.write("\r\n");
writer.write("你好");
writer.write("\r\n");
writer.write("你好程序员",2,3);
writer.flush();
writer.close();
}
}
读文件(使用缓冲对)
BufferedReader
创建方法
方法 | 概述 |
---|
BufferedReader(Reader in) | 创建使用默认大小的输入缓冲区的缓冲字符输入流 |
BufferedReader(Reader in, int sz) | 创建使用指定大小的输入缓冲区的缓冲字符输入流 |
常用方法
返回值 | 方法 | 概述 |
---|
String | readLine() | 读一行文字 |
void | close() | 关闭流并释放与之相关联的任何系统资源 |
使用步骤
- 创建字符缓冲输入流对象,构造方法中传递字符输入流
- 使用字符缓冲输入流对象中的方法read/readLine读取文本
- 释放资源
样例
package fileReadAndWrite;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderTest {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("C:\\aaa\\d.txt"));
String len = null;
while( (len = reader.readLine()) != null) {
System.out.println(len);
}
reader.close();
}
}
写文件(使用缓冲对)
BufferedWriter
创建方法
方法 | 概述 |
---|
BufferedWriter(Writer out) | 创建使用默认大小的输出缓冲区的缓冲字符输出流 |
BufferedWriter(Writer out, int sz) | 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区 |
常用方法
返回值 | 方法 | 概述 |
---|
void | write(int c) | 写一个字符 |
void | write(char[] cbuf) | 写入字符数组 |
void | write(String s) | 写入字符串 |
void | write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void | write(String s, int off, int len) | 写一个字符串的一部分 |
void | newLine() | 写一行行分隔符 |
void | close() | 关闭流,先刷新 |
void | flush() | 刷新流 |
使用步骤
- 创建字符缓冲输出流对象,构造方法中传递字符输出流
- 调用字符缓冲输出流中的方法write,把数据写入到内存缓冲区中
- 调用字符缓冲输出流中的方法flush,把内存缓冲区中的数据,刷新到文件中
- 释放资源
样例
package fileReadAndWrite;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterTest {
public static void main(String[] args) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\aaa\\d.txt",true));
writer.newLine();
writer.write("我是一个假程序员");
writer.newLine();
writer.write("我是一个假程序员",2,5);
writer.flush();
writer.close();
}
}
通往字符流—>字节流桥梁(解决不同编码格式可正常读取)
读文件
InputStreamReader
创建方法
方法 | 概述 |
---|
InputStreamReader(InputStream in) | 使用默认编码格式读文件 |
InputStreamReader(InputStream in, String charsetName) | 指定编码格式读文件 |
常用方法
返回值 | 方法 | 概述 |
---|
int | read() | 读一个字符 |
int | read(char[] cbuf ) | 一次读取多个字符,将字符送入字符数组 |
void | close() | 关闭流并释放与之相关联的任何系统资源 |
使用步骤
- 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
- 使用InputStreamReader对象中的方法read读取文件
- 釋放资源
注意事项
- 构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码
样例
package fileReadAndWrite;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class InputStreamReaderTest {
public static void main(String[] args) throws IOException {
InputStreamReader reader = new InputStreamReader(new FileInputStream("C:\\aaa\\d.txt"),"gbk");
int len = 0;
char[] buf = new char[1024];
while((len = reader.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
reader.close();
}
}
写文件
OutputStreamWriter
创建方法
方法 | 概述 |
---|
OutputStreamWriter(OutputStream out) | 使用默认编码格式读文件 |
OutputStreamWriter(OutputStream out, String charsetName) | 指定编码格式读文件 |
常用方法
返回值 | 方法 | 概述 |
---|
void | write(int c) | 写一个字符 |
void | write(char[] cbuf) | 写入字符数组 |
void | write(String s) | 写入字符串 |
void | write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void | write(String s, int off, int len) | 写一个字符串的一部分 |
void | close() | 关闭流,先刷新 |
void | flush() | 刷新流 |
使用步骤
- 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
- 使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
- 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
- 释放资源
样例
package fileReadAndWrite;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class OutputStreamWriterTest {
public static void main(String[] args) throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\aaa\\e.txt",true),"utf-8");
writer.write("你好啊程序员");
writer.write("\r\n");
writer.write("我不好啊,程序员",1,4);
writer.flush();
writer.close();
}
}
综合案例
复制图片格式文件
注意事项
- 读取图片格式文件。只能使用字节流。
- 其余类似于文本文件,字符流更擅长
package fileReadAndWrite;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) throws IOException {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\aaa\\1.jpg"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\aaa\\2.jpg"));
int len = 0;
byte[] buf = new byte[1024];
while((len = bufferedInputStream.read(buf)) != -1) {
bufferedOutputStream.write(buf,0,len);
}
bufferedOutputStream.close();
bufferedInputStream.close();
}
}