菜鸟浅学Java I/O总结

本文深入浅出地介绍了Java的I/O流,包括流的抽象概念、分类、操作流程以及字节流与字符流的区别。通过实例展示了如何使用FileOutputStream和FileInputStream进行文件的读写,以及如何利用FileWriter和Reader处理字符流。文章还讨论了在开发中选择字节流或字符流的考量因素。

前言:该总结涉及到利用Java I/O流创建文件,以不同的形式读写文件、操作文件。
一.理解Java的IO流
(1)什么是“抽象”?
是在头脑中抽出各种事物与现象的共同特征和属性,舍弃个别特征和属性的过程,在计算机科学总指高级的模型和低级的实体相对。(摘自维基百科)
(2)所以,流就是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行。设备可以是文件,网络,内存等。
(3)流具有方向性

(4)输入流(InputStream/Reader)、输出流(OutputStream/Writer)

(5)IO流是干什么的呢?
操作(创建、读写文件等)输入输出设备(磁盘、打印机、网络等)上的文件

二.IO流分类

从不同的角度对流进行分类
1. 处理的数据单位不同,可分为:字符流,字节流
2.数据流方向不同,可分为:输入流,输出流
3.功能不同,可分为:节点流,处理流
注:是不是对节点流和处理流不理解呢?
节点流:可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流,成为节点流,节点流也被称为低级流(摘自疯狂Java讲义);理解下来就是直接对IO设备上的文件进行直接读写,直接操作文件
处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。处理流也称为高级流。需要去了解装饰器设计模式

三.操作流程
在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:
1.使用File类打开一个文件(类比人要打开电脑上的文件并编辑,就需要知道文件路径和文件名)
2.通过字节流或字符流的子类,指定输出、输入的位置(找到编写的位置)
3.进行读/写操作(我们开始编辑文件)
4.关闭输入/输出(编辑完了,我们将要关闭文件,回到电脑桌面)
*IO操作是资源操作,最后一定不要忘记关闭
四.按数据单位分类来学习(分别用代码实践学习)

字节流
字节流主要是操作byte类型数据,以byte数组为准,主要操作类就是OutputStream、InputStream

字节输出流:OutputStream
OutputStream是整个IO包中字节输出流的最大父类,此类的定义如下:

public abstract class OutputStream extends Object implements Closeable,Flushable

从以上的定义可以发现,此类是一个抽象类,如果想要使用此类的话,则首先必须通过子类实例化对象,那么如果现在要操作的是一个文件,则可以使用:FileOutputStream类。通过向上转型之后,可以为OutputStream实例化

Closeable表示可以关闭的操作,因为程序运行到最后肯定要关闭

Flushable:表示刷新,清空内存中的数据

FileOutputStream类的构造方法如下:

