
命里有时终须有,命里无时莫强求。
简介
- IO操作是指Input、Output,数据的输入与输出,主要是操作数据:
- Input指的是从数据源读取数据到内存,例如:把数据从磁盘上读取到内存中,从网络读取数据到内存中等等。
- Output值得是把数据输出到其他地方,例如:把数据写入到文件,把数据输出到网络等等。
- Java中把文件中的内容读取到内存叫做输入流InputStream,而把数据写入到文件中叫做输出OutputStream,这是最基本的两种IO流
同步和异步
- 同步是指读写IO的操作完成以后才能完成其他任务,优点是编写简单,缺点是执行效率低
- 异步是指读写IO的操作的同事可以完成其他任务,优点是执行效率高,缺点是编写复杂
-
提供同步IOjava.io
-
提供异步IOjava.nio
File对象
-
中提供了文件操作类File,使用构造方法创建一个File对象,即使文件或者目录不存在也不会报错,因为这个时候并不会操作磁盘,只有调用File对象的具体方法时候才会进行磁盘操作java.io
public class DemoController {
public static void main(String[] args){
File f = new File("C:javahello.java");
System.out.println(f); // C:javahello.java
}
}
- getPath(),该方法返回构造方法传入的路径,原封不动的返回
public class DemoController {
public static void main(String[] args){
File f = new File(".javahello.java");
System.out.println(f.getPath()); // .javahello.java
}
}
- getAbsolutePath(),该方法返回的是绝对路径,拼接上完整的路径但是不帮着处理. ..符号(.表示当前目录 ..表示上级目录)
public class DemoController {
public static void main(String[] args){
File f = new File(".javahello.java");
System.out.println(f.getAbsolutePath()); // E:javaProjectstudy.javahello.java
}
}
- getCanonicalPath(),该方法返回的是处理好的规范路径
public class DemoController {
public static void main(String[] args) throws IOException {
File f = new File(".javahello.java");
System.out.println(f.getCanonicalPath()); // E:javaProjectstudyjavahello.java
}
}
- separator 可以打印对应系统下的路径分隔符
public class DemoController {
public static void main(String[] args) {
System.out.println(File.separator); // windows linux /
}
}
- isFile() 判断文件是否存在
- isDirectory() 判断文件目录是否存在
- canRead() 是否可读
- canWrite() 是否可写
- canExecute() 是否可执行 如果是目录则表示能否显示所有的文件和子目录
- length() 文件字节大小
- createNewFile() 创建一个新文件
- delete() 删除文件
- createTempFile() 创建临时文件,与deleteOnExit()在JVM退出时删除改文件,两者联动使用
- list()和listFiles() 列出目录下面所有文件和子目录名,listFiles提供了很多重载方法,可以过滤文件和目录
- mkdir() 创建目录
- mkdirs() 创建目录,如果父目录不存在也会创建
- delete() 删除目录,目录必须为空才能删除成功
Path对象
- Path位于Java.nio.file包。Path对象和File对象差不多
- Paths.get(".","father","children"...) 创建一个Path对象
- toAbsolutePath() 转化为绝对路径
- normalize() 转化为规范路径
- toFile() 转化为File对象
InputStream
- InputSteam是一个抽象类,FileInputStream是InputSteam的子类
public static void readFile() throws IOException {
InputStream inputStream = null;
try{
inputStream = new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt"); // 文件里面写Hello World!, 文件可以保存任意地方
int n;
while((n = inputStream.read()) != -1){
System.out.println((char) n);
}
} finally {
inputStream.close(); // 关闭流,必须用完就关闭流
}
}
缓冲
- 上面的read虽然可疑读取文件内容,但是一次只能读取一个字节,并不是很高效,可以通过InputSteam中的重载方法来读取多个字节
public static void readMoreFile() throws IOException {
InputStream inputStream = null;
byte[] bytes = new byte[1000];
try{
inputStream = new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
int n;
while((n = inputStream.read(bytes)) != -1){
System.out.println(n);
}
} finally {
inputStream.close(); // 关闭流
}
}
阻塞
- 阻塞的意思就是有任务在执行,卡在那不往后面执行,比如在执行read()方法的时候就需要等待read()方法返回后才能执行下面的代码
模拟InputStream
- 可以使用
伪造一个数据流ByteArrayInputStream
public static void makeSteam () throws IOException {
byte[] data = { 72, 101, 108, 108, 111, 33 };
try (InputStream inputStream = new ByteArrayInputStream(data)) {
int n;
while ((n = inputStream.read()) != -1) {
System.out.println((char) n);
}
}
}
OutputStream
- 与InputStream相反,OutputStream是输出流的超类,也是抽象类。
- OutputSteam也提供了
方法关闭输出流,还提供了一个close()
方法,作用是将内容真正输出到目的地,通常情况不需要调用这个人方法,因为OutputStream会自动调用,如果需要在某些特定情况主动推送缓存发送就需要主动触发flushflush()
public static void fileOutput() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
// 写入 wirte方法也是阻塞的
fileOutputStream.write(72); // H
fileOutputStream.write(101); // e
fileOutputStream.write(108); // l
fileOutputStream.write(108); // l
fileOutputStream.write(111); // o
fileOutputStream.close();
// 或者通过write的重载方法 与InputStream一样,为了避免IO错误导致资源没有关闭,通常需要用try...finally
try (OutputStream fileOutputStream2 = new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt")){
fileOutputStream.write("Hello".getBytes("UTF-8")); // Hello
} finally {
fileOutputStream.close();
}
}
- FileOutputStream是OutputStream的一个实现类,可以从文件中获取输出流。与InputStream一样,ByteArrayOutputStream可以再内存中模拟一个OutputStream输出流
public static void makeOutput () throws IOException {
byte[] data;
ByteArrayOutputStream outputStream = null;
try {
outputStream = new ByteArrayOutputStream();
outputStream.write("Hello".getBytes());
data = outputStream.toByteArray();
} finally {
outputStream.close();
}
System.out.println(new String(data, "UTF-8"));
}
操作zip
- 读取zip使用ZipInputStream
public static void getZip() throws IOException {
ZipInputStream zipInputStream = null;
try{
zipInputStream = new ZipInputStream(new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05Demo05.zip"));
ZipEntry entry = null;
// 判断是否还有文件
while ((entry = zipInputStream.getNextEntry()) != null){
String name = entry.getName(); // 获取文件名字
System.out.println(name);
if (!entry.isDirectory()){
int n;
while ((n = zipInputStream.read()) != -1){
System.out.println((char) n);
}
}
}
}finally {
zipInputStream.close();
}
}
- 写入zip包时使用的是ZipOutputStream
public static void setZip() throws IOException {
ZipOutputStream zipOutputStream = null;
try {
zipOutputStream = new ZipOutputStream(new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05Demo05.zip"));
ArrayList<File> files = new ArrayList<>();
files.add(new File("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt"));
files.add(new File("E:javaProjectstudystudy-20-8-30srcDemo05readme - 副本.txt"));
for (File file : files) {
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
zipOutputStream.write(getFileToByte(file));
zipOutputStream.closeEntry();
}
}finally {
zipOutputStream.close();
}
}
public static byte[] getFileToByte(File file) {
byte[] by;
try {
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bb = new byte[2048];
int ch;
ch = inputStream.read(bb);
while (ch != -1) {
byteArrayOutputStream.write(bb, 0, ch);
ch = inputStream.read(bb);
}
by = byteArrayOutputStream.toByteArray();
} catch (Exception ex) {
throw new RuntimeException("transform file into bin Array 出错",ex);
}
return by;
}
Reader与Writer
- 如果是读写字符,比如纯文本的数据源,可以使用Reader和Writer进行读和写的操作,这种流成为字符流,数据源虽然是字节的,但是Reader和Writer内部进行了处理,将byte做了解码转化为char
- FileReader是Reader的一个子类,FileReader可以打开一个文件并读取
public static void readerReadFile() throws IOException {
Reader reader = null;
try{
reader = new FileReader("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
int n;
while((n = reader.read()) != -1){
System.out.println((char) n);
}
}finally {
reader.close();
}
}
- CharArrayReader可以通过传入一个char[]模拟一个Reader
Reader reader = new CharArrayReader("Hello".toCharArray);
- StringReader 可以通过传入一个String 模拟一个StringReader
Reader reader = new StringReader("Hello")
- InputStreamReader可以通过传入一个InputStream转为一个Reader
Reader reader = new InputStreamReader(new FileInputStream("XXX"),"UTF-8");
- FileWriter可以项文件中写入字符流
Writer writer = new FileWriter("XXX");
wirter.wirter("asdas");
- CharArrayWriter可以在内存中创建一个Writer,作用就是狗在一个一个缓冲区
public static void wirterFile() {
try (CharArrayWriter writer = new CharArrayWriter()) {
writer.write(72); // H
writer.write(101); // e
writer.write(108); // l
writer.write(108); // l
writer.write(111); // o
char[] data = writer.toCharArray();
System.out.println(new String(data));
}
}
- StringWriter也是一个机遇内存的writer和CharArrayWriter类似
- OutPutStreamWriter可以讲一个FileOutputStream流转化为Writer
本文作者《猿氏·凯》,如果雷同,纯属抄袭····