Java基础-IO流

本文详细介绍了Java.IO流的使用,包括File类、字节流、字符流、节点流和处理流的概念。通过实例演示了文件的读写、文件操作、目录遍历、文件重命名、文件属性判断等功能,并探讨了字符编码和对象序列化。同时,展示了Buffer流的使用,提高了文件操作的效率。此外,还涉及到了随机访问文件流的运用,以及对图片加密解密的实现。
摘要由CSDN通过智能技术生成

IO流

  • 解决数据的输入输出问题

File类的使用

  • java.io.File类:文件和文件目录路径的抽象表示形式
  • File对象可以作为参数传递给流的构造器
package file;

import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/*
File类的使用
1.File类的一个对象,代表一个文件或者一个文件目录(文件夹)
路径分隔符和系统有关:
windows和DOS系统默认使用"\"来表示
UNIX和URL使用"/"来表示
java中提供了一个常量:public static final String separator,File.separator根据系统不同动态提供分隔符

File的常用方法:
public String getAbsolutePath():获取绝对路径
public String getPath():获取路径
public String getName():获取名称
public String getParent():获取上层文件目录路径,若无,返回null
public long length():获取文件长度(字节数),不能获取目录的长度
public long lastModified():获取最后一次的修改时间,毫秒值

以下方法适用文件目录:
public String[] list():获取指定目录下的所有文件或文件目录的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组

 */
/*
    public boolean renameTo(File dest):把文件重命名为指定的文件路径
    比如:file1.renameTo(file2):
    要想返回true,要保证file1在硬盘中存在,且file2不能在硬盘中存在
     */
/*
    public boolean isDirectory():判断是否是文件目录
    public boolean isFile():判断是否是文件
    public boolean exists():判断是否存在
    public boolean canRead():判断是否可读
    public boolean canWrite():判断是否可写
    public boolean isHidden():判断是否隐藏
    
    创建硬盘中对应的文件或文件目录:
    public boolean createNewFile():创建文件,若文件不在则不创建,返回false
    public boolean mkdir():创建文件目录,若文件目录存在则不创建,如果此文件目录上层文件目录不存在,则不创建
    public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建

    删除硬盘中的文件或文件目录:
    public boolean delete():删除文件或者文件夹
    删除注意事项:java中的删除不走回收站
     */
public class FileTest {

