java io
i:input输入,把硬盘数据读取到内存当中使用
o:output输出:把内存中的数据写道硬盘中保存
io流分为字节流和字符流
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流 InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
字节流
一切文件数据(文本,图片,视频)在存储时,都是以二进制数字的形式保存,都是一个一个的字节,那么传输时一样如此。所以字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的对象,底层传输的始终为二进制数据
字节输出
OutputStream,此抽象类是表示输出字节流的所有类的超类,是个抽象类
有四个方法
close()关闭此输出流并释放与此流相关联的任何系统资源
flush()刷新此输出流并强制任何缓冲的输出字节与被写入
write(byte[]b)将b.length字节从指定的字节数组写入此输出流
write(byte[] b,int off,int len)从指定的字节数组写入len字节从偏移量off开始输出到此输出流
write(int b)将指定的字节流输出(这是个抽象方法)
OutputStream
直接子类
ByteArrayOutputStream:往字节数组写数据的字节输出流
FileOutputStream:往文件中写数据的字节输出流
FilterOutputStream:带过滤器的字节输出流
ObjectOutputStream:用来写对象的字节输出流
OutputStream:其他包中的类
PipedOutputStream:管道流
FileOutputStream
该类也叫做文件字节输出流
作用:把内存中的数据写入到硬盘的文件中
构造方法
FilleOutpuStream(String name);创建一个向具有指定名称中写入数据的输出文件流
FileOutputStream(File file)创建一个指定File对象表示的文件中写入数据的文件输出流
参数
String name:目的地是一个文件的路径
File file:目的地是一个文件
构造方法作用
1.创建一个FileOutputStream对象
2.根据构造方法中传递的文件/文件路径,创建一个空文件
3.会把FileOutputStream对象指向创建好的文件
写入数据的原理
java程序->jvm->操作系统->os调用写数据的方法->把数据写入到文件中
1.步骤:创建FileOutputStream
2.调用FileOutputStream对象中的方法write,把数据写入到文件中
3.释放资源(流会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
public void write(int b)
package com.company;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
//继续抛异常
public static void main(String[] args) throws IOException {
//创建一个FileOutputStream对象,构造方法传递写书数据的目的地,会抛出文件找不到异常异常,是IO异常的子类
FileOutputStream fos = new FileOutputStream(".\\a.txt");
//将指定的字节输出流,会抛出io异常
//写数据的时候,会把10进制的帧数转换成二进制的整数
fos.write(97);
//释放资源
fos.close();
}
}
任意的文本编辑器(记事本,notepad++。。。)
在打开文件的时候,都会查询编码表,把字节转换为字符表示
0-127:查询ASCII表
其他值:查询系统默认码表(中文系统GBK)
public void write(byte[] b)
将b.length字节从指定的字节数组中写入此输出流
一次写多个字节:如果写的第一个字节是正数(0-127),那么现实的时候会查询ASCII表
如果写的第一个字节是负数,那第一个字节回合第二个字节组成一个中文显示,查询系统默认码表(GBK)
package com.company;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
//继续抛异常
public static void main(String[] args) throws IOException {
//创建一个FileOutputStream对象构造方法写入要绑定的数据的目的地
FileOutputStream fos = new FileOutputStream(new File(".\\a.txt"));
//调用FileOutputStream对象的方法write,把数据写到文件中
// byte[] bytes={65,66,67,68,69};//ABCDE
byte[] bytes={-65,66,-67,68,69};//前俩个是中文
fos.write(bytes);
fos.close();
}
}
public void write(byte[]b ,int iff,int len)
把字节数组的一部分写入到文件中
从指定的字节数组写入len字节从偏移量off开始输出到此输出流
特性
package com.company;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
//继续抛异常
public static void main(String[] args) throws IOException {
//创建一个FileOutputStream对象构造方法写入要绑定的数据的目的地
FileOutputStream fos = new FileOutputStream(new File(".\\a.txt"));
//将字符串转换为字节流
//[-28, -67, -96, -27, -91, -67]
//idea右下角查看默认编码方式,utf-8中三个字节是一个中文,jbk中俩个是一个中文
byte[]bytes2="你好".getBytes();
fos.write(bytes2);//运行结束打开a.txt显示你好
fos.close();
}
}
每次写入的时候都会创建新文件
追加续写
FileOutputStream(String name,boolean append)创建一个向具有指定name的文件中写入数据的输出文件流
FileOutputStram(File file,boolean append)创建一个向指定File对象表示的文件中写入数据文件输出流
参数
String name,File file写入数据的目的地
boolean append追加写开关
true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据
false;创建新文件
InputStream
java.io.InputStream 此抽象类是字节输入流的所有类的超类,以下是方法
int available()返回输入流下一个方法调用可以不受阻塞从此流读取(或跳过)的估计字节数
void close()关闭此输入流,并释放与该流关联的所有资源
void mark(int readlimit)在此输入流中标记当前的位置
boolean marksupported()测试此输入流是否支持mark和reset方法
abstrack int read()从输入流中读取数据的下一个字节
int read(byte[]b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
int read(byte[] b,int off,int len)将输入流最多len个数据字节写入读取byte数组
void reset()将此流重新定位到最后一次对输入流调用mark方法时的设置
long skip(long n)跳过和丢弃输入流中数据的n个字节
直接子类
AudioInputStream:读取音频
byteArrayInputStream:读取字节数组
FileInputStream:读取文件的
FiilterInputStream:带过滤器的
ObjectInputStream:读取对象的
PipedInputStream:管道流
SequenceInputStream:队列
StringBufferInputStream:字符串缓冲区
FileInputStream
java.ioFileInputstream extends Input InputStream
作用:把硬盘中文件的数据,读取到内存中使用
构造方法
FileInputStream(File file):通过打开一个实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定
FileInputStream(FileDescriptor fdObj)通过使用文件描述创建一个FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接
FileInputStream(String name)通过打开一个世纪文件的连接来创建一个FileInputStream,改文件通过文件系统中的路径名name指定
一次读取一个字节
package com.company;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
//文件为abc
public static void main(String[] args) throws IOException {
//1创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis=new FileInputStream(".\\a.txt");
//2使用FileInputStream对象的方法read读取文件
//intRead()读取文件中的一个字节并返回,读取到文件的末尾返回-1
int len=fis.read();
System.out.println(len);//97 a
len=fis.read();
System.out.println(len);//98 b
len=fis.read();
System.out.println(len);//99 c
len=fis.read();
System.out.println(len);//-1 读取完毕之后怎么读取都是-1
//释放资源
fis.close();
}
}
以上会发现许多代码都一样,因此可以使用循环优化,用while循环,读取到-1的时候结束
package com.company;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
//文件为abc
public static void main(String[] args) throws IOException {
//1创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis=new FileInputStream(".\\a.txt");
//2使用FileInputStream对象的方法read读取文件
int len=0;//
while ((len=fis.read())!=-1){//把读取到的字节赋值给变量hen之后去和-1做笔记
System.out.println(len);
}
//释放资源
fis.close();
}
}
字节输入流一次读取多个字节的方法
int read(byte[] b)从输入流中读取一定数量的字节,并将其粗存在缓冲区数组b中
原理
new FileInputStream的时候,会创建一个对象,指向文件的第一个字节
使用read方法的时候,jvm会让操作系统读取数据,读完之后指针向后移动一位,来读取下一个数据,数据最后会有个结束标记
一次读取多个字节
package com.company;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class Main {
/*
*String类有构造方法
* String(byte[]bytes)把字节数组转换为字符串
* String(byte[] bytes,int offset,int length)把字节数组的一部分转换为字符串 offset数组开始的索引,length转换的字节数
*/
//文件为ABCDE
public static void main(String[] args) throws IOException {
//创建fileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream(".\\a.txt");
//使用FileInputStream对象中的方法read读取文件
byte[] bytes=new byte[2];//new一个byte类型的数组[0,0]
int len = fis.read(bytes);
System.out.println(len);//每次读取的字节个数 2
//System.out.println(Arrays.toString(bytes));//65 66
System.out.println(new String(bytes));//AB
len = fis.read(bytes);
System.out.println(len);//2
System.out.println(new String(bytes));//CD
len = fis.read(bytes);
System.out.println(len);//-1
System.out.println(new String(bytes));//ED
len = fis.read(bytes);
System.out.println(len);//-1
System.out.println(new String(bytes));//ED
//释放资源
}
}
以上读取也可以使用循环优化
while循环的条件读取到-1结束
package com.company;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class Main {
/*
*String类有构造方法
* String(byte[]bytes)把字节数组转换为字符串
* String(byte[] bytes,int offset,int length)把字节数组的一部分转换为字符串 offset数组开始的索引,length转换的字节数
*/
//文件为ABCDE
public static void main(String[] args) throws IOException {
//创建fileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream(".\\a.txt");
//使用FileInputStream对象中的方法read读取文件
byte[] bytes=new byte[1024];//存储读取到的多个字节
int len = 0;//记录每次读取的有效字节个数
while ((len=fis.read(bytes))!=-1){
//System.out.println(new String(bytes));//直接这样使用会出现一堆的空格,因为默认的方法是0
//使用另一个构造方法来转,只转换有效的个数
System.out.println(new String(bytes,0,len));
}
//释放资源
}
}
原理
第一次读取,会读取AB,把数组写满为止,
len指的是读取的有效字节个数
数组:缓冲作用,存储到的多个字节,提高了读取的效率
数组的长度一般定义为1024(1kb)或者1024的整数倍数
方法的返回值为读取的有效字符数
文件复制
package com.company;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
//创建字节流输入对象,构造方法中绑定要读取的数据源
FileInputStream fis=new FileInputStream(".\\1.png");
//创建一个字节数出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos =new FileOutputStream(".\\2.png");
//读取一个字节写入一个字节的方式,(执行循环次数多,比较慢)
//3使用字节流对象中的方法读取read读取文件
// int len=0;
// while((len=fis.read())!=-1){
// fos.write(len);
// }
//使用数组缓冲读取多个字节,写入多个字节
byte[]bytes=new byte[1024];
int len=0;
while ((len=fis.read(bytes))!=-1){
//使用字节输出流的方法write,把读取到的字节写入到目的文件中
fos.write(bytes,0,len);
}
//释放资源(先关闭写的后关闭读的)
fos.close();
fis.close();
}
}