IO流:
IO流分为两大类:字节流和字符流
IO的作用就是为了读写操作的。
每种流都分为输入流(Input)、输出流(Output);站在java程序的角度来说,java程序进行读取操作时,就是输入流;如果java程序向其他地方(硬盘,其他的设备)写入操作时,就是输出流。
IO流只能操作文件,不能操作文件夹,否则会报错。
字节流:
字节输入流:InputStream
字节输出流:OutputStream
OutputStream:
可以向文件中写入字节,进行写入常用的是OutputStream的子类:FileOutputStream,常用的写入方法是write(byte[]),传入byte数组。
下面将是演示利用FileOutputStream来进行写入文件:

package com.xiaoshitou_io;import java.io.FileOutputStream;import java.io.IOException;public class Test { /**
* 使用FileOutputStream来写入文件
* @throws IOException
*
*/
public static void main(String[] args) throws IOException { // 创建FileOutputStream对象 // write.txt 文件在项目的根目录下面
FileOutputStream fos = new FileOutputStream("write.txt"); // 准备byte数组
byte[] b = "Hello every body!".getBytes();
// 写入整个数组
fos.write(b); // 写入换行符,System.lineSeparator()方法返回一个字符串,表示跨平台的换行符
fos.write(System.lineSeparator().getBytes()); // 写入数组的一部分
fos.write(b, 0, 5);// 应该写入的是Hello
// 关闭输出流
fos.close(); // 文件的内容为:
/*
Hello every body!
Hello */
}
}

如果写入的文件存在,会被覆盖掉;要想在文件的末尾进行追加内容(保留以前的内容),就需要在创建FileOutputStream对象是,向构造器传入一个true;下面演示向文件中追加内容:

package com.xiaoshitou_io;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;public class Test { /**
* 使用FileOutputStream来写入文件
* 直接在Write.txt文件追加内容
* @throws IOException
*
*/
public static void main(String[] args) throws IOException { // 创建FileOutputStream对象 // write.txt 文件在项目的根目录下面
File writeFile = new File("write.txt"); // 在创建对象传入一个true
FileOutputStream fos = new FileOutputStream(writeFile, true); // 准备byte数组
byte[] b = (System.lineSeparator()+"我是追加的内容,哈哈").getBytes(); // 写入文件
fos.write(b);
// 关闭输出流
fos.close(); // 文件的内容为:
/*
Hello every body!
Hello
我是追加的内容,哈哈 */
}
}

InputStream:
进行文件的读取经常使用的是InputStream的子类,FileInputStream可以读取任何文件,经常用的方法就是直接读入一个byte数组,这样是为了提高读取效率,不是用一个一个字节的读取。
下面演示一个文件的复制,文件的复制,就是利用字节输入流读取文件,然后利用输出流写入文件。下面是复制一个视频文件(同时用了输入流和输出流):

