Java粗浅认识-I/O(一)
I/O
IO到底是什么?I/O是(Input和Output)输入输出,在操作系统层面,Input就是从输入设备(磁盘驱动器、网络和终端)读取数据到内存中,
Output就是从内存中把数据输出到输出设备中(磁盘驱动器、网络和终端),而这些输入输出设备都是在Linux系统当中,所有的输入、输出设备都被抽象化为文件,二文件就是一个n个字节的序列,文件又被分类为普通文件(二进制和文本),目录,套接字(用于网络通信)。
Unix系统上支持的I/O模型
同步IO,异步IO
同步IO,阻塞式IO、非阻塞式IO、IO复用、信号驱动IO,都是同步IO,不同之处在于,应用系统调用内核进行数据访问时的两个阶段中的第一个阶段等待数据是否阻塞,第二个阶段都是阻塞式的,从内核把数据返回给应用程序
异步IO,则是在两个阶段都不会阻塞当前进程或线程
Java中的IO发展
java1.0中就存在阻塞式IO,就是常见的基于Stream、File、RandomAccessFile、Writers和Readers的IO处理,
java1.4中引入了NIO,主要解决,第一阶级等待数据是否阻塞的问题,IO复用式的IO操作,引入了新的处理的对象,如Channel、Selecotr、Buffer缓冲区
java1.7中引入了NIO2,引入了异步IO(这里需要注意,真正在现在unix操作系统上,是不支持异步IO,只有Windows操作系统才实现了真正意义上的异步IO),
引入新的类;新的文件系统抽象,如:Path、Files工具类等
接下来,针对上面的内容,一一写代码举例:
阻塞式I/O
/**
* 基于java 流文件复制,这里面涉及到的异常处理,资源回收,位运算等,后面会一一讲解
*
* @param sourceFileName
* @param targetFileName
*/
public static void copyFile(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream(sourceFile);
outputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[1 << 10];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void fileCopyWithBuffer(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
InputStream inputStream;
OutputStream outputStream;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
inputStream = new FileInputStream(sourceFile);
outputStream = new FileOutputStream(targetFile);
bufferedInputStream = new BufferedInputStream(inputStream);
bufferedOutputStream = new BufferedOutputStream(outputStream);
byte[] buffer = new byte[1 << 10];
int len;
while ((len = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//这里资源关闭,没有显示关闭inputStream和outputStream,那是因为,buffered**的关闭操作,会关闭底层的内嵌的stream
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 这里涉及到一个乱码问题
*
* @param sourceFileName
* @param targetFileName
*/
public static void copyFileWithCharacterStream(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
Reader reader = null;
Writer writer = null;
try {
reader = new FileReader(sourceFile);
writer = new FileWriter(targetFile);
char[] chars = new char[1 << 10];
int len;
while ((len = reader.read(chars)) != -1) {
writer.write(chars, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 这里有字符乱码问题
*
* @param sourceFileName
* @param targetFileName
*/
public static void copyFileWithBuffedCharacterStream(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
Reader reader;
Writer writer;
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
reader = new FileReader(sourceFile);
writer = new FileWriter(targetFile);
bufferedReader = new BufferedReader(reader);
bufferedWriter = new BufferedWriter(writer);
String line;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 文本文件编解码过程,文本文件(有自己的字符集)->StreamDecoder做解码(传入进去的字符集)
* ->StreamEncoder做编码(自己的字符集)
* 没有解码时用的字符集不兼容文件的字符集,则会产生乱码
*
* @param sourceFileName
* @param targetFileName
*/
public static void copyFileWithInputCharset(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
InputStream inputStream;
OutputStream outputStream;
InputStreamReader inputStreamReader;
OutputStreamWriter outputStreamWriter;
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
inputStream = new FileInputStream(sourceFile);
outputStream = new FileOutputStream(targetFile);
//系统的字符集编码GBK,底层通过StreamDecoder,做的流解码
inputStreamReader = new InputStreamReader(inputStream, "utf-8");
//StreamEncoder,做流编码
outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8");
bufferedReader = new BufferedReader(inputStreamReader);
bufferedWriter = new BufferedWriter(outputStreamWriter);
String line;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void copyFileWithRandomAccessFile(String sourceFileName, String targetFileName) {
File sourceFile = new File(sourceFileName);
File targetFile = new File(targetFileName);
if (!sourceFile.exists()) {
System.out.println("文件" + sourceFileName + "不存在。");
return;
}
if (!targetFile.exists()) {
try {
if (!targetFile.createNewFile()) {
System.out.println("文件" + targetFileName + "创建失败。");
return;
}
} catch (IOException e) {
System.out.println("文件" + targetFileName + "创建失败。");
e.printStackTrace();
}
}
RandomAccessFile reader = null;
RandomAccessFile writer = null;
try {
reader = new RandomAccessFile(sourceFile, "r");
writer = new RandomAccessFile(targetFile, "rw");
byte[] buffer = new byte[1 << 10];
int len;
//第一次的时候是零
System.out.println("reader所在位置:"+reader.getFilePointer());
System.out.println("writer所在位置:"+writer.getFilePointer());
//这里是可以调整当前位置
reader.seek(0);
writer.seek(0);
while ((len = reader.read(buffer)) != -1) {
writer.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
阻塞式I/O在java中的文件操作使用到此结束。