1.IO整体概括
Java中的IO体系主要分为以下三大类
个人总结,不是很完整,如有出错,请多多指教。
未列出全部方法,有的方法类似直接省略。
io流的整体分类:
输入流 | 输出流 | |
---|---|---|
字节流 | InputStream | OutputStream |
字符流 | Reader | Writer |
什么是输入输出
呢,我以我个人认知的简单叙述:(有点简陋)
输入流:以程序本身为参考点,简单说就是进入程序的流。
输出流:以程序本身为参考点,简单说就是从程序中输出的流。
查看源码可知,IO体系采用的是装饰者设计模式,因此在使用时可互相嵌套使用。
上思维导图中基本上把常用的方法都罗列出来了,其中DataInputStream/ObjectInputStream
等也都挺常用的,但是使用起来也很简单,这里不多叙述。
2.基本使用
直接上代码吧,与上一篇File简单配合使用:
import java.io.*;
public class IOLearning {
static String filePath = "G:" + File.separator + "io_test" + File.separator + "io_test.txt";
static String newFilePath = "G:" + File.separator + "io_test" + File.separator + "new_io_test.txt";
public static void main(String[] args) {
//System.out.println(readFileWithFileInputStream(filePath));
//System.out.println(readFileWithBufferedInputStreamAndFileInputStream(filePath));
//writeFileWithBufferedOutputStreamAndFileOutputStream(filePath, newFilePath);
//System.out.println(writeFileWithReader(filePath));
copyFileReaderWithFileWriter(filePath,newFilePath);
}
//使用FileInputStream读取指定路径文件的内容
private static String readFileWithFileInputStream(String path) {
FileInputStream fis = null;
StringBuilder builder = new StringBuilder();
try {
fis = new FileInputStream(path);
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
builder.append(new String(bytes, 0, len, "gbk"));
}
// System.out.println(builder.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(fis);
}
return builder.toString();
}
//FileInputStream BufferedInputStream读取文件信息
public static String readFileWithBufferedInputStreamAndFileInputStream(String path) {
StringBuilder builder = new StringBuilder();
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(path);
bis = new BufferedInputStream(fis);
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
//设置格式,避免中文乱码
builder.append(new String(bytes, 0, len, "gbk"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(fis);
close(bis);
}
return builder.toString();
}
public static String writeFileWithReader(String filePath) {
FileReader fr = null;
BufferedReader br = null;
StringBuilder builder = new StringBuilder();
try {
fr = new FileReader(filePath);
br = new BufferedReader(fr);
String str;
while ((str = br.readLine()) != null) {
builder.append(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(fr);
close(br);
}
return builder.toString();
}
//FileInputStream BufferedInputStream读取文件信息后直接写入新的文件
public static void writeFileWithBufferedOutputStreamAndFileOutputStream(String path, String newPath) {
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
fis = new FileInputStream(path);
//append 构造函数 , 文件追加在后方
fos = new FileOutputStream(newPath, true);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
//设置格式,避免中文乱码
//builder.append(new String(bytes, 0, len, "gbk"));
bos.write(bytes, 0, len);
}
bos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(fis);
close(bis);
close(fos);
close(bos);
}
}
public static void copyFileReaderWithFileWriter(String filePath,String newPath){
FileReader fr = null;
//Reader reader = new FileReader(filePath);
FileWriter fw = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
fr = new FileReader(filePath);
fw = new FileWriter(newPath);
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
String str;
while ((str=br.readLine())!=null){
bw.write(str);
bw.newLine();
}
bw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fr);
close(fw);
close(br);
close(fw);
}
}
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
上面的案例,基本上把基本的使用方法囊括,有兴趣的朋友自己看看。
3.注意事项
- 使用后必须关闭流
- 在使用输出流后,记得使用
flush()
方法进行刷新,否则写入无效果 - 合理选用合适的流能大大提升读写效率
- 尽量使用BufferedXx(缓冲流),减少访问次数等提升效率
- 字符流使用了缓冲区,而字节流没有使用缓冲区。使用字符流未关闭流时,不会有输出。
- 如果是音频文件、图片、歌曲,就用字节流好点;
如果是关系到中文(文本)的,用字符流好点,字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串而字节流处理单元为 1 个字节,操作字节和字节数组。注意:进行转码,避免出现乱码问题
,字节流通常处理二进制文件 - 字节流
默认不使用缓冲区
;字符流使用缓冲区
。