package com.xiaoshitou_io;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Test { /**
* 将C:\Users\Beck\Desktop\temp目录下all.avi文件复制到
* 当前文件中,名字为copy.avi */
public static void main(String[] args){ // 创建输入输出流
FileInputStream fis = null;
FileOutputStream fos = null; try{
File file = new File("C:/Users/Beck/Desktop/temp");
fis = new FileInputStream(new File(file, "all.avi"));
fos = new FileOutputStream(new File(file, "copy.avi")); // 进行读写操作
int len = -1; // 每次读入1M
byte[] b = new byte[1024*1024]; while ((len=fis.read(b)) != -1){ // 写入
fos.write(b, 0, len);
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("文件复制失败!");
}finally{ // 关闭流对象
try{ if (fos != null){
fos.close();
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("释放资源失败!");
}finally{ try{ if (fis != null){
fis.close();
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("释放资源失败!");
}
}
}
System.out.println("复制文件完毕!"); // 输出结果:
/*复制文件完毕!*/
}
}

BufferedInputStream&BufferedOutputStream:
字符缓冲输入流和字符缓冲输出流,这两个流的作用的是提高输入输出的效率。BufferedInputStream&BufferedOutputStream,接收的参数分别是InputStream,OutputStream,底层还是利用字节的输入输出流,只是对输入输出流进行了封装。
下面利用BufferedInputStream&BufferedOutputStream进行文件的复制:

package com.xiaoshitou_io;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Test { /**
* 将C:\Users\Beck\Desktop\temp目录下all.avi文件复制到
* 当前文件中,名字为copy.avi
* 这次使用的是BufferedInputStream 和 BufferedOutputStream来完成 */
public static void main(String[] args){ // 创建缓冲输入输出流
BufferedInputStream bis = null;
BufferedOutputStream bos = null; try{
File file = new File("C:/Users/Beck/Desktop/temp");
bis = new BufferedInputStream(new FileInputStream(new File(file, "all.avi")));
bos = new BufferedOutputStream(new FileOutputStream(new File(file, "copy.avi"))); // 进行读写操作
int len = -1; // 每次读入1M
byte[] b = new byte[1024*1024]; while ((len=bis.read(b)) != -1){ // 写入
bos.write(b, 0, len);
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("文件复制失败!");
}finally{ // 关闭流对象
try{ if (bos != null){
bos.close();
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("释放资源失败!");
}finally{ try{ if (bis != null){
bis.close();
}
}catch (IOException e){
e.printStackTrace(); throw new RuntimeException("释放资源失败!");
}
}
}
System.out.println("复制文件完毕!"); // 输出结果:
/*复制文件完毕!*/
}
}

练习:把一个视频文件按照5M的大小切割成多个。

package com.xiaoshitou_io;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Test { /**
* 将C:\Users\Beck\Desktop\temp目录下all.avi文件复制到
* 这次是把all.avi视频文件切割成多个文件。按照每个文件5M的大小切割
* @throws IOException
*/
public static void main(String[] args) throws IOException{ // 这次我把IOException直接抛出去了没有捕获
BufferedInputStream bis = new BufferedInputStream( new FileInputStream("C:/Users/Beck/Desktop/temp/all.avi")); // 读取视频文件
int len = -1; // 每次读入5M
byte[] bytes = new byte[1024*1024*5]; int flag = 0; while ((len=bis.read(bytes)) != -1 ){
flag++; // 把读入的文件写入到一个文件中
writeToFile(bytes, len, flag);
} // 关闭输入流
bis.close();
System.out.println("切割完成!");
} // 将一个byte数组的内容写入到一个文件中
private static void writeToFile(byte[] bytes, int len, int flag) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("C:/Users/Beck/Desktop/temp/copy_"+flag+".avi"));
bos.write(bytes, 0, len);
bos.close();
}
}

切割结果:

字符流:
输出流:Writer
输入流:Reader
字符流的底层是字节流+编码表
字符流只能操作文本文件,进行文本文件的读写,如果是为了复制文件的话,最好选择字节流进行复制。
Writer:
Writer下面有两个常用的字符输出流:OutputStreamWriter和FileWriter
OutputStreamWriter:接收的参数是一个OutputStream参数,也可以传一个charset编码字符串,这样就可以按照你设置的编码写入文本文件中。
以utf-8编码形式向文本文件中写入内容:

package com.xiaoshitou_io;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;public class Test { /*
* 以utf8的格式向文件中写入字符串 */
public static void main(String[] args) throws IOException{ // 创建 OutputStreamWriter对象
OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream("wirter.txt"),"utf-8");
osw.write("我是OutputStreamWriter写入的,");
osw.write("我的编码是UTF-8格式的。"); // 字符流需要自己刷新
osw.flush(); // 关闭流
osw.close(); //输出结果,两句话在一行,因为没有写入换行符
/*
我是OutputStreamWriter写入的,我的编码是UTF-8格式的。 */
}
}

FileWriter:可以接收的参数可以是File对象或者是String类型的;它的编码是系统默认的编码,我们的一般编码是使用的是GBK编码。
使用FileWriter向文本文件中写入字符串:

package com.xiaoshitou_io;import java.io.FileWriter;import java.io.IOException;public class Test { /*
* 用FileWriter向文件中写入内容 */
public static void main(String[] args) throws IOException{ // 创建 FileWriter对象
FileWriter fw = new FileWriter("writer_gbk.txt");
fw.write("我是用FileWriter写的"); // 写入换行符
fw.write(System.lineSeparator());
fw.write("我的编码是用的是默认的,GBK");
fw.flush();
// 关闭流
fw.close(); // 输出结果
/*
我是用FileWriter写的
我的编码是用的是默认的,GBK */
}
}

Reader:
Reader下面有两个常用的字符流:InputStreamReader,FileReader
InputStreamReader:可以按照指定的编码去读取文本文件,接收的参数是InputStream和一个编码字符串。
以utf-8的编码去读取一个文本文件:

package com.xiaoshitou_io;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;public class Test { /*
* 以UTF-8去读取writer.txt
* 这个文件是刚才用utf-8的格式写入的,
* 也只能以utf8的格式去读取,否则会出现乱码 */
public static void main(String[] args) throws IOException{ // 创建InputStreamReader对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("wirter.txt"), "utf-8");
int len = -1; // 一次可以读取1024个字符,2*1024个字节,2KB
char[] ch = new char[1024]; while ((len=isr.read(ch)) != -1){
System.out.print(new String(ch, 0, len));
} // 关闭流
isr.close(); // 输出结果:
/*
我是OutputStreamWriter写入的,我的编码是UTF-8格式的。 */
}
}

FileReader:以系统默认的编码去读取一个文本文件。接收的参数可以是一个File或者String。
用FileReader去读取GBK的文件,系统默认的编码是GBK

package com.xiaoshitou_io;import java.io.File;import java.io.FileReader;import java.io.IOException;public class Test { /*
* 用FileReader来读取文件writer_gbk.txt
* FileReader默认是用的是系统的默认编码
* 本机的默认编码是GBK */
public static void main(String[] args) throws IOException{ // 创建FileReader对象
FileReader fr = new FileReader(new File("writer_gbk.txt"));
int len = -1; char[] ch = new char[1024]; while ((len=fr.read(ch)) != -1){
System.out.println(new String(ch,0,len));
}
// 关闭流
fr.close(); // 输出结果
/*
我是用FileWriter写的
我的编码是用的是默认的,GBK */
}
}

乱码:
乱码产生的原因:用一个A编码表将字符转成字节, 又用B编码表将字节转回字符. 两个编码表对应的关系不同,因此查到的结果就不同.
保证不乱码的方式 : 编码与解码保持相同.
字符流复制文件原理:

BufferedReader&BufferedWriter:
BufferedReader&BufferedWriter:字符缓冲输入输出流,接收的参数分别是:Reader,Writer;作用是提高读写的速度,读写时字符的编码是系统默认的编码:
BufferedReader特有的一个方式读取一行readLine(),不会读取换行符
BufferedWrter特有的一个方法时,newLine()写入一个换行符
在写入的数据之后,需要手动flush。
利用BufferedReader&BufferedWriter进行文本文件的读写:

package com.xiaoshitou_io;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Test { /*
* 利用BufferedReader&BufferedWriter进行文本文件的读写:
* 复制文件:test.properties */
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new FileReader("test.properties"));
BufferedWriter bw = new BufferedWriter(new FileWriter("test_copy.properties"));
// 进行读写,缓冲流特有的方法就是可以按照行来读取,如果读取结束返回null
String line = null; while ((line=br.readLine()) != null){
bw.write(line); // 写入换行
bw.newLine(); // 刷新
bw.flush();
}
// 关闭流
bw.close();
br.close();
}
}

