IO
io介绍
生活中,你肯定经历过这样的场景。当你编辑一个文本文件,忘记了
ctrl+s
,可能文件就白白编辑了。当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为
输入input
和输出output
,即流向内存是输入流,流出内存的输出流。Java中I/O操作主要是指使用
java.io
包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
io分类
根据数据的流向分为:输入流和输出流。
输入流 :把数据从
其他设备
上读取到内存
中的流。输出流 :把数据从
内存
中写出到其他设备
上的流。格局数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。
字符流 :以字符为单位,读写数据的流。
io的顶级父类
名称 | 输入流 | 输出流 |
---|---|---|
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
字节流
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
OutPutStream
OuputStream 是用来将 IDL 类型写入 CDR 编组流的 Java API
java.io.OutputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
方法名 | 说明 |
---|---|
public abstract void write(int b) | 将指定的字节输出流。 |
public void write(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流。 |
public void write(byte[] b, int off, int len) | 从指定的字节数组写入 len字节,从偏移量 off开始输 |
public void close() | 关闭此输出流并释放与此流相关联的任何系统资源。 |
public void flush() | 刷新此输出流并强制任何缓冲的输出字节被写出。 |
注意事项:close方法,在完成流的操作室,必须调用此方法,释放系统资源
FileOutputStream类
public class FileOutputStream extends OutputStream
文件输出流是用于将数据写入
File
或FileDescriptor
的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。
构造方法
方法名 | 说明 |
---|---|
public FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
public FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件。 |
注意事项:当你创建一个对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建文件。如果有这个文件,会清空这个文件的数据
构造方法的使用
public class FileInputStreamDemo01 {
public static void main(String[] args) throws IOException {
/**
* FileInputStream(File file)
* 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
* FileInputStream(String name)
* 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
*/
//FileInputStream(File file)
// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream fis = new FileInputStream(new File("day150429\\a"));
int read = fis.read();
System.out.println(read);
//FileInputStream(String name)
// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream fis1 = new FileInputStream("day150429\\a");
int read1 = fis1.read();
System.out.println(read1);
}
}
public class FileInputStreamDemo03 {
public static void main(String[] args) throws IOException {
/*
读取数据使用的方法是int read()
什么时候能读完数据不知道,反正就是一直读
while()
文件的数据总有读取完的时候,什么时候结束呢,结束标记就是-1
读取一个数据的时候,使用 int i !=-1 不等于-1 说明有数据 反之则没有数据说明读完了
int i;
while((i = fis.read()) != -1)
*/
FileInputStream fis = new FileInputStream(new File("day150429\\a.txt"));
int i;
while ((i = fis.read()) != -1){
//输出的是字符对应的ASCII码值
System.out.println(i);
//输出字符
System.out.println((char)i);
}
//释放资源
fis.close();
}
}
读取字节数组
public class FileInputStreamDemo04 {
public static void main(String[] args) throws IOException {
/**
*
*一次读取一个字节数组
* 再使用FileOutputStream流的时候,可以一次写一个字节数组,当然再读的时候也可以一次读取一个字节数组
* int read ( byte[] b)
*
*我读取一个字节数据,存储到字节数组中即可,最后读取完将这个字节数组转换成一个字符串
*
*/
FileInputStream fis = new FileInputStream(new File("day150429\\a.txt"));
//定义数组
byte[] bytes = new byte[1024];
/*
int len: 记录了真实有效的字节的个数
fis.read(bys): 读取一个字节数据存储到字节数组中
len = fis.read(bys) : 将读取到的个数赋值给len变量
(len = fis.read(bys)) != -1 : 判断是否是到达数据末尾
*/
int len;
while ((len=fis.read(bytes)) != -1){
System.out.println(len);
//将字节数组转换成字符传
System.out.println(new String(bytes,0,len));
}
fis.close();
}
}
数据追加续写
方法名 | 说明 |
---|---|
public FileOutputStream(File file,boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
public FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件。 |
这两个构造方法,参数中都需要传入一个boolean类型的值,
true
表示追加数据,false
表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt",true);
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
fos.write(b);
// 关闭资源
fos.close();
}
}
写出换行
如果写的数据比较多,那么就会在文件中在一行展示。会造成阅读不方便。我们现在的需求是,每写一次数据,都要从下行开始,这个时候就要涉及到换行的问题。
回车符
\r
和换行符\n
:
回车符:回到一行的开头(return)。
换行符:下一行(newline)。
系统中的换行:
Windows系统里,每行结尾是
回车+换行
,即\r\n
;Unix系统里,每行结尾只有
换行
,即\n
;Mac系统里,每行结尾是
回车
,即\r
。从 Mac OS X开始与Linux统一。
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 定义字节数组
byte[] words = {97,98,99,100,101};
// 遍历数组
for (int i = 0; i < words.length; i++) {
// 写出一个字节
fos.write(words[i]);
// 写出一个换行, 换行符号转成数组写出
fos.write("\r\n".getBytes());
}
// 关闭资源
fos.close();
}
}
FileInputStream类
FileInputStream
从文件系统中的某个文件中获得输入字节。
构造方法
方法名 | 说明 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 |
注意:当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出
FileNotFoundException
构造方法的使用
//FileInputStream(File file)
// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream fis = new FileInputStream(new File("day150429\\a"));
int read = fis.read();
System.out.println(read);
//FileInputStream(String name)
// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream fis1 = new FileInputStream("day150429\\a");
int read1 = fis1.read();
System.out.println(read1);
读取字节数据
一次读取一个字节
public class FileInputStreamDemo03 {
public static void main(String[] args) throws IOException {
/*
读取数据使用的方法是int read()
什么时候能读完数据不知道,反正就是一直读
while()
文件的数据总有读取完的时候,什么时候结束呢,结束标记就是-1
读取一个数据的时候,使用 int i !=-1 不等于-1 说明有数据 反之则没有数据说明读完了
int i;
while((i = fis.read()) != -1)
*/
FileInputStream fis = new FileInputStream(new File("day150429\\a.txt"));
int i;
while ((i = fis.read()) != -1){
//输出的是字符对应的ASCII码值
System.out.println(i);
//输出字符
System.out.println((char)i);
}
//释放资源
fis.close();
}
}
读取数组字节
一次读取一个数组数据,大小为1024
public class FileInputStreamDemo04 {
public static void main(String[] args) throws IOException {
/**
*
*一次读取一个字节数组
* 再使用FileOutputStream流的时候,可以一次写一个字节数组,当然再读的时候也可以一次读取一个字节数组
* int read ( byte[] b)
*
*我读取一个字节数据,存储到字节数组中即可,最后读取完将这个字节数组转换成一个字符串
*
*/
FileInputStream fis = new FileInputStream(new File("day150429\\a.txt"));
//定义数组
byte[] bytes = new byte[1024];
/*
int len: 记录了真实有效的字节的个数
fis.read(bys): 读取一个字节数据存储到字节数组中
len = fis.read(bys) : 将读取到的个数赋值给len变量
(len = fis.read(bys)) != -1 : 判断是否是到达数据末尾
*/
int len;
while ((len=fis.read(bytes)) != -1){
System.out.println(len);
//将字节数组转换成字符传
System.out.println(new String(bytes,0,len));
}
fis.close();
}
}
字节输入流和输出流综合练习(图片复制)
public class FileInputStreamCopyToFileOutPutStreamTest {
public static void main(String[] args) throws IOException {
/**
* 完成一个文件的复制
* 经常的操作ctrl + c ctrl + v 简称vc大法
*
* 确定要复制的是那一个文件: 数据源
* 确定把该复制到那个地方: 目的地
*
* 数据源: day11_io下的1.jpg
* 目的地: day11_io下的copy1.jpg
*
* 如何复制:使用io流进行完成,jpg是图片,像这种的数据使用的流都字节流
* FileInputStream
* new FileInputStream(new File(day11_io下\\1.jpg))
* 读取文件时,一定要读取已存在的文件,否则报文件找不到异常
* FileNotFoundException
*
* FileOutputStream
* new FileOutputStream(new File(day11_io下\\copy1.jpg))
* 写数据时,指定的文件不存在也没关系,有自动创建的功能
*
* 如何读取和写数据:
* 1. 一次读取一个字节 一次写一个字节
* int len;
* fis.read() !=-1
*
* fos.write(len);
*
* 2. 一次读取一个字节数组 一次写一个字节数组
* byte[]
* int len;
*
* fos.write(byte[] , off, len)
*/
FileInputStream fis = new FileInputStream("day150429\\1.jpg");
FileOutputStream fos = new FileOutputStream("day150429\\1To2.jpg");
//copy(fis, fos);
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}
private static void copy(FileInputStream fis, FileOutputStream fos) throws IOException {
int len;
while ((len = fis.read()) != -1){
fos.write(len);
}
fos.close();
fis.close();
}
}