IO流
设备之间进行数据传输的过程称为流。
流:流本身也是一个具体的对象,它可以被看成是和特定设备连接的管道。
流的分类
根据数据的流向可以分为:==输入流和输出流==
根据流返回或接受数据类型可以分为:==字节流和字符路==
注意:
字符流内部处理的依旧是字节数据,他只是对外提供了字符数据的调用接口。
==节点流和处理流==
字节输出流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;
public class Output { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("a.txt",true); fos.write(97); fos.write(98); fos.close(); } }
|
输出流特点:
- 输出流写入数据,文件如果不存在则会自动创建文件。
- 如果希望每次在写的数据后追加内容,则可以设置FileOutputStream的构造方法的第二个参数为true(默认是false)。
字节输入流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;
public class Input { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("a.txt");
int i; while((i = fis.read()) != -1){ System.out.println(i); }
fis.close(); } }
|
注意:每次使用结束必须关闭流。
可使用read()和read(byte[] b)等方法读取文件中的数据,如果到达文件末尾, 会返回-1;
流对象用完之后,为了保证能够关闭流,可使用finally子句。
copy练习:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;
public class CopyDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("C:/Users/renhongchang/Desktop/c/aa.txt"); FileOutputStream fos = new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\ccc.txt");
long star = System.currentTimeMillis();
int i; while((i = fis.read()) != -1){ fos.write(i); } long end = System.currentTimeMillis();
int time = (int)(end - star); System.out.println("拷贝使用的时间是:" + time + "mm");
fis.close(); fos.close(); } }
|
缓冲流类:
除了定义字节缓冲区来提高文件拷贝效率外,IO中还提供了两个字节缓冲流来提高文件拷贝效率:
==BufferedInputStream==和==BufferedOutputStream==。
==BufferedInputStream和BufferedOutputStream常用来对InputStream和OutputStream进行缓冲处理==
一旦使用缓冲流,如果没有关闭流,数据保存在缓冲区中,并不及时关闭流。
缓冲流执行写操作时:
- 缓冲区满
- 刷新缓冲区
- 流关闭
使用缓冲流copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.io.*;
public class BufferCopy { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("C:\\Users\\renhongchang\\Desktop\\c\\aa.txt"); BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\ddd.txt")); try{
long star = System.currentTimeMillis();
int i; while((i = bis.read()) != -1){ bos.write(i); } long end = System.currentTimeMillis();
int time = (int)(end - star); System.out.println("拷贝使用的时间是:" + time + "mm"); }catch(IOException e){ e.printStackTrace(); }finally { bis.close(); fis.close(); bos.close(); } } }
|
字符流:
==抽象类Reader和Writer==是字符输入/输出流的根类
int read()
int read(char[] cbuf)
int read(char[] cbuf, int off, int len)
void close()
void flush()
void write(char[] cbuf)
void write(char[] cbuf, int off, int len)
void write(int c)
void write(String str) void close()
Writer如果不使用 flush() 方法或者 close() 方法数据不会写入磁盘。
flush() 和 close() 的区别:
- flush() 是刷新,将数据流中的数据刷出,写入磁盘,使用之后流 还可以继续调用;而close() 是关闭流,使用之后,流不可以再继续调用。
- close() 方法 主要功能是关闭流,释放资源,同时具有刷新流的效果;flush() 方法只能刷新流。
使用字符流写出数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import java.io.FileWriter; import java.io.IOException; import java.io.Writer;
public class WriteDemo { public static void main(String[] args) throws IOException { Writer fw = new FileWriter("b.txt"); try { fw.write(new char[]{'你','好','世','界'}); } catch (IOException e) { e.printStackTrace(); }finally { fw.flush(); fw.close(); } } }
|
使用字符流读入数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.io.FileReader; import java.io.IOException; import java.io.Reader;
public class ReadDemo { public static void main(String[] args) throws IOException { Reader fr = new FileReader("b.txt");
char[] context = new char[128];
int i; try{ while((i = fr.read(context)) != -1){ System.out.print(context); } }catch(Exception e){ e.printStackTrace(); }finally { fr.close(); }
} }
|
按照某种规则将数据存储在计算机中叫编码,反之,用某种规则将计算机中的二进制解析出来叫做解码。
在JDK中,提供了两个类用于实现将字节流转换为字符流,它们分别是InputStreamReader和OutputStreamWriter。
InputStreamReader是==Reader的子类==,它可以==将一个字节输入流转换成字符输入流==,方便直接读取字符。
OutputStreamWriter是==Writer的子类==,它可以==将一个字节输出流转换成字符输出流==,方便直接写入字符。
使用转换流copy不同编码集的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private static void test01()throws IOException { InputStreamReader inputStreamReader = new InputStreamReader( new FileInputStream("C:\\Users\\renhongchang\\Desktop\\c\\b.txt"),"GBK"); OutputStreamWriter outputStreamWriter = new OutputStreamWriter( new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\eee.txt"),"GBK" );
try{ int i; while((i = inputStreamReader.read()) != -1){ outputStreamWriter.write(i); } }catch(Exception e){ e.printStackTrace(); }finally{ inputStreamReader.close(); outputStreamWriter.flush(); outputStreamWriter.close(); }
}
|
注意:使用输入流转换流需要注意,设置的字符集需要和源文件的字符集相同,否则会乱码,写入的时候一般不存在乱码的问题。
序列化:
==将内存中的对象通过某种格式排列之后记录下来== ,这个过程叫对象的 序列化 (Serialization-也叫串行化) 。
练习:
学生实体类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import java.io.Serializable;
public class Student implements Serializable { private String id; private String name; private String sex;
public Student(String id, String name, String sex) { this.id = id; this.name = name; this.sex = sex; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
@Override public String toString() { return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } }
|
实现功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import java.io.*; import java.util.ArrayList; import java.util.List;
public class StudentList{
public static List<Student> getStudentList() { List<Student> studentList = new ArrayList<Student>(); studentList.add(new Student("111","张三","男")); studentList.add(new Student("222","张4","男")); studentList.add(new Student("333","张5","男")); studentList.add(new Student("444","张6","男")); studentList.add(new Student("555","张7","男")); return studentList; }
public static void studentList() throws IOException { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("list.txt")); objectOutputStream.writeObject(getStudentList()); objectOutputStream.flush(); objectOutputStream.close(); }
public static void reStudentList() throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("list.txt")); List list = (List) objectInputStream.readObject(); for (Object obj : list){ System.out.println(obj.toString()); } } }
|
File:
File类常用方法:
createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false。
mkdir() 在指定位置创建一个单级文件夹。
mkdirs() 在指定位置创建一个多级文件夹。
renameTo(File dest)如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名, 如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。
删除:
delete() 删除文件或者一个空文件夹,不能删除非空文件夹,马上删除文件,返回一个布尔值。
deleteOnExit() jvm退出时删除文件或者文件夹,用于删除临时文件,无返回值。
判断:
exists() 文件或文件夹是否存在。
isFile() 是否是一个文件,如果不存在,则始终为false。
isDirectory() 是否是一个目录,如果不存在,则始终为false。
isHidden() 是否是一个隐藏的文件或是否是隐藏的目录。
isAbsolute() 测试此抽象路径名是否为绝对路径名。
获取:
getName() 获取文件或文件夹的名称,不包含上级路径。
getAbsolutePath()获取文件的绝对路径,与文件是否存在没关系
length() 获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
lastModified()获取最后一次被修改的时间。
文件夹相关:
static File[] listRoots()列出所有的根目录(Window中就是所有系统的盘符)
list() 返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
listFiles() 返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
list(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
listFiles(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date;
public class FileMethod {
public static void main(String[] args) throws IOException {
File[] file = File.listRoots(); System.out.println("所有的盘符是:"); for(File item : file){ System.out.println("\t"+item); } File filename =new File("F:\\Java workspace\\Java"); String[] name = filename.list(); System.out.println("指定文件夹下的文件或者文件夹有:"); for(String item : name){ System.out.println("\t"+item); } File[] f = filename.listFiles(); System.out.println("获得该路径下的文件或文件夹是:"); for(File item : f){ System.out.println("\t"+item.getName()); }
} }
|
目录遍历:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import java.io.File;
public class TraverseOfFile { public static void main(String[] args) { File file = new File("C:\\Users\\renhongchang\\Desktop\\c");
test02(file); }
private static void test01(File file) {
File[] files = file.listFiles();
for (File fil : files){ if (fil.isDirectory()) test01(fil); if (fil.isFile()) System.out.println(fil); } }
private static void test02(File file) { File[] files = file.listFiles();
for (File fil : files){ if (fil.isDirectory()) test02(fil); if (fil.isFile()) fil.delete(); } file.delete(); } }
|