字节流和字符流的总结:

IO流只能操作文件”文件”,不能操作文件夹(目录),否则会出现异常。
打印流:
PrintStream,PrintWriter:字节打印流,字符打印流;打印流只有输出流,没有输入流;输出的目的可以是文件,也可以是其他流。PrintStream自带刷新功能,PrintWriter需要手动开启。
PrintStream:打印出来的字符的编码使用的是系统默认编码。

package com.xiaoshitou_io;import java.io.IOException;import java.io.PrintStream;public class Test { /*
* 使用打印流:PrintStream */
public static void main(String[] args) throws IOException{
PrintStream ps = new PrintStream("print.txt");
ps.println("旺旺");
ps.println("欢欢");
ps.println("乐乐");
ps.close(); // 结果:
/*
旺旺
欢欢
乐乐 */
}
}

PrintWriter:

package com.xiaoshitou_io;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;public class Test { /*
* 使用打印流:PrintWriter */
public static void main(String[] args) throws IOException{ // 创建PrintWriter对象时,开启自动刷新功能
PrintWriter pw = new PrintWriter(new FileWriter("print.txt"), true);
pw.println("我是PrintWriter");
pw.println("出来的");
pw.close(); // 结果:
/*
我是PrintWriter
出来的 */
}
}

序列化&反序列化:
序列化:就是将对象写入文件的过程
反序列化:从文件读入对象的过程
ObjectOutputStream&ObjectInputStream:需要序列化的对象必须去实现Serializable接口,否则在序列化的时候会出错。
序列化的注意点:
1、static修饰的成员不能被序列化
2、要想成员变量不被序列化,可以用transient关键字修饰
3、为了不发生序列号冲突,设置:serialVersionUID
下面就进行序列化和反序列化:

