Java IO
IO类
IO本身就是输入输出的意思,IO类就是为了与磁盘进行IO相关操作的工具、桥梁;
IO类基本可以分成字节流和字符流;
而既然是IO,那不管是哪个流都是分为输入和输出两大块
字节流
InputStream(抽象)(字节输入流)
InputStream是所有字节输入流的抽象基类,提供字节输入的通用方法
基本方法:
read() //从文件中读取数据的下一字节
read(byte[]) //从文件中读取一个数组量的字节
read(byte[], int, int) //从文件中读取限定位置数量的字节
注:当读取不到字节时会返回 -1
FileInputStream
该流是父类提供用于实例化的读取文件的输入流,能从指定文件中读取字节,从而读取文件内容
构造方法有两个:
- 需要实例化一个File文件对象
- FileInputStream( File )
- 不用实例化File对象
- FileInputStream( String )
使用方式
- 一个一个字节读取(效率慢)
public static void main(String[] args) throws IOException {
//创建一个字节输入流对象,必须明确数据源
File file = new File("c:\\file.txt");
FileInputStream fis = new FileInputStream(file);
//使用 read()一次读一个字节。
int ch = 0;
while((ch=fis.read())!=-1){
System.out.println("ch="+(char)ch);
}
fis.close();
}
- 一组一组数组读取
public static void main(String[] args) throws IOException {
// 创建一个字节输入流对象,必须明确数据源
File file = new File("c:\\file.txt");
FileInputStream fis = new FileInputStream(file);
// 创建一个字节数组。
byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fis.close();
}
BufferedInputStream(字节缓冲输入流)
这是FilterInputStream的子类,它除了父类功能之外还提供了 “缓冲”、“mark标记”、“重置” 等功能方法
构造方法:
- BufferedInputStream( FileInputStream )
使用方法
FileInputStream fileIn = new FileInputStream("abc.txt");
//1, 把基本的流包装成高效的流
BufferedInputStream in = new BufferedInputStream(fileIn);
//2,读数据
int ch = -1;
while ( (ch = in.read()) != -1 ) {
System.out.print((char)ch);
}
in.close();
OutputStream(抽象)(字节输出流)
OutputStream是所有字节输出流的抽象基类,提供内存字节输出到文件的通用方法
基本方法:
write(int) //将指定字节写入输出流
write(byte[]) //将一定数量字节从数组写入输出流
write(byte[], int, int) //将指定数组指定位置数量写入输出流
注:如果文件不存在,则会创建该文件,如果存在,则覆盖
FileOutputStream
该流是父类提供用于实例化的文件数据输出流,能将内存数据写入磁盘文件上
构造方法有四个:
- 需要实例化一个File文件对象
- FileOutputStream( File )
- FileOutputStream( File ,boolean )
- 不用实例化File对象
- FileOutputStream( String )
- FileOutputStream( String , boolean )
这里boolean代表如果有同名文件,是否在文件内容末位继续添加写入内容(不覆盖)
使用方式
public static void main(String[] args) throws IOException {
//创建存储数据的文件。
File file = new File("c:\\file.txt");
//创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
FileOutputStream fos = new FileOutputStream(file ,true);
String str = "\r\n"+"HelloIO";
//调用父类中的write方法。
fos.write(str.getBytes());
//关闭流资源。
fos.close();
}
BufferedOutputStream(字节缓冲输出流)
这是FilterInputStream的子类,它除了父类功能之外还提供了 “缓冲” 等功能方法
构造方法:
- BufferedOutputStream( FileOutputStream )
使用方法
//创建基本的字节输出流
FileOutputStream fileOut = new FileOutputStream("abc.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedOutputStream out = new BufferedOutputStream(fileOut);
//2,写数据
out.write("hello".getBytes());
//3,关闭流
out.close();
练习
- 使用字节流复制文件
public static void main(String[] args) throws IOException {
File srcFile = new File("c:\\YesDir\test.JPG");
File destFile = new File("copyTest.JPG");
// 明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//定义一个缓冲区。
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
}
fos.close();
fis.close();
}
- 使用缓冲流复制文件(效率更快)
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new FileReader("D:/Plan.txt"));
BufferedWriter ou = new BufferedWriter(new FileWriter("C:/Plan.txt"));
String line = null;
while( ( line = in.readLine() ) != null) {
ou.write(line);
ou.newLine();
}
ou.close();
in.close();
}
字符流
Reader(抽象)(字符输入流)
Reader是所有字符输入流的抽象基类,把输入流中的字符读到内存中
基本方法:
read() //从文件中读取下一字符
read(char[]) //从文件中读取一定数量字符到数组中
注:当读取不到字符会返回 -1
BufferedReader
该流能缓冲各个字符,从而提供字符、数组、字符串的高效读取
构造方法:
- 需要实例化一个File文件对象
- BufferedReader( FileReader )
使用方式
常用特性方法:
- readLine() ——没有则返回 null
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
String line = null;
while( (line = in.readLine()) != null ){
System.out.println(line);
}
in.close();
InputStreamReader(输入转换流)
使用指定编码表,将输入的“字节”转换成“字符”的输入流
使用方法
public static void readC() throws IOException{
//创建读取文件的字节流对象
InputStream in = new FileInputStream("c:\\c.txt");
//创建转换流对象
//这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
//InputStreamReader isr = new InputStreamReader(in);
InputStreamReader isr = new InputStreamReader(in,"utf-8");
//使用转换流去读字节流中的字节
int ch = 0;
while((ch = isr.read())!=-1){
System.out.println((char)ch);
}
isr.close();
}
注意:一旦要指定其他编码时,绝对不能用子类(FileReader),必须用该转换流
其实在FileReader使用的时候:
FileReader fr = new FileReader("a.txt");
这里就使用的是默认编码表
FileReader
这个类就是上面所说的简化而来的子类,能方便快捷地读取文件字符
构造方法:
- 需要实例化一个File文件对象
- FileReader( File )
- 无需手动实例化File文件对象
- FileReader( String )
使用方式
public static void readText() throws IOException {
FileReader fr = new FileReader("E:\\test\\a.txt");
int ch = 0;
while((ch = fr.read())!=-1){
//输出的字符对应的编码值
System.out.println(ch);
//输出字符本身
System.out.println((char)ch);
}
}
Writer(抽象)(字符输出流)
OutputStream是所有字符输出流的抽象基类,提供内存字符输出到文件的通用方法
基本方法:
write( int ) //将单个字符写入输出流
write( char[] ) //将一定数量字符数组写入输出流
write( char[] , int , int ) //将指定数组指定位置数量写入输出流
write( String ) //将字符串写入输出流
write( String , int , int) //将字符串一部分写入输出流
注:如果文件不存在,则会创建该文件,如果存在,则覆盖
BufferedWriter
缓冲各个字符,从而提供字符、数组、字符串的高效读取
构造方法:
- BufferedWriter( FileWriter )
使用方式
常用特性方法:
- readLine() ——没有则返回 null
FileWriter fileOut = new FileWriter("file.txt");
BufferedWriter out = new BufferedWriter(fileOut);
for (int i=0; i<5; i++) {
out.write("hello");
out.newLine();
}
out.close();
OutputStreamWriter(输出转换流)
使用指定编码表,将“字符”转换成“字节”的输出流,再使用字节流写出去
public static void writeC() throws Exception {
//创建与文件关联的字节输出流对象
FileOutputStream fos = new FileOutputStream("c:\\c.txt");
//创建可以把字符转成字节的转换流对象,并指定编码
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//调用转换流,把文字写出去,其实是写到转换流的缓冲区中
osw.write("你好");//写入缓冲区。
osw.close();
}
注:当调用 write 方法时,流会将字符在码表进行查询,转成字节后存到缓冲区中
FileWriter
功能性同FileReader相似,是简化父类操作的字符输出流,方便地将字符写到文件中
构造方法有四个:
- 需要实例化一个File文件对象
- FileWriter( File )
- FileWriter( File ,boolean )
- 无需手动实例化File文件对象
- FileWriter( String )
- FileWriter( String , boolean )
boolean代表是否在文件末位继续添加(不覆盖)
使用方法
public static void main(String[] args) throws IOException {
//演示FileWriter 用于操作文件的便捷类。
FileWriter fw = new FileWriter("E:\\text\\fw.txt");
fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。
fw.flush();//刷新
fw.close();// 关闭之前需要刷新它
}
注意:在写入字符的时候,需要先进行流的刷新,再关闭流
练习
- 使用字符流复制文本文件
public static void copyTextFile() throws IOException {
//1,明确源和目的。
FileReader fr = new FileReader("c:\\a.txt");
FileWriter fw = new FileWriter("c:\\copy.txt");
//2,为了提高效率。自定义缓冲区数组。字符数组。
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
//3,关闭资源。
fw.close();
fr.close();
}
- 使用缓冲流复制文件(效率更快)
public static void main(String[] args) throws IOException {
//1,指定数据源, 是数据源中读数据,采用输入流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,指定目的地,是把数据写入目的地,采用输出流
BufferedWriter out = new BufferedWriter(new FileWriter("copy.txt"));
//3,读数据
String line = null;
while ( (line = in.readLine()) != null ) {
//4,写数据
out.write(line);
//写入换行符号
out.newLine();
}
//5,关闭流
out.close();
in.close();
}
还有一些常用IO
由于想偷懒,就直接总结了
Properties集合
- 表示的是一个持久的属性集
- 属性列表是个键值对
- 每个键及其对应值都是一个String
- 哈希表的子类 与 map集合 中的方法都可以使用
- 键值对可以存储到集合中,也可以存到持久化设备中
基本方法
setProperty( String , String ) //设置键值对到集合中
getProperty( String ) //从键值对中根据指定的键获取值
与流技术相结合的方法:
load( InputStream ) //从输入流中读取属性键值对
load( Reader ) //按行的格式从字符流中读取属性键值对
store( OutputStream , String ) //以字节输出方法格式,将属性键值对写入输出流
store( Writer , String ) //以字符输出方法格式,将属性键值对写入输出流
(第二个参数String是写入文件中附带的注释)
使用方式
将集合中的内容存储到文件中:
public static void main(String[] args) throws IOException {
//1,创建Properties集合
Properties prop = new Properties();
//2,添加元素到集合
prop.setProperty("周迅", "张学友");
prop.setProperty("李小璐", "贾乃亮");
prop.setProperty("杨幂", "刘恺威");
//3,创建流
FileWriter out = new FileWriter("prop.properties");
//4,把集合中的数据存储到流所对应的文件中
prop.store(out, "save data");
//5,关闭流
out.close();
}
将文件中的数据读取到集合中:
public static void main(String[] args) throws IOException {
//1,创建集合
Properties prop = new Properties();
//2,创建流对象
FileInputStream in = new FileInputStream("prop.properties");
//FileReader in = new FileReader("prop.properties");
//3,把流所对应文件中的数据 读取到集合中
prop.load(in);
//4,关闭流
in.close();
//5,显示集合中的数据
System.out.println(prop);
}
反序列化流
- 反序列化的对象必须要提供该对象的字节码文件
- 序列化接口声明的序列UID号不一致会报错
ObjectInputStream(反序列化)
对以前序列化的对象从流中进行读取
构造方法:
- ObjectInputStream( InputStream )
基本方法:
- readObject( ) ——从反序列化流中读取对象
使用方式:
public static void readObj() throws IOException, ClassNotFoundException {
//1,定义流对象关联存储了对象文件
FileInputStream fis = new FileInputStream("tempfile\\obj.object");
//2,建立用于读取对象的功能对象
ObjectInputStream ois = new ObjectInputStream(fis);
Person obj = (Person)ois.readObject();
System.out.println(obj.toString());
}
序列化流
- 这是专门用于操作对象的流,将对象存储到磁盘、网络中
- JavaBean对象都需要做序列化
ObjectOutputStream(序列化)
将对象基本数据类型和图形写入字节输出流
构造方法:
- ObjectOutputStream( OutputStream )
基本方法:
- writerObject( Object ) ——写入指定对象
使用方式:
public static void writeObj() throws IOException {
//1,明确存储对象的文件
FileOutputStream fos = new FileOutputStream("tempfile\\obj.object");
//2,给操作文件对象加入写入对象功能
ObjectOutputStream oos = new ObjectOutputStream(fos);
//3,调用了写入对象的方法
oos.writeObject(new Person("wangcai",20));
//关闭资源
oos.close();
}
打印流
输出信息最方便的类,能打印各种数据值
构造方法:
字节打印流 | 字符打印流 |
---|---|
PrintStream( File ) | PrintWriter( File ) |
PrintStream( OutputStream ) | PrintWriter( OutputStream ) |
PrintStream( OutputStream , boolean ) | PrintWriter( OutputStream , boolean ) |
基本方法:
print( ) //此方法被重载多次,输出任意数据
println( ) //输出任意数据后换行
printf( ) //根据本地环境格式化输出
注:
System.out.println();
//其实等价于
PrintStream ps = new PrintWriter(System.out);
ps.println();
使用方式:
public static void main(String[] args) throws IOException {
//创建流
//PrintWriter out = new PrintWriter("printFile.txt");//无自动刷新
PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"), true);
//2,写数据
for (int i=0; i<5; i++) {
out.println("helloWorld");
}
//3,关闭流
out.close();
}
NIO(管道流)
- 管道流主要由 缓冲区(Buffer) 与 管道(Channel) 两部分组成
- 数据必须先读入缓冲区再进行处理
NIO 与 普通IO的区别:
- NIO面向缓冲;IO面向流
- NIO是非阻塞的;IO是阻塞IO
- NIO有其选择器
使用方式
public static void main(String[] args) throws Exception {
File file = new File("E:\\work\\TestFile\\s.avi");
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream("E:\\work\\TestFile\\ss.avi");
// 用字节流获取文件通道
FileChannel in = fis.getChannel();
FileChannel ot = fos.getChannel();
// 分配一个新的字节缓冲区,内容放在缓冲区里面,不能大也不能小
ByteBuffer allocate = ByteBuffer.allocate((int)file.length());
// 读缓冲区的内容
in.read(allocate);
// 查看指针的位置
System.out.println(allocate.position());
// 把指针设置为0
allocate.flip();
// 写缓冲区的内容到指定的位置
ot.write(allocate);
in.close();
ot.close();
fis.close();
fos.close();
}
随机流
- 该随机访问文件流可以在文件任意地方写入数据和任意地方读取字节
构造方法
- 需要实例化一个File文件对象
- RandomAccessFile( File , String )
- 无需手动实例化File文件对象
- RandomAccessFile( String , String )
第二个String参数是mode,指定打开文件的访问模式
- " r " :只读
- " rw ":读写
- " rws ":数据会立即写入文件,以防异常
- " rwd ":已被write的数据会保存到文件
随机流适合用于分文件复制 和 断点网络下载
使用IO进行网络下载
public static void main(String[] args) throws Exception {
// 目的地
File savefile = new File("F:/fileTest/b.jpg");
String src = "http://tupian.aladd.net/2013/11/738.jpg";
long filelength = 0;
if(savefile.exists()){
filelength = savefile.length();
}
else{
filelength=0;
}
//创建url对象
URL url = new URL(src);
//建立远程连接
URLConnection connection= url.openConnection();
//建立Http请求的连接
HttpURLConnection hc = (HttpURLConnection) connection;
//设置请求消息
hc.setRequestProperty("Range", "bytes="+filelength+"-");
//读
InputStream is= hc.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
//写
FileOutputStream bos = new FileOutputStream(savefile,true);
byte buff[] = new byte[1024*8];
int i ;
while((i=bis.read(buff))!=-1){
bos.write(buff,0,i);
}
bis.close();
bos.close();
}