字节输出流——OutputStream(程序——>文件)
OutputStream是一个抽象类,需要子类来初始化实例。已知直接子类有FileOutputStream。
除了close()和flush()方法(任何涉及流的操作都需要关闭close),Outputstream的写入输出流(byte字节或byte数组->输出流->文件)有三个重载方法:
- public abstract void write(int b) throws IOException:一次只写入一个字节
- public void write(byte[] b) throws IOException:一次写入整个字节数组
- public void write(byte[] b, int off, int len) throws IOException:一次写入从off开始,长度为len的字节数组
FileOutputStream的两个常用的构造方法:
- public FileOutputStream(File file) throws FileNotFoundException:调用此构造方法每此写入的输出流会覆盖原有文件
- public FileOutputStream(File file, boolean append) throws FileNotFoundException:调用此构造方法每次会在原有文件末尾追加内容,不覆盖原有文件
1.一次只向输出流写入一个字节,每次覆盖原有文件
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("d:" + File.separator + "test2.txt");
//倘若父目录不存在,则创建所有这条路径上必须的父目录
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
//倘若文件不存在,则会创建一个新的空文件
//覆盖原有文件
OutputStream outputStream=new FileOutputStream(file);
//每次在末尾追加内容,不覆盖原有文件
// OutputStream outputStream=new FileOutputStream(file,true);
String str="你好,world\r\n";//\r\n在文件中表示换行,共占两个字节
//采用默认编码将字符串转化为字节数组,我默认用utf-8
// 在中文平台下,如果指定的字符集编码是UTF-8,那么按照UTF-8对中文的编码规则:每个中文用
//3个字节表示
byte[] bytes=str.getBytes();
for (int i=0;i<bytes.length;i++){
outputStream.write(bytes[i]);
}//一个一个字节输出
// outputStream.write(bytes);//一整个字节数组输出
// outputStream.write(bytes,3,5);//部分字节数组输出
outputStream.close();//流的操作都要在最后关闭
}
}
运行结果:(打开text.txt文件)
你好,world
2.调用outputstream.write(bytes)与上面的运行结果相同。
3.调用outputstream.write(bytes,1,4)运行结果:(打开text.txt文件)
好,w
4.text.txt文件不去改动,调用new FileOutputStream(file,true)构造方法初始化,outputstream.write(bytes)写入输出流,执行三次后,文件会在末尾追加三次内容,运行结果:(打开text.txt文件)
好,w你好,world
你好,world
你好,world
字节输入流——InputStream(文件——>程序)
InputStream也是一个抽象类,它也需要子类来实例化。我们这里主要讲解它的直接子类FileInputStream。InputSteam也有close()方法,但没有flush()。而且相对应的,InputStream也有三个重载的读取方法(文件->输出流->byte数组):
- public abstract int read() throws IOException:一次只读取一个字节,返回读取的字节值,若流已经到底读取完了,则返回-1
- public int read(byte[] b) throws IOException:一次最多读取数组b的长度,返回读取的字节数,若流已经到底读完了,则返回-1
- public int read(byte[] b, int off, int len) throws IOException:一次最多读取从off开始,长度为len的字节数组b,返回读取的字节数,若流已经到底读完了,则返回-1
FileInputStream的一个常用构造方法,它没有像OutputStream那样有追加内容的另一个构造方法:
- public FileInputStream(File file) throws FileNotFoundException
示例:用第一种方法将文件中的数据读取到一个byte数组
public class Test {
public static void main(String[] args) throws IOException {
File file=new File("J:"+File.separator+"coding"+File.separator+"test"+File.separator+"test.txt");
if(file.exists()){
InputStream inputStream=new FileInputStream(file);
byte[] bytes=new byte[1024];//用来存放从文件中读取的数据
int count=0;
int temp=0;
// inputStream.read(bytes); 第二种方法
while ((temp=inputStream.read())!=-1){//第一种方法:每次读取一个字节,并赋值给temp
bytes[count++]=(byte) temp;
}
inputStream.close();//关闭输入流
//输出结果可以看出count的作用
System.out.println("["+new String(bytes,0,count)+"]");
System.out.println("**********************************************");
System.out.println("["+new String(bytes)+"]");
System.out.println("***********************************************");
}
}
}
运行结果:
[你好,world!
I miss you
我想你
但
我错过你了]
**********************************************
[你好,world!
I miss you
我想你
但
我错过你了 ]
***********************************************
字符输出流——Writer(程序——>文件)
Writer也是一个抽象类,需要子类来初始化实例。这里我们使用它的子类FileWriter。
Writer类 也有close()和flush()方法,除此之外,Writer类还有重载的五个写的方法等其他方法,举例两个:
- public void write(char[] cbuf) throws IOException:一次写入整个字符数组
- public void write(String str) throws IOException:一次写入整个字符串
和FileOutputStream一样,FileWriter也有两个常用的构造方法:
- public FileWriter(File file) throws FileNotFoundException:调用此构造方法每此写入的输出流会覆盖原有文件
- public FileWriter(File file, boolean append) throws FileNotFoundException:调用此构造方法每次会在原有文件末尾追加内容,不覆盖原有文件
示例:将字符串写入文件
public class Test {
public static void main(String[] args) throws IOException {
File file=new File("J:"+File.separator+"coding"+File.separator+"test"+File.separator+"test.txt");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
Writer writer=new FileWriter(file);
String str="好好学习,天天向上";
writer.write(str);
writer.close();//流必须要关闭,尤其是字符流,不进行close()可能会没有写到文件中
}
}
运行结果(打开text.txt文件):
好好学习,天天向上
字符输入流——Reader(文件——>程序)
Reader类也是一个抽象类,这里我们使用FileReader来初始化。
Reader类和InputStream类一样,只有close()方法,没有flush()方法。Reader类有4个重载的读取数据的方法:
- public int read() throws IOException:读取一个字符,并返回字符编码,已经读到底返回-1
- public int read(char[] cbuf) throws IOException:读取数据到字符数组,并返回读取的字符个数,已经读到底返回-1
- public abstract int read(char[] cbuf, int off, int len) throws IOException:读取数据到off开始长度为len的字符数组,并返回读取的字符个数,已经读到底返回-1
- public int read(CharBuffer target) throws IOException
示例:读取文件内容到字符数组
public class Test {
public static void main(String[] args) throws IOException {
File file=new File("J:"+File.separator+"coding"+File.separator+"test"+File.separator+"test.txt");
if (file.exists()){
char[] data=new char[1024];
int count=0;
Reader reader=new FileReader(file);
count=reader.read(data);
reader.close();
System.out.println("["+new String(data,0,count)+"]");
}
}
}
运行结果:
[好好学习,天天向上]
字节流与字符流的区别
字节流与字符流最大的区别是:字节流直接与终端进行数据交互,而字符流需要将数据经过缓冲区处理后才能输出。在使用OutputStream进行数据输出的时候,即使最后没有close()也能将数据正常输出到文件,但是使用Writer的话,如果最后没有关闭流,那么表示存在缓冲区的数据不会被强制清空就,所以有可能不能正常输出数据到文件。也可以用flush()强制清空缓冲区。
在开发之中对于字节数据处理是比较多的,如图片、电影、音乐、文字。所以,如果处理中文优先考虑字符流,没有中文建议使用字节流。
转换流——OutputStreamWriter和InputStreamReader
OutputStreamWriter和InputStreamReader分别是Writer和Reader的子类,也是FileWriter和FileReader的父类,这两个不是抽象类,主要作用是将字节流转换为字符流。它们的构造方法就能实现这样的功能:
OutputStreamWriter:
- public OutputStreamWriter(OutputStream out):接收字节输出流流,返回字符输出流
InputStreamReader:
- public InputStreamReader(InputStream in):接收字节输入流,返回字符输出流
示例:通过OutputStreamWriter将字节输出流转换为字符输出流输出字符串内容到文件
public class Test {
public static void main(String[] args) throws IOException {
File file=new File("J:"+File.separator+"coding"+File.separator+"test"+File.separator+"test.txt");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
OutputStream out=new FileOutputStream(file);
Writer writer=new OutputStreamWriter(out);
String str="好好学习,天天向上";
writer.write(str);
writer.close();//这里已经转换为字符流,所以同样的,如果不关闭,有可能不会正常输出
}
}
运行结果(打开text.txt文件):
好好学习,天天向上
利用字节流进行文件拷贝
public class Test {
public static void main(String[] args) throws IOException {
File file=new File("J:"+File.separator+"壁纸图片"+File.separator+"1.jpg");//源文件路径
if(!file.exists()){
return;
}
File file1=new File("J:"+File.separator+"壁纸图片"+File.separator+"2.jpg");//目标文件路径
if (!file1.getParentFile().exists()){
file1.getParentFile().mkdirs();
}
InputStream in=new FileInputStream(file);
OutputStream out=new FileOutputStream(file1);
int count=0;
byte[] bytes=new byte[1024];
while ((count=in.read(bytes))!=-1){
out.write(bytes,0,count);
}
in.close();
out.close();
}
}
运行结果:
上面的例子是开辟了一个长度为1024的byte数组进行读取和输出的,也可以一个一个字节读和输,但是那样速度会很慢。