Java IO相关流的学习

Java.io.File类的使用

计算机操作系统中的文件和文件夹
File类代表与平台无关的文件和目录,File 能新建,删除,重命名文件和目录,
但File不能访问文件内容本身,若要访问,需使用输入/输出流

Java IO原理

IO流:用来处理设备之间的数据传输,java.io包下提供了各种“流"类和接口,用以获取不同种类的数据,并通过标准的方法输入或者输出数据

  • IO:输入input【读取外部数据到程序中】、输出output【将程序数据输出到磁盘等存储设备中】
  • 流:通过程序把一个图放到某一个文件夹,把图片转换为一个数据集(例如二进制),把这些数据一点一点传到文件夹,这个传递的过程就很类似水的流动,称这个整体的数据集是一个数据流
流的分类:
  • 按操作数据单位不同分为:字节流(8 bit)、字符流(16 bit)
  • 按数据流的流向不同分为:输入流、输出流
  • 按流的角色的不同分为:节点流、处理流
File类的相关功能
public class TestFileFunction {
    public static void main(String[] args) {
        File f1 = new File("D:/aa/text.txt");//f1表示当前text.txt文件
        File f2 = new File("D:/aa");//f2表示当前文件目录
//        File f3 = new File("D:"+File.separator+"aa\\text.txt");
//        File f4 = new File("D:\\aa","bb:\\text1.txt");
        //注意:\在 文件中是路径的分隔符,但是在java编程中一个\的意思是转义符,在java中\\才是文件的分隔符
        //也可以用File.separator或者 / 作为文件分隔符
        System.out.println(f1.getName());//获取文件名
        System.out.println(f2.getName());//获取当前的文件名称
        File f5 = new File("src/com/zhang/File/TestFileFunction.java");//使用相对路径来创建file对象
        System.out.println(f5.getPath());//获取文件或者文件夹的路径,为new file时写的路径
        System.out.println(f5.getAbsolutePath());//获取当前文件夹的绝对路径
        System.out.println(f1.exists());//判断文件或者文件夹是否存在 true
        System.out.println(f1.canRead()); //判断文件是否可读
        System.out.println(f1.canWrite());//判断文件是否可写
        System.out.println(f1.isFile());//判断当前的file对象是不是文件
        System.out.println(f1.isDirectory());//判断当前的file对象是不是文件夹或者目录
        System.out.println(f1.lastModified());//获取文件最后修改时间,返回的是一个毫秒数
        System.out.println(f1.length());//返回文件的长度,单位为字节数
        File f6 = new File("D:/aa/text3.txt");
        if(!f6.exists()){
            try {
                f6.createNewFile();//创建新的文件
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
//        f6.delete();//删除文件
        File f7 = new File("D:/aa/cc");
        f7.mkdir();//创建单层目录,如果用这方法创建多层目录,就得一层一层的执行mkdir()
        File f8 = new File("D:/aa/dd/ee");
        f8.mkdirs();//创建多层目录
        File f9 = new File("D:/aa");
        String[] s = f9.list();//返回的是当前文件夹的子集名称,包括目录和文件
        for (String s1:s){
            System.out.println(s1);
            //text.txt
        }
        File[] fs = f9.listFiles();//返回的是当前文件夹的子集的路径,包括目录和文件
        for (File ff:fs){
            System.out.println(ff);
            //D:\aa\text.txt
        }
    }
}
文件流:
  • 数据流的读写都是基于文件的操作
  • FileInputStream / FileOutputStream / FileReader / FileWriter
测试文件字节流
public class TestFileByte {
    public static void main(String[] args) {
//       TestFileInputStream.testFileInputStream();
//       TestFileInputStream.testFileOutputStream();
       TestFileByte.copyFile("D:/aa/text1.txt","D:/aa/bb/text1.txt");
    }
    /**
     * 文件流输入流FileInputStream
     */
    public static void testFileInputStream(){
        try {
            FileInputStream in = new FileInputStream("D:/aa/text.txt");//
            int len ;//设置一个读取数据的长度
            byte[] b = new byte[10];//设置一个byte数组接收读取的文件内容
            while((len = in.read(b)) !=-1){
                //in.read()方法有一个返回值,返回值为读取的数据长度,当in.read的返回值为-1时整个文件就读取完毕
                System.out.println(new String(b,0,len));
                //new String(b,0,len),参数1是缓冲数据的数组,参数2是从数组的那个位置开始转化为字符串,参数3是转换的总长度
            }
            in.close();//流在使用完后一定要关闭
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //文件字节输出流FileOutputStream
    public static void testFileOutputStream(){
        try {
            FileOutputStream out = new FileOutputStream("D:/aa/text1.txt");
            String s = "hello world";
            out.write(s.getBytes());//把数据写到内容
            out.flush();//把内存中的数据刷写到硬盘
            out.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //复制文件到指定位置
    public static void copyFile(String inPath,String outPath){
        try {
            FileInputStream in = new FileInputStream(inPath);//读取的源文件
            FileOutputStream out = new FileOutputStream(outPath);//复制到哪里
            byte[] b =new byte[100];
            int len;
            while((len = in.read(b))!=-1){
                out.write(b,0,len);
            }
            out.flush();//把写到内存的数据刷到硬盘
            out.close();
            in.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
测试文件字符流
public class TestFileChar {
    public static void main(String[] args) {
//        TestFileChar.TestFileReader("D:/aa/text.txt");
//        TestFileChar.TestFileWriter("你好","D:/aa/text1.txt");
        TestFileChar.TestCopy("D:/aa/text1.txt","D:/aa/cc/text1.txt");
    }
    //文件字符输入流
    //在读取文件时,必须保证文件已存在
    public static void TestFileReader(String inPath){
        try {
            FileReader fr = new FileReader(inPath);
            char[] c = new char[10];//创建临时存储数据的字符数组
            int len=0;
            while ((len = fr.read(c))!=-1){
                System.out.println(new String(c,0,len));
            }
            fr.close();//关闭流
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //文件字符输出流
    public static void TestFileWriter(String text,String outPath){
        try {
            FileWriter fw = new FileWriter(outPath);
            fw.write(text);//写到内存
            fw.flush();
            fw.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void TestCopy(String inPath,String outPath){
        try {
            FileReader fr = new FileReader(inPath);
            FileWriter fw = new FileWriter(outPath);
            char[] c = new char[100];
            int len;
            while((len = fr.read(c))!=-1){
                fw.write(c,0,len);
            }
            fw.flush();
            fr.close();
            fw.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
缓冲流:
  • 数据流的读写都是基于内存的操作
  • BufferedInputStream / BufferedOutputStream / BufferedReader / BufferedWriter
  • 缓冲流可提高数据读写速度
  • 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出
public class TestBufferedStream {
    public static void main(String[] args) {
        try {
//            TestBufferedStream.testBufferedInputStream();
//            TestBufferedStream.TestBufferedOutputStream();
            TestBufferedStream.TestCopy();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //缓冲字节输入流
    public static void testBufferedInputStream() throws Exception {
        //文件字节输入流对象
        FileInputStream in = new FileInputStream("D:/aa/text.txt");
        //把文件字节输入流放到缓冲字节输入流对象
        BufferedInputStream bi = new BufferedInputStream(in);
        byte[] b = new byte[10];
        int len;
        while ((len = bi.read(b))!=-1){
            System.out.println(new String(b,0,len));
        }
        //关闭时,最晚开的最早关,依次关
        bi.close();
        in.close();
    }
    //缓冲字节输出流
    public static void TestBufferedOutputStream() throws Exception{
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("D:/aa/text2.txt"));
        String s = "hello world";
        bo.write(s.getBytes());//写到内存中
        bo.flush();//刷到硬盘里
        bo.close();
    }
    //缓冲字符流实现文件的复制
    public static void TestCopy() throws Exception{
        //缓冲输入、输出流
        BufferedReader br = new BufferedReader(new FileReader("D:/aa/text.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:/aa/text4.txt"));
        char[] c =new char[100];
        int len = 0;
        while ((len=br.read(c))!=-1){
            bw.write(c,0,len);
        }
        bw.flush();
        bw.close();
        br.close();
    }
}
标准输入输出流、数据流
  • 标准输入输出流:System.in和System.out分别代表了系统标准的输入输出设备
  • System.in的类型是InputStream,System.out的类型是PrintStream,其是OutputStream的子类FileOutputStream的子类
  • 数据流:DataOutputStream、DataInputStream
  • 方便操作Java语言的基本数据类型的数据
public class TestSystem {
    public static void main(String[] args) {
        try {
//            TestSystem.testSystemIn();
//            TestSystem.testDataOutputStream();
            TestSystem.testDataInputStream();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //标准的输入、输出流
    public static void testSystemIn() throws Exception{
        //创建一个接收键盘数据的流
        InputStreamReader in = new InputStreamReader(System.in);
        OutputStreamWriter out = new OutputStreamWriter(System.out);
        //把输入流放到缓冲流里
        BufferedReader br = new BufferedReader(in);
        BufferedWriter bw = new BufferedWriter(out);
        String str ="";//定义一个临时接收数据的字符串
        while ((str = br.readLine())!=null){
            System.out.println(str);
        }
        br.close();
        in.close();
    }

    /**
     * 数据流
     * 数据输出流
     * 用数据输出流写到文件中的基本数据类型的数据,是乱码的,不能之间辨认出来,需要数据输入流来读取
     * @throws Exception
     */
    public static void testDataOutputStream() throws Exception{
        DataOutputStream out = new DataOutputStream(new FileOutputStream("src/com/zhang/File/text2.txt"));
//        out.writeBoolean(true);
//        out.writeInt(1);
        out.writeDouble(1.4444d);
        out.flush();
        out.close();
    }
    /**
     * 数据输入流
     * 用数据输出流写到文件中的基本数据类型是乱码的,不能直接辨认出来
     * 用数据输入流读取数据输出流写到文件中的数据时,要保证使用和当时写的数据类型一致来读取
     * eg:写的时候是writeDouble,读的时候就是readDouble
     * @throws Exception
     */
    public static void testDataInputStream() throws Exception{
        DataInputStream in = new DataInputStream(new FileInputStream ("src/com/zhang/File/text2.txt"));
        System.out.println(in.readDouble());
        in.close();
    }
}
转换流
  • 转换流把字节流转换为字符流
  • InputStreamReader、OutputStreamWriter
  • 当字节流中的数据都是字符时,使用转换流转为字符流出来效果更高
  • 所有的文件都是有编码格式的
  • TXT,Java文件一般有三种编码 :IS08859—1 西欧编码,是纯粹英文编码,不适应汉字
  • GBK,UTF-8,这两种编码适用于中文和英文
public class TestChangeStream {
    public static void main(String[] args) {
        try {
//            TestChangeStream.TestInputStreamReader();
            TestChangeStream.TestOutputStreamWriter();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //转换输入流InputStreamReader
    //注意,在转换字符时,设置的字符集编码要与读取的文件的数据编码一致,否则会出现乱码
    public static void TestInputStreamReader() throws Exception{
        FileInputStream fs = new FileInputStream("src/com/zhang/File/text.txt");
//        FileInputStream fs = new FileInputStream("D:/aa/text.txt");
        //把字节流转换为字符流
        InputStreamReader in = new InputStreamReader(fs,"UTF-8");//参数1是字节流,参数2是编码
//        InputStreamReader in = new InputStreamReader(fs,"GBK");//编码不同会造成乱码
        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
    public static void TestOutputStreamWriter() throws Exception{
        FileOutputStream fo = new FileOutputStream("src/com/zhang/File/text1.txt");
        OutputStreamWriter ow = new OutputStreamWriter(fo,"UTF-8");
        ow.write("谢谢你");
        ow.flush();
        ow.close();
        fo.close();
    }
}
对象流
  • 需要做保存对象到硬盘(对象的持久化)和对象的网络传输,就产生了对象的输入和输出流
  • ObjectInputStream、ObjectOutputStream
  • 用于存储和读取数据的处理流,可把java中的对象写到数据源中,也能把对象从数据源中还原回来
  • 序列化(Serialize) :用ObjectOutputStream类将一个Java对象写进IO流中
  • 反序列化(Deserialize) :用ObjectInputStream类从IO流中恢复该Java对象
  • ObjectInputStream、ObjectOutputStream不能序列化static和transient修饰的成员变量
  • 系列化和反序列化对针对的是对象的各种属性,不包括类的属性
对象的序列化

凡是实现Serializable接口的类都有一个表示序列化版本标书符的静态变量
若某一个类实现了Serializable接口,该类的对象就是可序列化的

/**
 - 序列化与反序列化
 - 注意:对象的序列化和反序列化使用的类要严格一致,类名,包名,类机构等待都要一致
 */
public class TestObjectStream {
    public static void main(String[] args) {
        try {
//            TestObjectStream.testSerialize();
            TestObjectStream.testDeserialize();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //对象的序列化
    public static void testSerialize() throws Exception{
        //定义对象的输出流,把对象的序列化之后的流放到指定的文件中
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("src/com/zhang/File/text3.txt"));
        Person p = new Person(4,"小明");
        out.writeObject(p);
        out.flush();
        out.close();
    }
    public static void testDeserialize() throws Exception{
        //创建对象输入流,从指定的文件中把对象序列化后的流读取出来
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("src/com/zhang/File/text3.txt"));
        Object obj = in.readObject();
        Person p = (Person)obj;
        System.out.println(p.age+"   "+p.name);
        in.close();
    }
}
//可以序列化和反序列化的对象
class Person implements Serializable{
    /**
     * 一个表示序列化版本标识符的静态变量
     * 用来表明类的不同版本间的兼容性
     */
    private static final long serialVersionUID = 1L;
    public int age;
    public String name;
    public Person() {
    }
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
随机存取文件流
  • 程序可以直接跳到文件的任意地方来读写文件
  • RandomAccessFile类
public class TestRandomStream {
    public static void main(String[] args) {
        try {
//            TestRandomStream.testRandomAccessFileRead();
            TestRandomStream.testRandomAccessFileWrite();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //随机读文件
    public static void testRandomAccessFileRead() throws Exception{
        /**
         * RandomAccessFile的构造有两个参数,参数1是读写的文件路径,参数2是指定RandomAccessFile的访问模式
         * r:以只读方式打开
         * rw:打开以便读取和写入
         * rwd:打开以便读取和写入,同步文件内容的更新
         * rws:打开以便读取和写入,同步文件内容和元数据的更新
         */
        RandomAccessFile ra = new RandomAccessFile("src/com/zhang/File/text.txt","r");
//        ra.seek(0);
        ra.seek(8);//设置读取文件的起始点
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = ra.read(b))!=-1){
            System.out.println(new String(b,0,len));
        }
        ra.close();
    }
    //随机写
    public static void testRandomAccessFileWrite() throws Exception{
        RandomAccessFile ra = new RandomAccessFile("src/com/zhang/File/text.txt","rw");
        //注意:若在文件开头或中间的某位置写,就会用写的内容覆盖掉等长的原内容
        ra.seek(ra.length());//设置写的起点,ra.length()代表从文件的最后结尾写,也就是文件的追加
        ra.write("你好啊".getBytes());
        ra.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值