字节流写数据
先了解一下有关字节流的两个类。InputStream、OutputStream类
InputStream类在java.io包下。该类是抽象类,继承了Object类,实现了Closeable接口
该类和该类的子类都是字节输入流
该类表示的是字节输入流的所有类的超类,该类的直接子类有AudioInputStream、ByteArrayInputStream等以InputStream结尾的类
OutputStream类在java.io包下。该类是抽象类,继承了Object类,实现了Closeable接口、Flushable接口
该类和该类的子类都是字节输入流
该类表示的是字节输出流的所有类的超类,该类的直接子类有FileOutputStream、ByteArrayOutputStream等以OutputStream结尾的类
字节流抽象基类
1、InputStream:这个抽象类是表示字节输入流的所有类的超类
2、OutPutStream:这个抽象类是表示字节输出流的所有类的超类
上面两个超类的子类名的特点:子类名称都是以父类名作为子类名的后缀
写数据需要用到OutPutStream类,但是OutPutStream是抽象类不能直接创建实例对象,所以我们要找OutPutStream类的子类来使用
思考找那个子类呢:我们写数据是要把数据写入文件的,所以就使用FileOutputStream这个子类
使用FileOutputStream类的FileOutputStream(String name)这个构造方法来创建字节输出流对象,作用是创建文件输出流以指定的名称写入文件
使用IO流写数据的三个步骤:
1、创建字节输出流对象(这一步做了三件事,详细看操作类,里面有写)
2、调用字节输出流对象的写数据方法
3、释放资源(这一步做了两件事情,详细看操作类,里面有写)
字节流写数据的练习
xxxxxxxxxx
package ch18;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//注意:不是在控制台看结果,而是去系统帮我们创建好的fos.txt文件有没有写入数据。数据是追加写入的,不是覆盖写入的
public class a_9_1测试 {
//下面那行的throws FileNotFoundException是14行抛出快捷键生成的,也可手动写
public static void main(String[] args) throws IOException {
//创建字节输出流对象。注意下面那行用的是相对路径
FileOutputStream fos = new FileOutputStream("java\\src\\ch18_ch19_储物区\\fos.txt");//我们没有提前创建fos.txt文件
//上面那行FileOutputStream报红线,抛出异常快捷键选中FileOutputStream,按Alt+Enter,选Add...
/*上面创建字节输出流对象fos做了三件事情:
1、调用系统功能创建了文件
2、创建了字节输出流对象
3、让字节输出流对象指向创建好的文件*/
//创建好文件,怎么写数据呢,需要用到FileOutputStream类的write(int b)方法,作用是将指定的字节写入此文件输出流
fos.write(97);//这行的write报红线,抛出异常快捷键选中FileOutputStream,按Alt+Enter,选Add...
//注意不是在控制台看结果,而是去系统帮我们创建好的fos.txt文件有没有写入了字节97对应的ASCII码值,即看fos.txt文件有没有写入小写的a
//思考:如何只写入97,而不是写入97对应的ASCII码值a,如下
fos.write(57);//57对应的ASCII码值是9
fos.write(55);//55对应的ASCII码值是7
//此时就在fos.txt文件里面追加97
//创建文件之后写入数据就结束了吗。其实对于所有跟IO操作相关的内容,最后还必须释放资源,如何释放如下
//close():作用是关闭此文件输出流并释放与此流相关联的任何系统资源
//close方法做了两件事情:分别是关闭此文件输出流、释放与此流相关联的任何系统资源
fos.close();
}
}
字节流写输入的三种方式
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流,一次写一个字节数据 |
void write(byte[] b) | 将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
void write(byte[] b,int off,int len) | 将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据 |
字节流写输入三种方式的练习
xxxxxxxxxx
package ch18;
//FileOutputStream类的创建对象的两个构造方法
//1、FileOutputStream(String name); 创建文件输出流以指定的名称写入文件
//2、FileOutputStream(File file); 创建文件输出流以写入由指定的File对象表示的文件
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class a_10_1测试 {
//下面那行的throws FileNotFoundException是17行抛出快捷键生成的,也可手动写
public static void main(String[] args) throws IOException {
//创建对象(第一种方法)
FileOutputStream fos = new FileOutputStream("java\\src\\ch18_ch19_储物区\\fos2.txt");//我们没有提前创建fos2.txt文件
//上面那行FileOutputStream报红线,抛出异常快捷键选中FileOutputStream,按Alt+Enter,选Add...
//上面17行的操作,在底层实际就是做了如下操作。即把字符串路径给封装成字符串对象File。上面的写法比较方便,底层的写法也可以,就是不方便
//FileOutputStream fos = new FileOutputStream(new File("java\\src\\ch18_储物区\\fos2.txt");
//------------------------------------------------------------------------------------------------------------------
//创建对象(第二种方法)
//由于该方法需要的参数是一个file对象,所以我们先创建一个file对象,如下
File file = new File("java\\src\\ch18_ch19_储物区\\fos3.txt");
//用上面那行的方法创建对象
FileOutputStream fos2 = new FileOutputStream(file);
//上面那行其实可以合并缩写,如下
FileOutputStream fos3 = new FileOutputStream(new File("java\\src\\ch18_ch19_储物区\\fos3.txt"));
//-------------------------------------------------------------------------------------------------------------------
//上面只是在将怎么创建对象的两种方式,下面开始真正讲写数据的三种方式,如下
//1、void write(int b) 将指定的字节写入此文件输出流,一次写一个字节数据
fos.write(97);//这行的write报红线,抛出异常快捷键选中write,按Alt+Enter,选Add...
fos.write(98);
fos.write(99);
fos.write(100);
//注意不是在控制台查看,而是去文件里面看,即取fos2.txt,上面对应写入的是a,b,c,d
//-----------------------------------------------------------------------------------
//2、void write(byte[] b) 将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
//该方法需要的是字节数组byte[],所以我们需要先定义一个字节数组,如下
byte[] bys = {102,103,104,105};
//下面那行需要自己写一个字节数组,有什么办法可以简单地获取一个字节数组,我们可以String类里面的getBytes()方法,
//该方法返回的是字符串对应的字节数组,如下
byte[] bys2 = "11111111".getBytes();
fos.write(bys);
fos.write(bys2);
//注意不是在控制台查看,而是去文件里面看,即去fos2.txt,上面对应写入的是f,g,h,i
//-----------------------------------------------------------------------------------
//void write(byte[] b,int off,int len) 将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据
//该方法也需要一个字节数组,我们来定义一下
byte[] bys3 = "23456789".getBytes();
fos.write(bys3,1,3);//从上面那行的bys3的数据里面,从索引1的位置,只往fos2.txt文件写入三个数据,即只写入345
//最后,别漏了释放资源的操作,如下
fos.close();
}
}
字节流写数据的两个小问题
第一个小问题:字节流写数据如何换行 1、写完数据后,加换行符。比如windows:\r\n linux:\n mac\r
第二个小问题:字节流写数据如何实现追加写入呢 1、public FileOutputStream(String name,boolean append) 2、创建文件输出流以指定的名称写入文件。如果第二个参数为true,则字节将写入文件的末尾而不是开头
字节流写数据两个小问题的练习
xxxxxxxxxx
package ch18;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class a_11_1测试 {
public static void main(String[] args) throws IOException {
//创建字节流输出对象
FileOutputStream fos = new FileOutputStream("java\\src\\ch18_ch19_储物区\\fos4.txt");
//写数据
for (int i = 0; i < 10; i++){//写10次数据,每一次是"hello"
fos.write("hello".getBytes());//但是会全部都输出在同一行,如何让每一个hello分行显示呢
//通过\n实现换行,如下
fos.write("\n".getBytes());//即可实现让每一个hello分行显示
//但是上面那行的操作,对于某些JDK版本,当我们用记事本打开fos4.txt,还是没换行
//原因:不同的操作系统对换行符号的识别不同,举例如下
//window:\r\n linux:\n mac:\r
//解决如下
fos.write("\r\n".getBytes());
}
//释放资源
fos.close();
//---------------------------------------------------------------------------------------------------------------
//字节流写数据如何实现追加写入呢,如下
FileOutputStream fos2 = new FileOutputStream("java\\src\\ch18_ch19_储物区\\fos5.txt",true);
//写数据
for (int i = 0; i < 10; i++){
fos2.write("hello".getBytes());
fos2.write("\n".getBytes());
}
//释放资源
fos2.close();
}
}
字节流写数据加异常处理
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的是否资源
finally块的特点:被finally控制的语句一定会执行,除非JVM退出
异常处理的写法格式
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
字节流写数据加异常处理的练习
xxxxxxxxxx
package ch18;
import java.io.FileOutputStream;
import java.io.IOException;
//字节流写数据加入异常处理。注意这里的解决异常,只使用了try...catch,不使用throws
public class a_12_1测试 {
public static void main(String[] args){
//FileOutputStream fos = new FileOutputStream("java\\src\\ch18_储物区\\fos5.txt");
//fos.write("hello".getBytes());
//fos.close();
//注意,没做异常处理时,上面的FileOutputStream、write、close会报红线错误
//我们之前是抛出处理,但如果需要本质上处理的话,需要try...catch处理,如下
//上面三行代码先注释,可以自行解开看看报的异常
//------------------------------------------------------------------------------------------------------------------
FileOutputStream fos = null;
try{
//FileOutputStream fos = new FileOutputStream("java\\src\\ch18_储物区\\fos5.txt");
fos = new FileOutputStream("java\\src\\ch18_ch19_储物区\\fos5.txt");//上面的'FileOutputStream fos'定义写在了try的外面
fos.write("hello112233".getBytes());
fos.close();//这行没有被执行到,是一个弊端
} catch(IOException e){//IOExceptions是抛出的异常类型
e.printStackTrace();
}
//上面虽然处理了异常,但是fos.close()释放资源没有执行到,即还少了一步释放资源。
//为什么没执行到fos.close(),因为:当执行完write方法的时候,程序报IOExceptions异常,就没有继续往下执行,而是去执行了catch里面的
//没有释放资源的话,在21行的FileOutputStream()调用的系统资源就会被一直占用
//如何解决释放资源fos.close()没有执行到的问题,如下
//我们可以使用finally块,写法是在try...catch后面继续写finally{}即可
finally {
if(fos != null){
try { //这里的try...catch是快捷键生成的,即'选中close,按Alt+Enter,选Surround...'
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//上面fos报红线的话,就把21行的'FileOutputStream fos'定义写在try的外面。注意写在外面时,要进行初始化,即赋值为null
//此时close就会异常报红线,我们选中close,按Alt+Enter,选Surround...
}
//其实还可以优化一下,当我们23行的路径写错时,为了finally里面不报空指针错误,我们可以在finally里面加一个if判断
}
}
字节流读数据_一次读一字节
需求:把文件fos.txt中的内容读取出来在控制台输出
读数据使用的是FileInputStream类,该类在java.io包下。该类是具体类,继承自InputStream
该类的作用是从文件系统中的文件获取输入字节
该类常用的构造方法:FileInputStream(String name),作用是通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
使用字节输入流读数据的步骤,如下 1、创建字节输入流对象 2、调用字节流对象的读数据方法,读数据的方法我们用的是FileInputStream类里面的read()方法,返回值类型是int 3、释放资源
字节流读数据_一次读一字节的练习
xxxxxxxxxx
package ch18;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
//当没有数据可读了之后,就会返回-1
public class a_13_1测试 {
//下面那行的throws FileNotFoundException是12行的快捷键生成的,当然也可以手写
public static void main(String[] args) throws IOException {
//1、创建字节输入流对象
FileInputStream fis = new FileInputStream("java\\src\\ch18_ch19_储物区\\fos.txt");//fos.txt文件要先创建好且有内容
FileInputStream fis2 = new FileInputStream("java\\src\\ch18_ch19_储物区\\fos5.txt");//fos.txt文件要先创建好且有内容
//上面那行的FileInputStream报红线,解决是选中FileInputStream,Alt+Enter,选Add...
//2、调用字节流对象的读数据方法。第一次读取数据,即只读第一个数据
int by = fis.read();
System.out.println(by);//输出的是fos.txt文件的第一个数据对应的ASCII码值,比如这里是a对应的就是97
//如何使读出来的不是ASCII码呢,我们需要输出a,而不是97,如下
System.out.println((char)by);//加一个强制转换就好
System.out.println("-------------");
//2、调用字节流对象的读数据方法。第二次读取数据,即只读第二个数据
by = fis.read();
System.out.println(by);
System.out.println((char)by);
System.out.println("-------------");
//如何读多个数据呢,我们可以使用循环进行优化。当返回值是-1时,就说明数据已经读完了
int byy = fis.read();
while(byy != -1){
System.out.println((char)byy); //如果println改为print就是不换行输出
byy = fis.read();
}
System.out.println("-------------");
//其实上面的读多个数据的代码还可以优化,如下
int dyy;
while((dyy= fis2.read()) != -1){//这一行的写法很重要,实际开发中的写法
System.out.print((char)dyy);//输出不换行
}
/*该优化写法做了3件事,如下
1、fis2.read():读数据、
2、dyy=fis2.read():把读取到的数据赋值给dyy
3、by!=-1:判断读取到的数据是否是-1,如果是-1就说明读取到文件结尾了*/
//3、释放资源
fis.close();
}
}
字节流复制文本文件
案例:复制文本文件 需求:把'D:\huanf\java\src\ch18储物区\fos3.txt'复制到'D:\huanf\java\src\ch18储物区\JavaSE\fos3.txt'
分析: 1、复制文本文件,其实就把文本文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地) 2、读数据用InputStream,但是InputStream是抽象类,所以我们要使用的是FileInputStream 3、写数据用OutputStream,但是OutputStream是抽象类,所以我们要使用的是FileOutputStream
思路: 1、根据数据源创建字节输入流对象 2、根据目的地创建字节输出流对象 3、读写数据,复制文本文件,一次读取或写入一个字节 4、释放资源
字节流复制文本文件的练习
xxxxxxxxxx
package ch18;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//不是在控制台查看,是在对应路径看文件有没有复制过去
public class a_14_1测试 {
//下面那行的throws FileNotFoundException是由12行的创建对象抛出的异常写的
public static void main(String[] args) throws IOException {
//1、根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\fos3.txt");//抛出异常,不细说了
//2、根据目的地创建字节输出流对象
FileOutputStream fos = new FileOutputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\JavaSE\\fos3.txt");
//3、读写数据,复制文本文件,一次读取或写入一个字节
int by;
while((by= fis.read())!=-1){
fos.write(by);
}
//4、释放资源
fos.close();
fis.close();
}
}
字节流读数据_一次读一字节数组
需求:把文件fos.txt中的内容读取出来在控制台输出
使用字节输入流读数据的步骤,如下 1、创建字节输入流对象 2、调用字节输入流对象的读数据方法 3、释放资源
字节流读数据_一次读一字节数组的练习
xxxxxxxxxx
package ch18;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class a_15_1测试 {
public static void main(String[] args) throws IOException {
//1、创建字节输入流对象。报红线就需要抛出异常
FileInputStream fis = new FileInputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\fos.txt");
//2、调用字节输入流对象的读数据方法
//int read (byte[] b) 作用是从该输入流读取最多b.length个字节的数据到一个字节数组
byte[] bys = new byte[6]; //只读前6位的数据
//第一次读取数据
int len = fis.read(bys);
System.out.println(len);
//String (byte[] bytes)
System.out.println(new String(bys));//输出前6位的数据
System.out.println("------------------");
//第二次读取数据
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys));//输出前7-12位的数据
System.out.println("------------------");
System.out.println("------------------");
//注意一下当fos.txt文件里面有换行时,要注意换行实际上读的是2位即\r或2位\n。具体讲解在ch18_储物区\fos.txt有写
//String(byte[] bytes, int offset, int length) 作用是通过平台的默认字符集解码指定的字节子阵列来构造新的String
//优化读取数据。注意这里是第三次读取数据
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys,0,len));//输出a,b。其实读的是a\nb\n
System.out.println("------------------");
System.out.println("------------------");
//如何解决空格、换行问题,如下
byte[] bys2 = new byte[1024];//1024及其整数组
int len2;
while((len2=fis.read(bys2))!=-1){//当等于-1时,就说明文件里面的数据已经读完了
System.out.print(new String(bys2,0,len2));//print的意思是不换行输出
//注意这样是按fos.txt文件的内容输出,如果那里使用了换行,这里控制台就会换行,即1:1原样输出
}
//3、释放资源
fis.close();
}
}
字节流复制图片
需求:把"D:\huanf\java\src\ch18储物区\壁纸3.jpg"复制到"D:\huanf\java\src\ch18储物区\JavaSE"里面
思路: 1、根据数据源创建字节输入流对象 2、根据目的地创建字节输出流对象 3、读写数据,复制图片,一次读取或写入一个字节数组 4、释放资源
字节流复制图片的练习
xxxxxxxxxx
package ch18;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class a_16_1测试 {
public static void main(String[] args) throws IOException {
//1、根据数据源创建字节输入流对象。如果报红线就抛出异常
FileInputStream fis = new FileInputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\壁纸3.jpg");
//2、根据目的地创建字节输出流对象
FileOutputStream fos = new FileOutputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\JavaSE\\壁纸3.jpg");
//3、3、读写数据,复制图片,一次读取或写入一个字节数组
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys)) != -1){
fos.write(bys,0,len);
}
//4、释放资源
fos.close();
fis.close();
}
}