IO流主要是处理设备之间的数据传输
需要注意的是:字节流以字节(8bit)为单位,字符流以字符为单位,一个字符包含多个字节,具体和编码有关,字节流可以处理所有的文件,而字符流只能处理文本类型的文件。
从图中可以看出这两个类分别都是InputStream和OutputStream的子类,父类都是抽象类。
FileInputStream 类有三个重载方法,最常用的是前面两个,第一个的参数一般是文件的路径,第二个就是File对象。
//通过字节流读取文本内容(中文可能会乱码)
//对于文本文件使用字符流处理(.txt,.java,.c)
//对于非文本文件使用字节流处理(.jpg,.png,.doc,.ppt)
public static void test01(){
FileInputStream fr=null;
try {
//1、获取file对象
File file = new File("src/main/java/annotation/io/test.txt");
//2、提供具体的流
fr = new FileInputStream(file);
//3、数据的读入,
// read()返回读入的一个字符,如果到达文件末尾,返回-1
//方式一:一个字节的读
// int read = fr.read();
// while (read !=-1){
// System.out.print((char) read);
// read = fr.read();
// }
//方式二:字节数组读取
byte[] buffer = new byte[4];
int len;
while ((len=fr.read(buffer)) !=-1){
String str = new String(buffer, 0, len);
System.out.print(str);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fr !=null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
需要注意的是:由于这个是字节流,read()方法是一个重载方法,可以一个字节一个字节的读入,也可以按照字节数组的方式读入,读到文件末尾都会返回-1. 一般使用前面两个,第三个指定数组长度读入。
由于是通过字节读入数据,所以读取文本文件就会出现乱码。
/**
* 字节流
* 向文件中写入字符串
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName); //获取File对象,
OutputStream out =new FileOutputStream(f);
String str="Hello World";
byte[] b=str.getBytes(); //字符串转化为byte数组
out.write(b);
out.close();
}
}
write() 方法也是一个重载方法,主要是写入字节数组
这两个类主要处理字符,使用方法和上面的字节流基本一样,就是读取的数据是一个一个的字符而已
这两个类同样具有read() 方法以及 write() 方法,而且都是重载方法
看上面图就知道可以传一些什么样的参数进去。
下面是一个小例子(读取和写入文本文件,以及复制文本文件):
package annotation.io;
import java.io.*;
//字符流
public class demo01 {
public static void main(String[] args) {
// test01();
// test02();
// test03();
copyFile();
}
//一个字符一个字符读入
public static void test01(){
FileReader fr=null;
try {
//1、获取file对象
File file = new File("src/main/java/annotation/io/test.txt");
System.out.println(file.getAbsoluteFile()); //打印以下路径
//2、提供具体的流
fr = new FileReader(file);
//3、数据的读入,
// read()返回读入的一个字符,如果到达文件末尾,返回-1
int read = fr.read();
while (read !=-1){
System.out.print((char) read);
read = fr.read();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fr !=null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//对read()方法的重载使用
public static void test02(){
FileReader fr=null;
try {
//1、获取file对象
File file = new File("src/main/java/annotation/io/test.txt");
//2、提供具体的流
fr = new FileReader(file);
//3、数据的读入,这次使用字符数组读入,读完最后还是返回-1
char[] cbuf = new char[5]; //每次写入5个字符
int read; //fr.read(cbuf) 返回的就是每次读入的字符数,比如第一次就返回5
while ((read = fr.read(cbuf)) !=-1){
for (int i = 0; i <read ; i++) {
System.out.print(cbuf[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fr !=null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//从内存中写出数据到硬盘的文件里
//对应的file可以不存在,输出会自动创建文件
//如果存在,FileWriter(file) 或者FileWriter(file,false) 对原有的文件覆盖,
//如果是FileWriter(file,true) 是在原有的文件追加内容!
public static void test03(){
FileWriter fw=null;
try {
//1、获取file对象,指名写出的文件
File file = new File("src/main/java/annotation/io/test_write.txt");
//2、提供具体的流
fw = new FileWriter(file);
//3、写出的操作(这里就写出字符串)
fw.write("write String! \n");
fw.write("write String 22222");
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fw !=null) fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//通过字符流实现文件的复制(读入,写出操作)
public static void copyFile(){
FileReader fr = null;
FileWriter fw=null;
try {
//1、获取file对象
File r_file = new File("src/main/java/annotation/io/test.txt"); //获取读取文件对象
File w_file = new File("src/main/java/annotation/io/test_write.txt"); //写入文件对象
//2、提供具体的流
fr = new FileReader(r_file);
fw = new FileWriter(w_file);
//3、读取数据(使用字符数组读入)
char[] cbuf = new char[5];
int read; //fr.read(cbuf) 返回的就是每次读入的字符数,比如第一次就返回5
while ((read = fr.read(cbuf)) !=-1){
//4、写入数据
fw.write(cbuf);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fr !=null) fr.close();
if(fw !=null) fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
其实就是可以将字节流转化为字符流,字符流可以转化为字节流,
InputStreamReader 字节 —> 字符
OutputStreamReader 字符 输出流----->字节 输出流
比如utf-8编码的文件可以通过这个转换流转化为gbk的编码格式
package annotation.io;
//转换流
import java.io.*;
/**属于字符流
* InputStreamReader 字节 ---> 字符
* OutputStreamReader 字符 输出流----->字节 输出流
* 字节流与字符流之间的转换
*/
public class demo03 {
public static void main(String[] args) {
// test01();
test02();
}
//将字节转化为字符在控制台输出
public static void test01(){
FileInputStream fis=null;
InputStreamReader isr = null;
try {
//1、获取file对象
File file = new File("src/main/java/annotation/io/test.txt");
fis = new FileInputStream(file);
//参数二指名字符集,具体使用哪个字符集
isr = new InputStreamReader(fis,"UTF-8");
char[] cbuf = new char[5];
int len;
while ((len = isr.read(cbuf)) != -1){
String str = new String(cbuf, 0, len);
System.out.print(str);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fis !=null) fis.close();
if(isr !=null) isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//将utf-8编码文件通过字节流读取,转化为字符流,然后再将字符流转化为字节流,以gbk编码存储
public static void test02(){
FileInputStream fis=null;
InputStreamReader isr = null;
FileOutputStream fos=null;
OutputStreamWriter osw = null;
try {
//1、获取file对象
File file = new File("src/main/java/annotation/io/test.txt");
File file1 = new File("src/main/java/annotation/io/test_gbk.txt");
fis = new FileInputStream(file); //输入文件流
fos = new FileOutputStream(file1); //输出文件流
//2、参数二指名字符集,具体使用哪个字符集,将字节转化为字符
isr = new InputStreamReader(fis,"utf-8");
osw = new OutputStreamWriter(fos,"gbk"); //设置输出文件编码
char[] cbuf = new char[10];
int len;
while ((len = isr.read(cbuf)) != -1){
//3、将字符数组写入
osw.write(cbuf,0,len);
System.out.print(cbuf);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//关闭流
// if(fos !=null) fos.close();
// if(osw !=null) osw.close();
if(fis !=null) fis.close();
if(isr !=null) isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}