public FileOutputStream(File file)throws FileNotFoundException
(本段内容摘自博客园博主:一直在等
写数据:

package IObyte;
import java.io.*;

public class test1 {
     public static void main(String[] args) throws IOException {
//       对照流程看代码
//      1. 使用File类打开一个文件(需要知道文件路径和文件名,如果没有这个文件,自动创建)
//      2.File.separator可以理解为分隔符
         File f = new File("F:/JavaWorkspce/IOtest/txt"+(String) File.separator+"test1.txt");
//       如果不存在,会在自动创建文件
         OutputStream out=new FileOutputStream(f);
//       要写入文本的内容
         String str = "Hello ;Hello ;Hello ";
//       定义一个数组,用来装入字符
         byte[] b = str.getBytes();
//      (1)一个字节一个字节输出
         for(int i = 0;i<b.length;i++){
             out.write(b[i]);
         }
//      (2)以数组的形式输出,对比这两种情况进行学习
//       out.write(b);//因為是字節流,所以要轉化成字節數組進行輸出
         out.close();
     }
}

采用FileOutputStream类的另一个构造方法:public FileOutputStream(File file,boolean append)throws FileNotFoundException
将append设置为true,在文件末尾追加内容

package IObyte;
//构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容
import java.io.*;
public class test2 {
    public static void main(String[] args) throws IOException{
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test.txt");
        OutputStream out = new FileOutputStream(f,true);
        String str = "\r\nHello ;Hello ;Hello ";
        byte[] b = str.getBytes();
        for(int i=0;i<b.length;i++){
             out.write(b[i]);
        }
        out.close();                
    }
}

字节输入流:InputStream
既然程序可以向文件中写入内容,则就可以通过InputStream从文件中把内容读取进来,首先来看InputStream类的定义:

public abstract class InputStream extends Object implements Closeable

与OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,就用FileInputStream来实现。

观察FileInputStream类的构造方法:

public FileInputStream(File file)throws FileNotFoundException
读文件:

//package IOtest;
//import java.io.*;
//
//public class test3 {
//  public static void main(String[] args) throws IOException {
//      File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test.txt");
//      InputStream in = new FileInputStream(f);
////        byte[] b = new byte[1024];
//      byte[] b = new byte[(int) f.length()];
////        int len = in.read(b);
//      for(int i=0;i<b.length;i++){
//          b[i]=(byte) in.read();
//      }
//      in.close();
//      System.out.println(new String(b));
//  }
//
//}
package IObyte;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class test3 {
    public static void main(String[] args) throws IOException {
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test.txt");
        InputStream in=new FileInputStream(f);
        byte[] b=new byte[1024];
        int len=in.read(b);
        in.close();
        System.out.println(new String(b,0,len));
    }
}

一个字节一个字节读,(不知道文本大小)

package IObyte;
import java.io.*;

public class test4 {
    public static void main(String[] args) throws IOException {
//  文件路径和文件名    
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test.txt");
//      如果没有文件,自动创建文件
        InputStream in = new FileInputStream(f);
//      定义数组,用来放入字节数
        byte[] b = new byte[1024];
//      定义两个变量,一个用来判断文本是否读完,一个用来计算文本的大小
        int temp = 0;
        int len = 0;
//      -1位文件读完的标志
         while((temp=in.read())!=-1){//-1为文件读完的标志
                b[len]=(byte) temp;
                len++;
            }
         in.close();
//       从零开始到结束一次输入
         System.out.println(new String(b,0,len));
    }

}

字符流:
在程序中一个字符等于两个字节,那么java提供了Reader、Writer两个专门操作字符流的类。

字符输出流:Writer
Writer本身是一个字符流的输出类,此类的定义如下:

public abstract class Writer extends Object implements Appendable,Closeable,Flushable

此类本身也是一个抽象类,如果要使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,所以应该使用FileWriter的子类。

FileWriter类的构造方法定义如下:

public FileWriter(File file)throws IOException

字符流的操作比字节流操作好在一点,就是可以直接输出字符串了,不用再像之前那样进行转换操作了。
写数据

package IOchar;
import java.io.*;
// 字符流输出

public class test1 {
    public static void main(String[] args) throws IOException{
//      定义一个File类
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test4.txt");
//      定义一个子类,用来实现Writer类
        Writer wr = new FileWriter(f);
//      定义一个字符串
        String str = "hello ";
//      这个地方以字节流不一样注意区分,字节流这里需要用到str.getbytes(),转换一下;
//      以字符流的形式写到文件上
        wr.write(str);
//      关闭资源操作
        wr.close();
    }

}

追加内容,将append设置为true

package IOchar;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class test2 {
    public static void main(String[] args) throws IOException {
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test4.txt");
        Writer out=new FileWriter(f,true);//追加
        String str="\r\nHello World";
        out.write(str);
        out.close();
    }
}

Reader:

package IOchar;
import java.io.*;
public class test3{
    public static void main(String[] args) throws IOException {
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test4.txt");
        Reader in = new FileReader(f);
//      以数组来过渡,放在这里,随后来读
        char[] c=new char[1024];
        int len=in.read(c);
        in.close();
//             输出数组字符串
        System.out.print(new String(c,0,len));
    } 
}

不知道文本大小的情况下,判断是否读完

package IOchar;
import java.io.*;
public class test4 {
    public static void main(String[] args) throws IOException {
        File f = new File("F:\\JavaWorkspce\\IOtest\\txt\\test4.txt");
        Reader in = new FileReader(f);
        char[] ch = new char[1024];
        int temp = 0;
        int len = 0;
//  表達式
        while((temp=in.read())!=-1){
            ch[len]=(char) temp;
            len++;
            }
        in.close();
        System.out.print(new String(ch,0,len));
        }

}

字节流与字符流有什么区别呢?
在计算机中一个字符(16bit)等于两个字节(8bit),在文件读/写操作中,字节流不需要缓冲区,直接对文件读/写,即使最后不关闭资源(close()方法),也能读/写到数据,字符流是需要缓冲区的,如果最后没有关闭资源(close方法),无法读/写数据的,也可以用flush强制刷新缓冲区,这时也可以输出内容。
那开发中究竟用字节流好还是用字符流好呢?

在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。

如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)。

*以上内容参考大神博客以及相关书籍,有重复的内容也有自己思考的,不对的地方,望各位使劲吐槽

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值