    /*
    如何创建File的实例化:

    1.相对路径:相较于某个路径下指明的路径

    2.绝对路径:包含盘符在内的文件或文件目录的路径
     */
    @Test
    public void test(){
        //构造器1:创建文件
        File file = new File("hello.txt");//相对于当前的module
        File file1 = new File("D:\\Java\\exercise2\\he.txt");//绝对路径

        System.out.println(file);
        System.out.println(file1);

        //构造器2:创建exercise2文件夹
        File file2 = new File("D:\\Java", "exercise2");
        System.out.println(file2);

        //构造器3:exercise2下的文件
        File file3 = new File(file2, "hi,txt");
        System.out.println(file3);
    }
    @Test
    public void test1(){
        File file = new File("hello.txt");
        File file1 = new File("D:\\io\\hi.txt");

        System.out.println(file.getAbsolutePath());
        System.out.println(file.getPath());
        System.out.println(file.getName());
        System.out.println(file.getParent());//获取上层文件目录,无返回null
        System.out.println(file.length());
        System.out.println( new Date(file.lastModified()));//最近修改时间

        System.out.println("===============");

        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getPath());
        System.out.println(file1.getName());
        System.out.println(file1.getParent());
        System.out.println(file1.length());
        System.out.println(file1.lastModified());
    }
    @Test
    public void test3(){
        //找文件名
        File file = new File("D:\\Java\\exercise2\\src");
        String[] list = file.list();
        for (String s : list) {
            System.out.println(s);
        }

        //找完整名包括路径
        File[] files = file.listFiles();
        for (File file1 : files) {
            System.out.println(file1);
        }
    }

    /*
    public boolean renameTo(File dest):把文件重命名为指定的文件路径
    比如:file1.renameTo(file2):
    要想返回true,要保证file1在硬盘中存在,且file2不能在硬盘中存在
     */
    @Test
    public void test4(){
        File file1 = new File("hello.txt");
        File file2 = new File("D:\\io\\hi.txt");

        boolean renameTo = file1.renameTo(file2);
        System.out.println(renameTo);
    }

    /*
    public boolean isDirectory():判断是否是文件目录
    public boolean isFile():判断是否是文件
    public boolean exists():判断是否存在
    public boolean canRead():判断是否可读
    public boolean canWrite():判断是否可写
    public boolean isHidden():判断是否隐藏
     */
    @Test
    public void test5(){
        File file = new File("hello.txt");

        System.out.println(file.exists());//先判断在不在
        System.out.println(file.isFile());
        System.out.println(file.isDirectory());
        System.out.println(file.isHidden());
        System.out.println(file.canRead());
        System.out.println(file.canWrite());
    }

    /*
    创建硬盘中对应的文件或文件目录:
    public boolean createNewFile():创建文件,若文件不在则不创建,返回false
    public boolean mkdir():创建文件目录,若文件目录存在则不创建,如果此文件目录上层文件目录不存在,则不创建
    public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建

    删除硬盘中的文件或文件目录:
    public boolean delete():删除文件或者文件夹
    删除注意事项:java中的删除不走回收站
     */
    @Test
    public void test6() throws IOException {
        //文件的创建
        File file = new File("hi.txt");
        if (!file.exists()){
            file.createNewFile();
            System.out.println("创建成功");
        }else{//文件存在
            file.delete();
            System.out.println("删除成功");
        }

        //文件目录的创建
        File file1 = new File("D:\\io\\io1\\io2");

        boolean mkdir = file1.mkdir();//不会创建上层目录
        if (mkdir){
            System.out.println("创建成功1");
        }

        File file2 = new File("D:\\io\\io1\\io2");
        boolean mkdirs = file2.mkdirs();//会创建上层目录
        if (mkdirs) {
            System.out.println("创建成功2");
        }
    }
}

练习题

package file;

import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;

public class FileExercise {
    @Test
    public void test() throws IOException {
        File file = new File("D:\\io\\io1\\hello.txt");
        //创建一个与file同目录下的另外一个文件,文件名为:haha.txt
        File destFile = new File(file.getParent(), "haha.txt");//内存层面的
        boolean newFile = destFile.createNewFile();
        if (newFile){
            System.out.println("创建成功");
        }
    }

    //判断指定目录下是否有后缀名为.jpg的文件,如果有就输出该文件名称
    @Test
    public void test1(){
        File file = new File("D:\\io\\io1");
        String[] list = file.list();
        for (String s : list) {
            if (s.endsWith("jpg")){
                System.out.println(s);
            }
        }
    }

    //递归:文件目录
    //打印除指定目录所有文件名称,包含子文件目录中的文件
    public static void printSubFile(File dir){
        //打印目录子文件
        File[] subFiles = dir.listFiles();

        for (File f : subFiles) {
            if (f.isDirectory()){//判断是否是文件目录
                printSubFile(f);
            }else {//如果是文件
                System.out.println(f.getAbsolutePath());
            }
        }
    }

    //求指定目录所在空间的大小
    public long getDirectorySize(File file){
        //file是文件,直接返回file.length()
        //file是文件目录,把它的下一级所有大小加起来就是总大小
        long size = 0;
        if (file.isFile()){
            size += file.length();
        }else {
            File[] all = file.listFiles();//获取下一级
            //累加all[i]的大小
            for (File f : all) {
                size += getDirectorySize(f);//f的大小
            }
            System.out.println(size);
        }
        return size;
    }
    //测试
    public static void main(String[] args) {
        //File dir = new File("D:\\Java\\exercise2\\src");
        //printSubFile(dir);
        File file = new File("D:\\io\\io1");
        FileExercise fileExercise = new FileExercise();
        fileExercise.getDirectorySize(file);
    }
}

