java的IO流-行云流水篇(学习笔记全)
先来看一下java中IO流 的图谱
一、File类
File类能代表与平台 无关的文件和目录。File能新建、删除、重命名文件和目录,但是不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入输出流。
File类常用方法:
大致有以下几种:
- isDirectory() 是否为文件夹
- isFile() 是否为文件
- getPath() 得到file的路径
- getName() 得到最后一层的名字
- getParent() 得到去掉最后一层的路径
- getParentFile() 得到父类路径的新文件
- renameTo() 改名
- mkdir() 创建新文件夹,只能创建一层
- mkdirs() 创建新文件夹,可以多层
- createNewFile() 创建新文件,只能一层
- exists() 路径(文件或者文件夹)是否存在
- delete() 删除文件或者目录(为空的目录)
- list() 返回该路径下文件或者文件夹的名字数组
- listFiles() 返回该路径下文件或者文件夹组成的File数组
- separator 代替文件或文件夹路径的斜线或反斜线,防止跨平台出现错误
递归遍历文件夹,输出路径下的所有文件和文件夹
public class IOTest {
public static void main(String[] args) {
File file=new File("E:\\mabook\\Git_code");
IOTest ioTest=new IOTest();
ioTest.recursion(file);
}
public void recursion(File file){
if (file.isFile()){
System.out.println("文件--->"+file.getAbsolutePath());
}else{
System.out.println("文件夹->"+file.getAbsolutePath());
File[] fs=file.listFiles();
for (File ff:fs){
recursion(ff);
}
}
}
}
二、文件字节流&字符流
文件字节流较为通用,可以用来操作字符的文档,还可以操作任何的其他类型文件(图片,压缩包等等)
输入流 FileInputStream,FileReader
输出流 FileOutputStream,FileWriter
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest(); ioTest.copyFile("E:\\mabook\\Git_code\\demo\\README.md","E:\\mabook\\Git_code\\demo\\README10086.md");
//输出文件路径的目录结构确保真实存在,不会自动建文件夹目录
}
/**
* 文件字节流操作
*/
public void copyFile(String inPath,String outPath){
try{
FileInputStream in=new FileInputStream(inPath);
FileOutputStream out=new FileOutputStream(outPath);
byte[] b=new byte[127];
int len=0;
while ((len=in.read(b))!=-1){
out.write(b,0,len);
}
out.flush();
out.close();
in.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* 文件字符流操作
* @param inPath 被复制文件路径
* @param outPath 复制后的文件路径
*/
public void copyFile2(String inPath,String outPath){
try{
FileReader in=new FileReader(inPath);
FileWriter out=new FileWriter(outPath);
char[] c=new char[100];
int len=0;
while ((len=in.read(c))!=-1){
out.write(c,0,len);
}
out.flush();
out.close();
in.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
flush()和write()方法有什么区别
java在使用流时,都会有一个缓冲区,按一种它认为比较高效的方法来发数据:把要发的数据先放到缓冲区,缓冲区放满以后再一次性发过去,而不是分开一次一次地发.而flush()表示强制将缓冲区中的数据发送出去,不必等到缓冲区满.所以如果在用流的时候,没有用flush()这个方法,很多情况下会出现流的另一边读不到数据的问题,特别是在数据特别小的情况下.
三、缓冲流
缓冲流即先把数据缓存到内存里,在内存中做io操作,速度比上面的的直接操作能快上万倍。
输入流 BufferedInputStream,BufferedReader
输出流 BufferedOutputStream,BufferedWriter
关闭流的顺序:遵循最先开的最晚关
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest();
try {
ioTest.bufferedTest("E:\\Desktop\\git\\java.md","E:\\Desktop\\git\\copy_java.md");
} catch (Exception e) {
e.printStackTrace();
}
}
public void bufferedTest(String inPath,String outPath) throws Exception{
//文件字节输入流对象
FileInputStream in=new FileInputStream(inPath);
//创建字节输出流对象
FileOutputStream out=new FileOutputStream(outPath);
//把文件字节输入流放到缓冲字节输入流对象
BufferedInputStream br=new BufferedInputStream(in);
//把字节输出流对象放到缓冲字节输流流中
BufferedOutputStream bo=new BufferedOutputStream(out);
byte[] b=new byte[1024];
int len=0;
while ((len=br.read(b))!=-1){
bo.write(b,0,len);
}
bo.flush();
bo.close();
br.close();
in.close();
out.close();
}
}
缓冲字节流跟字符流基本一样,使用FileReader,FileWriter,BufferedReader,BufferedWriter替换即可。
三、转换流
输入流 InputStreamReader
输出流 OutputStreamWriter
为啥使用转换流?
转换流提供了字节流和字符流之间的装换,如果我们程序使用字节流在操作文件时,文件中存在大量字符(例如是txt,word文件等等),那么效率大打折扣,所以需要使用到转换流,将字节流转换为字符流
注意点?
所有文件都有编码格式,一般有
ISO8859-1西欧编码,不适应中文
GBK和utf-8,使用于中文和英文
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest();
try {
ioTest.testInputStreamReader("E:\\Desktop\\笔记\\java待探究.md");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 转换输入流
* @throws Exception
*/
public void testInputStreamReader(String inPath) throws Exception{
FileInputStream fs=new FileInputStream(inPath);
InputStreamReader in=new InputStreamReader(fs,"UTF-8");
char[] c=new char[100];
int len=0;
while ((len=in.read(c))!=-1){
System.out.println(new String(c,0,len));
}
in.close();
fs.close();
}
}
转换输出流也一样,参考前面代码举一反三(OutputStreamWriter)
四、标准输入输出流
System.in和System.out分别代表了系统标准的输入输出设备,默认键盘和显示器
System.in的类型是InputStream
System.out的类型是PrintStream,
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest();
try {
ioTest.testSystemIn();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 标准输入流
* 程序功能:
* 将键盘输入流的内容写入到abc.txt文件中,输入finish结束输入
*/
public void testSystemIn() throws Exception{
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
BufferedWriter bw=new BufferedWriter(new FileWriter("E:\\abc.txt"));
String str="";
while ((str=br.readLine())!=null){
if(str.equals("finish")){
break;
}
bw.write(str);
}
bw.flush();
bw.close();
br.close();
isr.close();
}
}
五、简单了解流(打印流、数据流)
开发中比较少用到,简单了解即可
字节打印流 PrintStream,字符打印流 PrintWriter,其输出不会抛出异常 ,都有自动flush功能
数据输出流 DataOutputStream,数据输入流 DataInputStream
六、对象流
ObjectInputStream和ObjectOutputStream,用于存储读取对象的处理流。强大之处就是可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。
**序列化和反序列化:**java对象流在网络传输中是以二进制传输的,使用序列化和反序列化可以使得对象转化成二进制的字节流,使其能在网络中中传输,最后在另一端将流通过反序列化重新恢复为对象。
//IOTest.java
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest();
try {
ioTest.testSerialize();
ioTest.testDeserialize();
} catch (Exception e) {
e.printStackTrace();
}
}
public void testSerialize() throws Exception{
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("E:\\abc.txt"));
Person person=new Person();
person.name="yuec1998";
person.age=21;
out.writeObject(person);
out.flush();
out.close();
}
public void testDeserialize() throws Exception{
ObjectInputStream in=new ObjectInputStream(new FileInputStream("E:\\abc.txt"));
Person person=(Person)in.readObject();
System.out.println(person.name+":"+person.age);
}
}
//Person.java
public class Person implements Serializable {
public static final long serialVersionUID=1L;
String name;
Integer age;
}
七、随机存取流
RandomAccessFile类支持“随机访问“的方式,程序可以直接跳转到文件的任意地方来读写文件
long getFilePointer():获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到pos位置
public class IOTest {
public static void main(String[] args) {
IOTest ioTest=new IOTest();
try {
ioTest.testRandomAccessFileRead("E:\\abc.txt");
ioTest.testRandomAccessFileWrite("E:\\abc.txt");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 随机读
* @param inPath
* @throws Exception
*/
public void testRandomAccessFileRead(String inPath) throws Exception{
//参数一:读写文件的路径
//参数二:访问模式(r:只读 rw:打开以便读写)
RandomAccessFile ra=new RandomAccessFile(inPath,"r");
ra.seek(5);//指针
byte[] b=new byte[1024];
int len =0;
while ((len=ra.read(b))!=-1){
System.out.println(new String(b,0,len));
}
ra.close();
}
/**
* 随机写
* @param outPath
* @throws Exception
*/
public void testRandomAccessFileWrite(String outPath) throws Exception{
RandomAccessFile ra=new RandomAccessFile(outPath,"rw");
ra.seek(0);
/**
* 设置写的起始点,0表示文件内容的开头,如果在开头或中间则会发生内容覆盖
* ra.seek(0);
* 文件末尾追加
* ra.seek(ra.length());
*/
ra.write("aaa11111".getBytes());
ra.close();
}
}