Java IO学习笔记(二):字节流与字符流
首先我们要知道流的概念
。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。
字节流与字符流
以上这四个都是抽象类
。
文件操作流程:
- 使用File类打开一个文件
- 通过字节流或字符流的子类,指定输出的位置
- 进行读/写操作
- 关闭输入/输出
注意:IO操作属于资源操作,一定要记得关闭。
字节流
字节流主要是操作byte类型
数据,以byte数组为准,主要操作类就是OutputStream、InputStream
。
字节输出流:OutputStream(向文件写入内容)
OutputStream是整个IO包中字节输出流的最大父类
,定义如下:
public abstract class OutputStream extends Object implements Closeable,Flushable
有上面的定义可以看出:
- 此类是一个抽象类,必须通过
子类实例化对象
才能使用 - 使用
FileOutputStream类
。通过向上转型之后,可以为OutputStream实例化 -
Closeable
表示可以关闭的操作 -
Flushable
:表示刷新,清空内存中的数据
FileOutputStream类的构造方法如下:
写数据:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
OutputStream out = new FileOutputStream(f);//如果文件不存在会自动创建
String str = "Hello World";
byte[] b = str.getBytes();
out.write(b);//因为是字节流,所以要转化成字节数组进行输出
out.close();//最后一定要关闭
}
最后在E盘生成一个内容属Hello World
的 txt 文件。
也可以一个字节一个字节进行输出,如下:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
OutputStream out = new FileOutputStream(f);//如果文件不存在会自动创建
String str = "Hello World";
byte[] b = str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.close();//最后一定要关闭
}
以上输出只会进行覆盖,如果要追加的话,需要FileOutputStream类的另一个构造方法:
public FileOutputStream(File file,boolean append)throws FileNotFoundException
在构造方法中,如果将append的值设置为true
,则表示在文件的末尾追加内容。
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
OutputStream out = new FileOutputStream(f, true);//如果文件不存在会自动创建
String str = "\r\n 追加Hello World";
byte[] b = str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.close();//最后一定要关闭
}
文件内容变为:
文件中换行为:\r\n
字节输入流:InputStream(从文件中把内容读取进来)
InputStream类的定义:
public abstract class InputStream extends Object implements Closeable
InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,就用FileInputStream来实现。
FileInputStream类的构造方法:
public FileInputStream(File file)throws FileNotFoundException
读文件
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
InputStream in = new FileInputStream(f);
byte[] b = new byte[(int) f.length()];//根据文件的大小来定义字节数组的大小
int len = in.read(b);
in.close();
System.out.println(new String(b, 0, len));
}
控制台打印结果:
换种方式,一个字节一个字节读入:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
InputStream in = new FileInputStream(f);
byte[] b = new byte[(int) f.length()];//根据文件的大小来定义字节数组的大小
for (int i = 0; i < b.length; i++) {
b[i] = (byte) in.read();
}
in.close();
System.out.println(new String(b));
}
控制台打印结果:
以上情况只适合知道输入文件的大小
,不知道的话用如下方法:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
InputStream in = new FileInputStream(f);
byte[] b = new byte[1024];
int temp = 0;
int len = 0;
while ((temp = in.read()) != -1) {//-1为文件读完的标志
b[len] = (byte) temp;
len++;
}
in.close();
System.out.println(new String(b, 0, len));
}
字符流
一个字符等于两个字节
,java提供了Reader、Writer
两个专门操作字符流的类。
字符输出流:Writer(向文件写入内容)
Writer本身是一个字符流的输出类,定义如下:
public abstract class Writer extends Object implements Appendable,Closeable,Flushable
此类本身也是一个抽象类,如果要使用此类,则肯定要使用其子类.如果是向文件中写入内容
,所以应该使用FileWriter
的子类。
FileWriter类的构造方法定义如下:
public FileWriter(File file)throws IOException
字符流的操作比字节流操作好在一点,就是可以直接输出字符串
,不用再像之前那样进行转换操作。
写数据
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
Writer out = new FileWriter(f);
String str = "Hello World进行测试";
out.write(str);
out.close();
}
在默认情况下再次输出会覆盖,追加的方法也是在构造函数上加上追加标记
。
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
Writer out = new FileWriter(f,true);
String str = "\r\nHello World进行测vdfvb试";
out.write(str);
out.close();
}
字符输入流:Reader(从文件读取内容)
Reader是使用字符的方式从文件中取出数据,Reader类的定义如下:
public abstract class Reader extends Objects implements Readable,Closeable
Reader本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用FileReader子类。
FileReader的构造方法定义如下:
public FileReader(File file)throws FileNotFoundException
以字符数组的形式读取出数据:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
Reader input = new FileReader(f);
char[] c = new char[1024];
int len = input.read(c);
input.close();
System.out.println(new String(c, 0, len));
}
也可以用循环方式,判断是否读到底:
public static void main(String[] args) throws IOException {
File f = new File("E:" + File.separator + "IO.txt");
Reader input = new FileReader(f);
char[] c = new char[1024];
int temp = 0;
int len = 0;
while ((temp = input.read()) != -1) {
c[len] = (char) temp;
len++;
}
input.close();
System.out.println(new String(c, 0, len));
}
拓展:通过字节缓冲流实现文件拷贝
/**
* 通过字节缓冲流实现文件的拷贝
*
* @param sourcePath 源文件路径
* @param targetPath 目标文件路径
*/
public static void copyFileByBuffered(String sourcePath, String targetPath){
//源文件路径
File source = new File(sourcePath);
//目标文件路径
File target = new File(targetPath);
//如果源文件不存在则不能拷贝
if (!source.exists()) {
return;
}
//如果目标文件目录不存在则创建
if (!target.getParentFile().exists()) {
target.getParentFile().mkdirs();
}
InputStream in = null;
OutputStream out = null;
try {
//字节缓冲输入流和字节缓冲输出流
in = new BufferedInputStream(new FileInputStream(source));
out = new BufferedOutputStream(new FileOutputStream(target));
byte[] b = new byte[1024];
int temp = 0;
//每次读取一个1024的字节数组
while((temp = in.read(b)) != -1){
//输出到文件
out.write(b,0,temp);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭流
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
连接拓展:java IO学习笔记(一)File类