package com.xiaoshitou_io;import java.io.Serializable;public class Student implements Serializable{ private static final long serialVersionUID = -5214244848175027425L; private String name; private String id; private transient String phone;
public Student(String name, String id, String phone) { super(); this.name = name; this.id = id; this.phone = phone;
} public Student() { super();
}
@Override public String toString() { return "Student [name=" + name + ", id=" + id + ", phone=" + phone
+ "]";
}
public String getName() { return name;
} public void setName(String name) { this.name = name;
} public String getId() { return id;
} public void setId(String id) { this.id = id;
} public String getPhone() { return phone;
} public void setPhone(String phone) { this.phone = phone;
}
}package com.xiaoshitou_io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Test { /*
* 进行序列化和反序列化
* 对Student对象序列化 */
public static void main(String[] args) throws IOException, ClassNotFoundException{ // 创建ObjectOutputStream对象,绑定目的地
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tmp.txt")); // 创建Student对象
Student stu = new Student("张三", "T001", "15522223333"); // 写入对象
oos.writeObject(stu); // 关闭流
oos.close();
System.out.println("序列化成功!");
System.out.println("==============分割==============");
// 进行反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("tmp.txt")); // 读取对象
Object obj = ois.readObject(); if (obj instanceof Student){
Student s = (Student)obj;
System.out.println(s);
} // 关闭流
ois.close();
System.out.println("反序列化成功!"); // 结果:phone是transient关键字修饰的,所以没有被序列化
/*
序列化成功!
==============分割==============
Student [name=张三, id=T001, phone=null]
反序列化成功! */
}
}

Properties:
Properties类是HashTable的一个子类,实现了Map接口,所以里面保存的是键值对,元素的存取是无序的,这个类经常被用来处理配置文件。
利用Properties来读写文件:

package com.xiaoshitou_io;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;public class Test { /* * 利用Properties来读写文件 */ public static void main(String[] args) throws IOException{ // 读取Properties文件:pro.properties Properties pro = new Properties(); // 加载文件 pro.load(new FileReader("pro.properties")); // 根据key来读取值 String key = pro.getProperty("key"); System.out.println(key); String value = pro.getProperty("匿名"); System.out.println(value); System.out.println("============================="); // 修改Properties内的值,或者添加新的值 pro.setProperty("key", "我是修改的值"); pro.setProperty("add", "我是新添加的值"); // 保存进文件 pro.store(new FileWriter("pro.properties"),""); System.out.println("修改完成"); // 控制台打印结果: /* 姥姥阿里 娇娇 ============================= 修改完成 */ // pro.properties 文件中的内容: /* # #Sun Jun 11 08:53:22 CST 2017 key=我是修改的值 张嘴=监控 匿名=娇娇 add=我是新添加的值 */ }}
本文转自xmgdc51CTO博客,原文链接:http://blog.51cto.com/12953214/1940497 ,如需转载请自行联系原作者