IO流原理及流的分类

  • 处理设备之间的数据传输,以“流”的方式进行数据输入/输出

  • 输入:读取外部数据(文件,网络)到程序(内存)当中,

  • 输出:将程序(内存)数据输出到磁盘、光盘等存储设备中

流的分类

  • 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)

  • 按数据流的流向不同分为:输入流,输出流

  • 按流的角色不同分为:节点流(文件–内存,作用在文件上的流),处理流(在节点流上包了一层流,将节点流的对象作为属性传输)

  • 字符流不能处理图片文件的测试

  • 抽象基类字节流字符流
    输入流InputStream后缀Reader
    输出流OutputStream后缀Writer

在这里插入图片描述

流的体系结构

在这里插入图片描述

  • //1.File类的实例化

    //2.FileReader流的实例化

    //3.读入的操作

    //4.资源的关闭

package io;

import org.testng.annotations.Test;

import java.io.*;

/*
一、流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色不同分为:节点流,处理流

二、流的体系结构
二、流的体系结构
抽象基类            节点流(文件流)                                缓冲流(处理流的一种)
InputStream       FileInputStream(read(byte[] buffer))         BufferInputStream(read(byte[] buffer) 
OutputStream      FileOutputStream(write(byte[] buffer,0,len)) BufferOutputStream(write(byte[] buffer,0,len)/flush()
Reader            FileReader(read(char[] cbuf))                BufferReader(read(char[] cbuf)/readline())
Writer            FileWriter(write(char[] cbuf,0,len))         BufferWriter(char[] cbuf,0,len) /flush()

缓存流中都有flush()操作,将数据刷出去
 */
public class FileReaderWriterTest {

