Java中的IO流
流的概念
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。数据在两设备间的传输称为流,流的本质是数据传输。
Java中流的分类
根据处理数据类型的不同分为:字节流和字符流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
字节流和字符流的区别:
读写单位不同:
字节流以byte字节(8个bit)为单位;
字符流以char字符(2个byte)为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:
字节流能处理所有类型的数据(如图片、avi等);
而字符流只能处理字符类型的数据。
- 结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
根据数据流向不同分为:输入流和输出流
输入流只能进行读操作;
输出流只能进行写操作。
程序中需要根据待传输数据的不同特性而使用不同的流。
字节流
字节输入流(FileInputStream)和字节输出流(FileOutputStream)
-
使用字节流读取本地文本打印出来并写入另一个文本
FileInputStream fis = null; FileOutputStream fos = null; try { // 相对路径 //fis = new FileInputStream("a.txt"); // 绝对路径 //fis = new FileInputStream("C:/workspace/IOStream/a.txt"); fis = new FileInputStream(new File("a.txt")); fos = new FileOutputStream("b.txt"); //在原来的数据后面添加(不覆盖) //fos = new FileOutputStream("b.txt",true); int len; //每读一次就写一次到本地文本(效率不高) while ((len = fis.read()) != -1) { System.out.print((char) len + ","); fos.write(len); } } catch (IOException e) { e.printStackTrace(); } finally { try { fis.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } }
**注意:
1、本地文本内容不能是中文,否则打印输出时会出现乱码(写入另一个文本时不会乱码)。
2、注意流使用完毕后必须关闭(后面的例子一样,不再赘述)**
-
使用byte数组缓冲区读取并写入文本
FileInputStream fis = new FileInputStream("a.txt"); FileOutputStream fos = new FileOutputStream("c.txt"); byte[] array = new byte[8*1024]; int len; // 读取文本数据每填满字节数组array就一次写到本地。(效率高) while ((len = fis.read(array)) != -1) { System.out.println(new String(array, 0, len)); // 将字节数组中的文件写到文件上去 fos.write(array, 0, len); } fis.close(); fos.close();
**注意:
1、此时即便要读取的文本有中文,打印输出时候也不一定会有乱码(在读取文本的内容小于缓冲区字节数组内容时。当然也有肯能大于,所以不推荐这样使用,复制中文可以用字符流)。
2、除了复制文本也可以复制图片、音乐等。使用缓冲区能提高效率**
-
使用Buffered缓冲区复制文件
FileInputStream fis = new FileInputStream("butterfly.mp3"); // 创建缓冲区输入流对象,对fis进行包装 BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("Havorld.mp3"); // 创建缓冲区输出流对象,对fos进行包装 BufferedOutputStream bos = new BufferedOutputStream(fos); // bis.read()会先将文件上的数据读到缓冲区中,再从缓冲里获取数据 int b; while ((b = bis.read()) != -1) { // bos.write(b)是先将字节写到缓冲区里,然后在从缓冲区中一起写出 System.out.print((char) b + ""); bos.write(b); } bis.close(); bos.close();
**
注意:
1、使用Buffered缓冲区如果有中文,在输出打印时会出现乱码。
2、Buffered缓冲区的大小是8*1024个字节也就是8M。**
字符流
字符输入流(FileReader)和字符输出流(FileWriter)
-
使用字符流读取中文打印出来并写入另一个文本
FileReader fr = new FileReader("d.txt"); FileWriter fw = new FileWriter("f.txt"); int len; while ((len = fr.read()) != -1) { System.out.print((char) len + ","); fw.write(len); } fr.close(); fw.close();
**注意:
1、字符流不能用于读写图片、音乐文件。
2、字符流加缓冲区同字节流(BufferedReader,BufferedWriter),此处不再赘述。**
关于中文文字总结
- 从文件读取中文(字符)打印输出时,不能使用字节流(会出现乱码),用字符流。
-
向文件中写入中文(字符)时,可以用字节流,也可以用字符流。
//字节流写入中文 FileOutputStream fos = new FileOutputStream("e.txt"); fos.write("Hi,你们好吗".getBytes()); fos.write("\n".getBytes()); fos.write(97); fos.write("b".getBytes()); fos.close(); //字符流写入中文 FileWriter fw = new FileWriter("e.txt"); fw.write("hello,掌声在哪里"); fw.close();
复制中文文字(字符)时。可以使用字节流,也可以使用字符流,优先使用字节流(效率高)。
转换流InputStreamReader和OutputStreamWriter
转换流使用场景
- 当字节和字符之间有转换动作时;
- 流操作的数据需要编码或解码时。
当从一个UTF-8格式的文本中读取中文并写到GBK格式的文本中时需要用到转换流
//字节流(FileInputStream)转换成了字符流(InputStreamReader),同时指定了编码
InputStreamReader isr = new InputStreamReader(new FileInputStream("x.txt"), "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("y.txt"), "GBK");
int ch;
while((ch = isr.read()) != -1) {
osw.write(ch);
}
//同时也可以加上Buffered缓冲区
/*
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);
int ch;
while((ch = br.read()) != -1) {
bw.write(ch);
}
*/
isr.close();
osw.close();
内存输出流ByteArrayOutputStream
FileInputStream fis = new FileInputStream("note.txt");
//内存输出流:一般操作文本,溢出的可能性很小(当是大文件时就容易内存溢出)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
while((len = fis.read()) != -1) {
//把输入流全部写入内存,然后再全部输出
baos.write(len);
}
byte[] array = baos.toByteArray();
System.out.println(new String(array)); //输出
System.out.println(baos);
fis.close();
DataInputStream和DataOutputStream
通过DataInputStream获取文件中的内容输出打印出来,然后通过DataOutputStream写到另一个文件中
DataInputStream dis = new DataInputStream(new FileInputStream("DataInput.txt"));
DataOutputStream dos = new DataOutputStream(new FileOutputStream("DataOutput.txt"));
int len = 0;
byte[] buffer = new byte[8 * 1024];
while ((len = dis.read(buffer)) != -1) {
dos.write(buffer, 0, len);
dos.flush();//刷新缓冲区
System.out.println(new String(buffer));
}
dis.close();
dos.close();
存取JavaBean中的基本数据类型
public static void main(String[] args) throws IOException {
Student[] students = { new Student("Havorld", 22), new Student("Jack", 18), new Student("Sunny", 17) };
DataOutputStream dos = new DataOutputStream(new FileOutputStream("Havorld.txt"));
for (Student student : students) {
// 按UTF-8的格式写入字符串
dos.writeUTF(student.getName());
// 写入int数据
dos.writeInt(student.getAge());
}
// 所有数据至目的地
dos.flush();
// 关闭流
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("Havorld.txt"));
// 读出数据并还原为对象
for (int i = 0; i < students.length; i++) {
// 读出UTF字符串
String name = dis.readUTF();
// 读出int数据
int age = dis.readInt();
students[i] = new Student(name, age);
}
// 关闭流
dis.close();
// 显示还原后的数据
for (Student student : students) {
System.out.printf("%s\t%d%n", student.getName(), student.getAge());
}
}
创建JavaBean Student类
class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
读写对象流ObjectInputStream和ObjectOutputStream
使用ObjectInputStream和ObjectOutputStream保存和读取对象
public static void main(String[] args) throws ClassNotFoundException, IOException {
ObjectOutputStream objectwriter = new ObjectOutputStream(new FileOutputStream("student.txt"));
objectwriter.writeObject(new Student("Havorld", 22));
objectwriter.writeObject(new Student("Jack", 18));
objectwriter.writeObject(new Student("Sunny", 17));
ObjectInputStream objectreader = new ObjectInputStream(new FileInputStream("student.txt"));
for (int i = 0; i < 3; i++) {
System.out.println(objectreader.readObject());
}
objectwriter.close();
objectreader.close();
}
上一篇: Record25—多维数组的本质
下一篇: 多维数组