初学IO流:
首先,读与写的参照对象是程序,也可以是内存。
接着就是流的方向,IO流中,输入流(读取),输出流(写出)。ps:input输入,output输出
输入流的作用为:读取本地文件的数据。
输出流的作用为:把数据写到本地文件当中。
其中,流又分为字节流和字符流,字节流可以操作所有类型的文件,而字符流只能操作纯文本文件(Windows自带的记事本打开能读懂的文件,如txt文件、md文件)。
那么什么是IO流呢? 其实是存储和读取数据的解决方案,I是input,O是outpu,流就是像水流一样传输数据。
那IO流的作用是什么? 可以用于读取数据(如本地、网络)
IO流按照流向可以分为哪两种流? 输出流(程序-->文件)和输入流(文件-->程序)
注:我们可以想象Idea或者ecplise就是程序。
接下来我们介绍IO流体系,首先是字节流:
在字节流中有这么两个关键字,InputStream(字节输入流,负责读取数据),OutputStream(字节输出流,负责写出数据)。
其次是字符流:
同样是两个关键字,Reader(字符输入流,负责读取数据),Writer(字符输出流,负责写出数据)。
注意:InputStream,OutputStream,Reader,Writer都是抽象类不能直接创建对象,还得看子类。
接下来我们介绍它们的子类,首先是FileInputSteam,它是InputStream的子类(容易辨认,后面不再接受各自是谁的子类),它可以操作本地文件的字节输入流,可以把程序中的数据写到本地文件中,然后是FileOutputSteam,它可以操作本地文件的字节输出流。
下面演示字节输出流FileOutputSteam:
public class ByteStreamDemo1 {
public static void main(String[] args) throws IOException {
//1.创建对象
FileOutputStream fos = new FileOutputStream("D:\\IdeaFile\\MyIO\\AnLi.txt");//FileOutputStream("文件路径")
//2.写出数据
fos.write(97);
//3.释放资源
fos.close();
}
}
注:AnLi.txt在程序执行之前需要准备好
运行结果:
另外补充一些字节输出流的细节:
在创建字节输出流对象中:
细节1:参数是字符串表示的路径或者是File对象都是可以的
细节2:如果文件不存在时会创建一个新的文件,但是要保证父级路径是对的
细节3:如果文件已经存在,则会清空文件
下面来演示这些细节:
FileOutputStream fos = new FileOutputStream("可以直接放文件路径(文件已经存在),也可以是File对象(可以创建新的文件,但是父级路径一定要存在)");
比如当我们运行这一句代码时:
FileOutputStream fos = new FileOutputStream(new File("D:\\IdeaFile\\MyIO\\AnLi2.txt"));
原本没有AnLi2.txt的文件夹中,出现了AnLi2.txt文件。
并且把数据也写进去了。
现在在原本的基础上演示细节3:
我们把刚刚AnLi2.txt里面的内容改成“123456789”
当我们再次运行时,因为在相同的路径下存在同样的文件,那么则会清空文件,“123456789”也就会重新变成“a”
接下来,在写数据中:
细节:write方法的参数是整数,但实际上写到本地文件中的是整数在ASCII上对应的字符。
这个其实很明显,因为我们运行的时候,写入的数据是97,但是在文件中却是a。那么如果我们只想输出97这个数字怎么办?我们可以采取字符的形式输出,也就是'9','7'。
fos.write('9');
fos.write('7');
最后在释放资源:
它的作用其实很简单,就是解除了资源的占用。
接下来我们介绍FileOutputSteam写数据的3种方式。
1.void write(int b) 一次写一个字节数据
2.void write(byte[] b) 一次写一个字节数组数据
3.void write(byte[] b , int off , int len) 一次写一个字节数组的部分数据
这里不再介绍第1种方式,我们来介绍第2种,在使用第2种方法时,我们需要先创建一个数组,再把这个数组写入本地文件中。
byte[] bytes = {97,98,99,100,101};
fos.write(bytes);//一次写一个字节数组的数据
下面介绍第3种,在第3种方法中,存在三种参数,第一个参数就是存放数据的数组,第二个参数叫做起始索引,第三个参数表示个数。下面举个例子,我们让第二个参数等于0,第三个参数等于3,也就是让数据从位置0开始写,一共写3个数据。
那么我们来运行下面这段代码:
byte[] bytes = {97,98,99,100,101};
fos.write(bytes,1,2);//一次写一个字节数组的部分数据
这段代码中,第二参数为1,第三参数为2,也就是说,从数组bytes中位置为1的数据开始(也就是98), 写两个参数。那么理论上来说应该在本地文件中写下”bc“,我们来看一下实际结果:
结果无误。
最后我们来介绍以下换行和续写:
在正式开始之前,我们先介绍一个方法:getBytes()
getBytes() 是Java编程语言中将一个字符串转化为一个字节数组byte[]的方法。String的getBytes()方法是得到一个系统默认的编码格式的字节数组。
将一个String类型的字符串中包含的字符转换成byte类型并且存入一个byte[]数组中。在java中的所有数据底层都是字节,字节数据可以存入到byte数组。
好,接下来我们通过以下代码先在本地文件中写入数据:
public class ByteStreamDemo4 {
public static void main(String[] args) throws Exception{
//1.创建对象
FileOutputStream fos = new FileOutputStream("D:\\IdeaFile\\MyIO\\AnLi.txt");
//2.写出数据
String str = "abcdefghyjkomn";
byte[] arr = str.getBytes();
System.out.println(Arrays.toString(arr));//演示以下getBytes()的作用
fos.write(arr);
//3.释放资源
fos.close();
}
}
另外,这是getBytes()的运行结果:
接下来,我们想在已有的数据的基础上,先换行,再写入新的数据,那么我们需要先写好另外一个写入的方法,再在两者之间,写出一个换行符就可以了。
注意:windows系统的换行符为:\r\n,如果是linux系统则是:\n,另外Mac系统的换行符为:\r
但是,由于在Windows操作系统中,Java对回车换行进行了优化,虽然完整的是\r\n,但是我们写其中一个\r或者\n,Java也可以实现,因为Java会在底层补全,不过我们依旧建议写全,不要省略。
接下来我们补全这段代码:
public class ByteStreamDemo4 {
public static void main(String[] args) throws Exception{
//1.创建对象
FileOutputStream fos = new FileOutputStream("D:\\IdeaFile\\MyIO\\AnLi.txt");
//2.写出数据
String str1 = "abcdefghyjkomn";
byte[] arr1 = str1.getBytes();
fos.write(arr1);
String wrap = "\r\n";//换行
byte[] wraps = wrap.getBytes();
fos.write(wraps);
String str2 = "pqsyzuvwswz";
byte[] arr2 = str2.getBytes();
fos.write(arr2);
//3.释放资源
fos.close();
}
}
运行结果:
已经换行写出了。
接下来我们介绍一下续写,在我们的FileOutputStream()当中,我们已经知道了在括号里面放的是本地文件的路径,或者直接放File对象也是可以的,其实在FileOutputStream()当中还有另外一个参数,我们称之为续写开关。
那么如果我们想要续写,则只需要打开续写开关即可(在第二个参数位置输入true即为打开):
FileOutputStream fos = new FileOutputStream("文件路径",true);
当我们打开续写开关时,原本的本地文件就不会被清空,于是就会出现这种情况:
那么我们也就实现了续写。