    /*
    将exercise2下的hello.txt文件内容读入程序中,并输出到控制台
    1.read():返回读入的一个字符,如果达不到文件末尾,返回-1
    2.抛出异常的方式不可取,会造成流的关闭操作不执行,造成内存的浪费,
      用try-catch-finally方法:ctrl+alt+t
    3.读入的文件一定要存在,否则就会报:FileNotFoundException异常
     */
    @Test
    public void testFileReader() {
        FileReader fr = null;
        try {
            //main方法里面是相较于工程下,而test是相较于模块下
            //1.实例化File类的对象,指明要操作的文件
            File file = new File("hello.txt");//相较于当前module
            //2.提供具体的流,流的实例化
            fr = new FileReader(file);

            //3.数据的读入过程
            //read():返回读入的一个字符,如果达不到文件末尾,返回-1
            int data;
            while((data = fr.read())!=-1){
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

        //4.流的关闭操作
        //物理连接,如数据库连接,输入输出流,Socket连接需要手动关闭,避免内存泄漏
        try {
            if (fr != null)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

    //对read()方法的升级,read的重载方法
    @Test
    public void test1()  {
        FileReader fr = null;
        try {
            //1.File类的实例化
            File file = new File("hello.txt");
            //2.FileReader流的实例化
            fr = new FileReader(file);
            //3.读入的操作
            //read(char[] cbuffer):返回每次读入cubffer数组中的字符个数,如果到达文件末尾返回-1
            // 如果是字节类型,就是byte类型
            char[] cbuf = new char[5];//返回读入的5个字符
            int len;
            while((len = fr.read(cbuf)) != -1){
                //方式一
                for (int i = 0; i < len; i++) {//i<len:每次读进去几个就写几个
                    System.out.print(cbuf[i]);
                }
                //方式二(不推荐)
//                String str = new String(cbuf, 0, len);
//                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        //4.资源的关闭
        try {
            if (fr != null)
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }


    /*
    从内存中写出数据到硬盘的文件里
    说明:
    1.输出操作,对应的File文件可以不存在,并不会报异常
    2.
      如果不存在,在输出的过程中,会自动创建此文件
      如果存在,
      如果使用的构造器是:FileWriter(file,false)/FileWriter(file):对原文件覆盖
      如果使用的构造器是:FileWriter(file,true),对原文件续写
     */
    //写出
    @Test
    public void testFileWriter()  {
        FileWriter fw = null;
        try {
            //1.提供file类的对象,指明写出到的文件
            File file = new File("hello1.txt");

            //2.提供FileWriter的对象,用于数据的写出
            fw = new FileWriter(file);

            //3.写出的操作
            fw.write("I have a dream" +"\n");
            fw.write("you have a dream");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

        //4.资源的关闭
        try {
            if (fw != null)
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

    @Test
    public void testFileReaderFileWriter() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类的对象,指明读入和写出的文件
            File file1 = new File("hello.txt");
            File file2 = new File("hello2.txt");
            //2.创建输入流和输出流的对象
            fr = new FileReader(file1);
            fw = new FileWriter(file2);
            //3.数据的读入和写出
            char[] cbuf = new char[5];
            int len;//记录每次读入到cubf数组中的字符的个数
            while ((len = fr.read(cbuf)) != -1){
                for (int i = 0; i < len; i++) {
                    System.out.print(cbuf[i]);
                }
                //每次写出len个字符
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        //4.关闭资源
        try {
            if (fr != null)
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (fw != null)
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package io;

import org.testng.annotations.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
测试FileInputStream和FileOutputStream的使用
结论:
对于文本文件(txt,java,c,cpp),使用字符流处理
对于非文本文件(jpg,mp3,mp4,doc,ppt,avi),使用字节流处理

 */
public class FileInputOutputStreamTest {

    @Test
    public void testFileInputStream()  {
        FileInputStream fis = null;
        try {
            //1.创建文件
            File file = new File("hello.txt");

            //2.创建流
            fis = new FileInputStream(file);

            //3.读数据
            byte[] buffer = new byte[5];
            int len;
            while((len = fis.read(buffer)) != -1){
                String str = new String(buffer, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        //4.关闭资源
        try {
            if (fis !=null)
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}


  • Buffer流的使用
package io;

import org.testng.annotations.Test;

import java.io.*;

public class BufferTest {
    //实现文件复制的方法
    public void copyFileWithBuffered(String srcPath,String destPth)  {
        BufferedOutputStream bos = null;
        try {
            //1.造文件
            File srcFile = new File(srcPath);
            File destFile = new File(destPth);
            //2.造流
            //2.1 造节点流
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            BufferedInputStream bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.复制的细节:读入、写出
            byte[] buffer = new byte[1024];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        //4.关闭资源
        //关闭外层流的同时,内层流也会自动关闭
        try {
            if (bos != null)
                bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

    //使用BufferReader和BufferWriter实现文本文件的复制

    @Test
    public void test1() {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //1.造文件造流,造缓冲流
            br = new BufferedReader(new FileReader(new File("dbvp.txt")));
            bw = new BufferedWriter(new FileWriter(new File("dbvp1.txt")));

            //2.读写操作
            //方式一
//            char[] cbuf = new char[1024];
//            int len;
//            while ((len = br.read(cbuf)) != -1){
//                bw.write(cbuf,0,len);
//            }

            //方式二
            String data;
            while((data = br.readLine()) != null){
                bw.write(data + "\n");//data中不包含换行符,得自己加或者加:newLine();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

        //3.关闭资源
        try {
            if (bw != null)
            bw.close();
            if (br != null)
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

练习题
  • 对图片的加密解密操作
    对数组buffer的数据异或了5,就是加密
    对数组buffer的数据异或了5,再异或5就可以解密
package io;

import org.testng.annotations.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
对图片的加密解密操作
对数组buffer的数据异或了5,就是加密
对数组buffer的数据异或了5,再异或5就可以解密
 */
public class ExerciseTest {
    //图片的加密
    @Test
    public void test(){
        FileOutputStream fos = null;
        try {
            FileInputStream fis = new FileInputStream(new File("llyy.jpg"));
            fos = new FileOutputStream(new File("llyysecret.jpg"));

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer))!= -1){
                //对字节数据进行修改
                //错误写法:没有对buffer中数据进行修改
    //            for (byte b : buffer) {
    //                b = (byte) (b ^ 5);
    //            }
                //正确:
                for (int i = 0; i < len; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5);
                }
                fos.write(buffer,0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (fos !=null)
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

    //解密
    //对数组的数据异或了5,再异或5就可以解密
    @Test
    public void test1(){
        FileOutputStream fos = null;
        try {
            FileInputStream fis = new FileInputStream(new File("llyy.jpg"));
            fos = new FileOutputStream(new File("llyy1.jpg"));

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer))!= -1){
                //对字节数据进行修改
                //错误写法:没有对buffer中数据进行修改
                //            for (byte b : buffer) {
                //                b = (byte) (b ^ 5);
                //            }
                //正确:
                for (int i = 0; i < len; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5 ^5);
                }
                fos.write(buffer,0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (fos !=null)
                fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

  • 获取文本上每个字符出现的次数(遍历文本每一个字符,字符及出现的次数保存在Map中:将Map中数据写入文件)
package io;

import org.testng.annotations.Test;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
获取文本上字符出现的次数,把数据写入文件

思路:
1.遍历文本每一个字符
2.字符出现的次数存在Map中

Map<Character,Integer> map = new HashMap(Character,Integer>();
map.put('a',18);
map.put('你',2);
3.把map中的数据写入文件

 */
public class ExerciseTest1 {
    @Test
    public void test(){
        FileReader fr = null;
        BufferedWriter bw = null;
        try {
            //1.创建map集合
            HashMap<Character, Integer> map = new HashMap<>();
            //2.遍历每一个字符,每一个字符出现的次数放到map中
            fr = new FileReader("dbvp.txt");
            int c = 0;
            while ((c = fr.read())!= -1){
                //int 还原为char
                char ch = (char) c;
                //判断char是否在map中第一次出现
                if (map.get(ch) == null){//或者contains()
                    map.put(ch,1);
                }else {
                    map.put(ch,map.get(ch)+1);
                }
            }
            //3.把map中数据存在文件count.out
            //3.1创建writer
            bw = new BufferedWriter(new FileWriter(new File("wordcount.txt")));
            //3.2 遍历map,再写入数据
            Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
            for (Map.Entry<Character, Integer> entry : entrySet) {
                switch (entry.getKey()){
                    case ' ':
                        bw.write("空格=" + entry.getValue());
                        break;
                    case '\t'://t表示tab键字符
                        bw.write("tab键=" + entry.getValue());
                        break;
                    case 'r':
                        bw.write("回车=" + entry.getValue());
                        break;
                    case '\n':
                        bw.write("换行=" +entry.getValue());
                        break;
                    default:
                        bw.write(entry.getKey() + "=" + entry.getValue());
                }
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (fr != null)
            fr.close();
            if (bw!=null)
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

转换流

1.转换流:(字符流)
输入的字节流(byte)转换成字符流(char):InputStreamReader
输入的字符流(char)转换成字节流(byte):OutputStreamWriter

2.解码:字节、字节数组 —> 字符数组,字符串
编码:字节、字节数组 —> 字符数组,字符串

3.字符集
1.ASCII:标准信息交换码,用一个字节的7位可以表示
2.IS08859-1:拉丁码表,欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表,最多两个字节编码所有字符
GBK:中文编码表升级
Unicode:国际标准码,为每个字符分配唯一的字符码
UTF-8:变长的编码方式,可用1-4个字节表示一个字符

在这里插入图片描述

  • Unicode字符集只是定义了字符的集合和唯一编码,
    Unicode编码则是对UTF-8、UTF-16等具体编码方案的统称
package io;

import org.testng.annotations.Test;

import java.io.*;

/*
处理流的一种:
1.转换流:(字符流)
输入的字节流(byte)转换成字符流(char):InputStreamReader
输出的字符流(char)转换成字节流(byte):OutputStreamWriter

2. 解码:字节、字节数组 ---> 字符数组,字符串
   编码:字节、字节数组 ---> 字符数组,字符串

3.字符集
1.ASCII:标准信息交换码,用一个字节的7位可以表示
2.IS08859-1:拉丁码表,欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表,最多两个字节编码所有字符
GBK:中文编码表升级
Unicode:国际标准码,为每个字符分配唯一的字符码
UTF-8:变长的编码方式,可用1-4个字节表示一个字符

Unicode字符集只是定义了字符的集合和唯一编码,
Unicode编码则是对UTF-8、UTF-16等具体编码方案的统称
 */
public class InputStreamReaderTest {
    @Test
    public void test() throws IOException {
        File file = new File("dbvp.txt");
        FileInputStream fis = new FileInputStream(file);
        System.out.println(file.getAbsolutePath());
        //InputStreamReader isr = new InputStreamReader(fis);//系统默认的字符集,UTF-8
        //参数2指明了字符集,具体使用取决于文件保存时使用的字符集
        java.io.InputStreamReader isr = new java.io.InputStreamReader(fis, "UTF-8");

        char[] cbuf = new char[20];
        int len;
        while ((len = isr.read(cbuf))!=-1){
            String str = new String(cbuf, 0, len);
            System.out.print(str);
        }
        isr.close();

    }
}

其他流(输入输出流、打印流)

package io;

import org.testng.annotations.Test;

import java.io.*;

/*
System in :标准输入流,默认从键盘输入。类型是InputStream
System out:标准的输出流,默认从控制台输出,类型是PrintStream,是OutputStream的子类


 */
public class OtherStreamTest {
    /*
    练习题:
    从键盘输入字符串,要求将读取到的整行字符串转成大写输出,用readline()读整行
    然后继续输入操作,直至当输入"e"或者”exit“时,退出程序
     */
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            //转换成buffer
            br = new BufferedReader(isr);
            String data;
            System.out.println("请输入字符串:");
            while((data = br.readLine()) != null){
                System.out.println("请输入字符串:");
                if ("e".equalsIgnoreCase(data)|| "exit".equalsIgnoreCase(data)){//避免空指针
                    System.out.println("程序结束");
                    break;
                }
                String upperCase = data.toUpperCase();//转换成大写输出
                System.out.println(upperCase);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (br!=null)
                br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
    /*
    打印流:
    PrintStream和PrintWriter

    提供一系列重载(参数不同)的print()和println()
     */
    @Test
    public void test(){
        PrintStream ps = null;
        try {
            FileOutputStream fos = new FileOutputStream(new File("D:\\io\\text.txt"));
            //创建打印输出流,设置自动刷新模式
            ps = new PrintStream(fos, true);
            if (ps != null){
                System.setOut(ps);//把标准输出流(控制台输出)改成文件
            }

            for (int i = 0; i <= 255; i++) {
                System.out.print((char) i);//打印ASCII字符
                if (i % 50 == 0){//每50个一行
                    System.out.println();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
        }

        try {
            if (ps != null)
           ps.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }

    }

    /*
    数据流的使用:
    可以对基本数据类型和String类型做读写
     */
    @Test
    public void test1() throws IOException {
        //写出
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
        dos.writeUTF("刘想");
        dos.flush();
        dos.writeInt(23);
        dos.flush();

        dos.close();
    }

    @Test
    public void test2() throws IOException {
        //读入
        //读取的顺序要与保存的数据顺序一致
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));



        String name = dis.readUTF();
        int age = dis.readInt();

        System.out.println("name=" + name);
        System.out.println("age=" + age);

        dis.close();
    }
}



对象流

  • 可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。

  • 序列化:用(ObjectOutputStream)类保存基本类型数据或对象的机制

  • 反序列化:用(ObjectInputStream)类读取基本类型数据或对象的机制

  • 对象的序列化机制:允许内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持续的保存在磁盘上,或通过网络将这种二进制流输到另一个网络节点,当其他程序获取了这种二进制流就可以恢复成原来的java对象

package io;

import org.testng.annotations.Test;

import java.io.*;

/*
对象流的使用:
1.ObjectInputStream\ObjectOutputStream
2.作用:用于存储和读取基本数据或对象的处理流,
String已经实现了Serializable可序列化
自定义的类要可序列化需要类继承接口,在当前类需要定义常量:
public static final long serialVersionUID = 42342424235L;//序列版本号
String和基本数据类型都是可序列化的
内部属性也必须可序列化
 */
public class ObjectInputOutputStreamTest {
    //序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
    //使用ObjectOutputStream实现

    @Test
    public void testObjectOutputStream(){
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

            oos.writeObject(new String("我爱yy"));//String已经实现了Serializable可序列化
            oos.flush();

            oos.writeObject(new Person("llx",23));//自定义的类要可序列化需要接口
            oos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (oos!=null)
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

    //反序列化的过程:将磁盘文件中的对象还原为内存中的java对象
    //使用ObjectInputStream
    @Test
    public void test1(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));

            Object obj = ois.readObject();
            String str = (String) obj;

            Person p = (Person) ois.readObject();

            System.out.println(str);
            System.out.println(p);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
        }

        try {
            if (ois != null)
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

package io;

import java.io.Serializable;

//自定义类
public class Person implements Serializable {
    public static final long serialVersionUID = 423424242L;//序列版本号
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

随机存储文件流

package io;

import org.testng.annotations.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/*
随机存储文件流:
RandomAccessFile使用:
1.RandomAccessFile直接继承于java.lang.Object类,实现了DateInput和DateOutput接口
2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流

3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则自动创建
如果写出的文件存在,则覆盖,从头覆盖
raf1.seek(3);//将指针调到指标为3的位置进行覆盖

4.可以通过StringBuilder实现插入效果(效率差)

构造器后缀:
-r:只以读的方式打开,不会创建文件
-rw:打开以便读取和写入
-rwd:打开以便读取和写入,同步文件内容的更新
-rws:打开以便读取和写入,同步文件内容和元件数的更新

 */
public class RandomAccessFileTest {
    @Test
    public void test()  {
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            raf1 = new RandomAccessFile(new File("llyy.jpg"), "r");
            raf2 = new RandomAccessFile(new File("llyy1.jpg"), "rw");

            byte[] buffer = new byte[1024];
            int len;
            while ((len = raf1.read(buffer)) != -1){
                raf2.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
        try {
            if (raf1 != null)
                raf1.close();
            if (raf2 != null)
                raf2.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

    }

    //实现覆盖的效果
    @Test
    public void test2() throws IOException {
        File file = new File("hello.txt");
        RandomAccessFile raf1 = new RandomAccessFile(file, "rw");

        raf1.seek(file.length());//将指针调到末尾的位置进行拼接
        raf1.write("xyz".getBytes());//覆盖操作

        raf1.close();
    }

    //使用RandomAccessFile实现插入的效果
    @Test
    public void test3() throws IOException {
        RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"), "rw");

        raf.seek(3);//将指针调到角标为3的位置
        //保存指针3后面的所有数据到StringBuilder中
        //buffer里的数据放到String里面
        StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
        byte[] buffer = new byte[20];
        int len;
        while ((len = raf.read(buffer)) != -1){
            builder.append(new String(buffer,0,len));
        }
        //调回指针,写入”xyz“
        raf.seek(3);
        raf.write("xyz".getBytes());

        //将StringBuilder中的数据写入到文件中
        raf.write(builder.toString().getBytes());

        raf.close();
    }
}

1.close();
if (raf2 != null)
raf2.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}

}

//实现覆盖的效果
@Test
public void test2() throws IOException {
    File file = new File("hello.txt");
    RandomAccessFile raf1 = new RandomAccessFile(file, "rw");

    raf1.seek(file.length());//将指针调到末尾的位置进行拼接
    raf1.write("xyz".getBytes());//覆盖操作

    raf1.close();
}

//使用RandomAccessFile实现插入的效果
@Test
public void test3() throws IOException {
    RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"), "rw");

    raf.seek(3);//将指针调到角标为3的位置
    //保存指针3后面的所有数据到StringBuilder中
    //buffer里的数据放到String里面
    StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
    byte[] buffer = new byte[20];
    int len;
    while ((len = raf.read(buffer)) != -1){
        builder.append(new String(buffer,0,len));
    }
    //调回指针,写入”xyz“
    raf.seek(3);
    raf.write("xyz".getBytes());

    //将StringBuilder中的数据写入到文件中
    raf.write(builder.toString().getBytes());

    raf.close();
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值