java输入输出流(I/O)

概念

        流是一组有序的数据序列,根据操作的类型,分为输入和输出(I/O),常与磁盘文件存取有关,源和地址可以是键盘、鼠标、内存或显示器窗口等

输入流

        InputStream类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到的错误时会引发IOException异常。下面是对该类中一些方法的简要说明(并不是所有InputStream类的子类都支持以下方法)

read();从输入流中读取数据的下一个字节,没有可用字节时,返回-1
read(byte[] b);从输入流中读取一定长度的字节,并以整数的形式返回字节数
mark(int readlimit);在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数
reset();将输入指针返回到当前所做的标记处
skip(long n);跳过输入流上的n个字节并返回跳过的字节数
markSupported();如果当前流支持mark/reset操作就返回true
close();关闭此输入流并释放与该流关联的所有系统资源

        Java中的字符都是Unicode编码,是双字节的。IputStream是用来处理字节的,并不适合处理字符文本。java为字符文本的输入专门提供了一套单独的类Reader。

        Reader是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

输出流

        OutStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。所有方法均返回void,遇到错误是引发IOException异常。

        下面对其类中的方法做简单的介绍:

writer(int b);将指定的字节写入此输出流
writer(byte[] b);将b个字节从指定的byte数组写入此输出流
writer(byte[] b,int off,int len);将指定的byte数组中从偏移量off开始的len个字节写入此输出流
flush();彻底完成输出并清空缓存区
close();关闭输出流

        Writer类是字符输出流的抽象类,所有的字符输出类的实现都是它的子类。

File类

        java.io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件马,可以通过调用File类中的方法,实现创建、删除、重命名文件等操作。主要用来获取文件本身的一些信息。

文件的创建与删除

创建文件对象的三种方法:
new File(String 全路径);
new File(String 父路径,String 子路径);如"D:/doc","le.txt"
new File(File 父路径对象,String 子路径);

        当File创建一个对象时,如果目标文件不存在,可以调用createNewFile();方法创建,若想删除,可以调用delete();方法删除

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

public class file {
    public static void main(String[] args) {
        File file = new File("world.txt");
        if (file.exists()){
            file.delete();
            System.out.println("文件已删除");
        }else{
            try {
                file.createNewFile();
                //file.mkdir();创建单个目录
                //file.mkdirs();逐级创建文件,比如new File("D:/xx/world.txt")
                System.out.println("文件已创建");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3cfd49f3bd904e4995fcaf7b097547f3.png

 file.mkdirs();的运行结果

d3c6fa90475d40f58c62a0e5fbd7e0b3.png

获取文件信息

class fileOut{
    public static void main(String[] args) {
        File file = new File("world.txt");
        if (file.exists()){//文件是否存在
            String FileName = file.getName();//获取文件名
            boolean ifRead = file.canRead();//文件是否可读
            boolean ifWrite = file.canWrite();//文件是否可写
            long length = file.length();//获取文件长度,单位:字节
            String path = file.getAbsolutePath();//获取文件绝对路径
            String parent = file.getParent();//获取父路径
            boolean isFile = file.isFile();//判断文件是否存在
            boolean isDirectory = file.isDirectory();//判断文件是否是一个目录(及文件夹)
            boolean isHidden = file.isHidden();//文件是否有隐目录
            long lastTime= file.lastModified();//获取文件最后修改时间,返回时间戳
            System.out.println("文件名:"+FileName+"\n"+"可读:"+ifRead+"\n"+"可写:"+ifWrite+"\n"+"文件长度:"+length+"\n" +
                    "绝对路径:"+path+"\n"+"父路径:"+parent+"\n"+"是否存在:"+isFile+"\n" +
                    "是文件夹:"+isDirectory+"\n"+"隐藏目录:"+isHidden+"\n"+"最后修改时间:"+lastTime);
        }else{
            System.out.println("该文件不存在");
        }
    }
}

7819d413a0ce4acca8e266e444fc59da.png

 获取该路径下所有目录及子目录

 private static void readFile(File f){
        File[] files = f.listFiles();
        for (File fi:files){
            if (fi.isFile()){
                //String name = fi.getName();获取文件名
                //if (name.endsWith(".java"))如果文件以.java结尾,则输出文件
                    System.out.println("fi.getAbsolutePath() = " + fi.getAbsolutePath());
            }else if (fi.isDirectory()){
                readFile(fi);
            }
        }
    }

文件输入输出流

FIleInputStream和FileOutputStream类

        FIleInputStream和FileOutputStream类都是用来操作磁盘文件的如果用户对读取需求比较简单,则可以使用FileInputStream类,FileOutputStream类提供了基本的文件写入功能。

        FileInputStream类常用的构造方法如下:

                FileInputStream(String name);

                FileInputStream(File file);

        FileOutputStream与之相同,可以指定不存在的文件

下面演示两个实例:

import java.io.*;
import java.nio.charset.StandardCharsets;

public class fileInorOut {
    public static void main(String[] args) {
        File file = new File("world.txt");//创建文件对象
        try {
            FileOutputStream out = new FileOutputStream(file);//创建FileOutputStream对象
            byte[] b = "我有一头小毛驴".getBytes(StandardCharsets.UTF_8);
            out.write(b);//将数组内容写入文件
            out.close();//关闭输出流
            FileInputStream in = new FileInputStream(file);
            byte[] read = new byte[1024];
            int len = in.read(read);//读取文件内容
            System.out.println("文件中的信息是:"+new String(read,0,len));
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

public class InputOutStreamDemo {
    public static void main(String[] args) throws IOException {
        /**
         *在文件file3下有个1.txt文本,想把它上传到file3下的upload文件夹下
         */
        //1.获取路径,如果不存在则创建
        String srcDirectPath = "D:\\file3\\upload\\";
        File file3 = new File(srcDirectPath);
        if (!file3.exists()) file3.mkdirs();
        //创建1.txt文件
        File txt = new File("D:\\file3\\1.txt");
        if (!txt.exists()) txt.createNewFile();
        //2.创建OutputStream对象
        OutputStream out = new FileOutputStream(txt);
        //3.向文件中写入内容
        StringBuilder sb = new StringBuilder();
        while (sb.length()<1024){
            sb.append("这是我写进去的东西");
        }
        byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8);
        out.write(bytes);
        //5.创建InputStream对象
        InputStream in = new FileInputStream(txt);
        //根据指定的规则生成一个文本文档
        OutputStream o = new FileOutputStream(srcDirectPath + UUID.randomUUID() + ".txt");
        //创建字节数组,表示一次读取多少字节的内容
        byte[] b = new byte[1024];
        int len = 0;
        //写入的大小超过1024时就需要用到循环,不然只写入前1024字节的内容
        while ((len = in.read(b))!=-1){
            o.write(b, 0, len);
        }
        //关闭流,最后使用的先关闭,最先使用的最后关闭
        if (o!=null) o.close();
        if (out!=null) out.close();
        if (in!=null) in.close();
    }
}

FileReader和FileWriter类

        FIleInputStream和FileOutputStream类只提供了字节/字节数组的输入和输出,由于汉字占两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流更为合适。

下面是实例:(不知道JFrame的我的博客有写)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;

public class readerORwriter extends JFrame {
    private JPanel jContentPane = null;//创建面板对象
    private JTextArea jTextArea = null;//创建文本域
    private JButton writerButton = null;
    private JButton readButton = null;
    private JPanel controltPanel = null;

    private JButton getWriterButton(){
        if (writerButton == null){
            writerButton = new JButton("写入文件");
            writerButton.addActionListener(new ActionListener() {//给按钮添加监听事件
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        File file = new File("test.txt");//创建文件对象
                        file.createNewFile();//创建文件
                        FileWriter writer = new FileWriter(file);//创建FileWriter对象
                        writer.write(jTextArea.getText());//获取文本域中的文本并写入磁盘
                        writer.close();//关闭流
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
            });
        }
        return writerButton;
    }
    private JButton getReadButton(){
        if (readButton == null){
            readButton = new JButton("读取文件");
            readButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    File file = new File("test.txt");
                    try {
                        FileReader read = new FileReader(file);
                        char[] text = new char[1024];
                        int len = read.read(text);//读取文件长度
                        jTextArea.append("\n文件内容如下:\n"+new String(text,0,len));
                        read.close();
                    } catch (FileNotFoundException fileNotFoundException) {
                        fileNotFoundException.printStackTrace();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
            });
        }
        return readButton;
    }

    public readerORwriter(){
        super();
        initialize();
    }
    private void initialize(){
//        this.setVisible(true);
        this.setSize(300,200);
//        this.setDefaultCloseOperation(3);
        this.setTitle("测试写入读取");
        this.setContentPane(getjContentPane());
    }
    private JPanel getjContentPane(){
        if (jContentPane == null){
            jContentPane = new JPanel();
            jContentPane.setLayout(new BorderLayout());
            jContentPane.add(getJTextArea(),BorderLayout.NORTH);
            jContentPane.add(getControlPanel(),BorderLayout.SOUTH);
        }
        return jContentPane;
    }

    private JPanel getControlPanel() {
        if (controltPanel == null){
            controltPanel = new JPanel();
            controltPanel.add(getWriterButton());
            controltPanel.add(getReadButton());
        }
        return controltPanel;
    }

    public JTextArea getJTextArea() {
        if (jTextArea == null) {
            jTextArea = new JTextArea(7,15);
            jTextArea.setLineWrap(true);
        }
        return jTextArea;
    }

    public static void main(String[] args) {
        readerORwriter r = new readerORwriter();
        r.setVisible(true);
        r.setDefaultCloseOperation(3);
    }
}

b23c5291a89b4a30a07bcb6db803169f.png

带缓存的输入输出流

        缓存是I/O的一种性能优化,缓存流为I/O流增加了内存缓存区。有了缓存区使得在流上执行skip()、mark()、reset()方法都成为可能

BufferedInputStream与BufferedOutputStream类

        BufferedInputStream类可以对所有InputStream类进行缓存区的包装以达到性能的优化。它的两个构造方法:

                BufferedInputStream(InputStream in);//创建一个带有32个字节的缓存流

                BufferedInputStream(InputStream in,int size);//按指定大小创建缓存区

        BufferedOutputStream输出信息和用OutputStream完全一样,只不过BufferedOutputStream有一个flush()方法用来将缓存区的数据强制输出完。它的两个构造方法:

                BufferedOutputStream(OutputStream out);

                BufferedOutputStream(OutputStream out,int size);

private static void testFile3(String src) throws IOException {
    //		1.通过file将源文件路径建立联系,读取文件的路径信息
    File srcFile = new File(src);

    //		2.创建上传后的路径,不存在的话进行创建
    String path= "D:\\upload\\";
    File uploadFile = new File(path);
    if(!uploadFile.exists()) {//判断是否存在该文件
        uploadFile.mkdir();//一层文件夹的创建,如果是多层文件都不存在,需要用到mkdirs方法进行创建
    }

    if(srcFile.exists()) {
        //创建输入缓冲流	,也叫包装流
        InputStream is = new BufferedInputStream(new FileInputStream(srcFile));

        String distPath = path + UUID.randomUUID()+srcFile.getName();
        OutputStream os = new BufferedOutputStream(new FileOutputStream(distPath));

        //读和写的具体实现
        byte[] buf = new byte[1024];//通过字节数组提高读取效率
        int len =0;//每次读取的长度,如果读取到文件末尾,该值==-1,代表结束
        while ((len=is.read(buf))!=-1) {
            os.write(buf, 0, len);
        }
        os.close();
        is.close();
    }
}

BufferedReader与BufferedWrtier类

        BufferedReader与BufferedWrtier类是以行为单位进行输入/输出

        BufferedReader类的常用方法:

                read();//读取单个字符

                readLine();//读取一个文本行,并将其返回为字符串,若无数据可读,则返回null

        BufferedWrtier类的常用方法:

                wirte(String s,int off,int len);//写入字符串的某一部分

                flush();//刷新该流的缓存

                newLine();//写入一个行分隔符

        注意:在使用BufferedWrtier类的wirte()方法时,数据并没有立刻被写入至输出流,而是先进入缓存区中,如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法。

import java.io.*;

public class buffer {
    public static void main(String[] args) {
        //定义字符串数组
        String[] text = {
                "好久不见",
                "最近好吗",
                "常联系"
        };
        File file  = new File("word.txt");
        try {
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fileWriter);//BufferedWriter需要传一个writer对象为参数
            for (int i = 0; i < text.length; i++) {//遍历数组写入磁盘文件
                bw.write(text[i]);
                bw.newLine();
            }
            bw.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            FileReader fileReader = new FileReader(file);
            BufferedReader br = new BufferedReader(fileReader);
            String s = null;//创建字符串接收数据
            int i = 0;
            //创建循环,如果文本行不为空,则进入循环
            while ((s = br.readLine())!=null){
                i++;
                System.out.println("第"+i+"行:"+s);
            }
            br.close();
            fileReader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

40b451903ab74680b1610b0140e238ed.png

         BufferedReader同样需要一个reader对象作为参数。流关闭是一个良好的写代码习惯,防止占用资源,一定不要忘记哦。

 7d243aaed40a432f9e76372fd3eeb132.png

数据输入输出流

        DataInputStream类与DataOutputStream类允许应用程序以与机器无关的方式从底层输入流中读取基本java数据。也就是说,当读取一个数据时,不必再关心这个数值应当是哪个字节。构造方法如下;

                DataInputStream(InputStream in);//使用指定的基础InputStream创建一个DataInputStream

                DataOutStream(OutputStream out);//创建一个新的字节输出流,将数据写入指定基础输出流。

        DataOutStream提供如下三种写入字符串的方法:

                writeBytes(String s);

                writeChars(String s);

                writeUTF(String s);

        DataInputStream只有一个readUTF()方法用于在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。DataOutStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确地读回写入的字符串。

import java.io.*;

public class data {
    public static void main(String[] args) {
        try {
            FileOutputStream fo = new FileOutputStream("word.txt");//创建文件输出流对象
            DataOutputStream da = new DataOutputStream(fo);//创建数据输出流对象
            da.writeUTF("UTF输入");
            da.writeChars("Char输入");
            da.writeBytes("Byte输入");
            da.close();
            FileInputStream in = new FileInputStream("word.txt");
            DataInputStream di = new DataInputStream(in);
            System.out.println(di.readUTF());//输出文件信息
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

只输出由UTF格式写入的数据 

 b05582f1fa064393aa62bac1a17980b4.png128a02da2fab49e6a857b04fc89a6cd6.png

zip压缩输入输出流

        ZIP压缩管理文件是一种十分典型的文件压缩形式,使用它可以节省存储空间。

压缩文件

        ZipOutputStream(OutputStream out);//将文件压缩为zip文件。

        ZipOutputStream类的常用方法如下:

                putNextEntry(ZipEntry e);//开始写一个新的ZipEntry(代表一个压缩文件的进入点),并将流内的位置移至此entry(进入点)所指的数据的开头。

                write(byte[] b,int off,int len);//将字节数组写入当前zip条目数据。

                finish();//完成写入zip输出流的内容,无需关闭它所配合的OutputStream

                setComment(String comment);//可设置此zip文件的注释文字

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class zipTest {
    private void zip(String zipFileName, File inputFile){
        try {
            ZipOutputStream out = new JarOutputStream(new FileOutputStream(zipFileName));//创建zip输出流对象
            zip(out, inputFile, "");//调用方法
            System.out.println("压缩中...");
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void zip(ZipOutputStream out, File f,String base){//重载方法
        if (f.isDirectory()){//判断是否是一个目录
            File[] fl = f.listFiles();//获取文件路径数组
            System.out.println("路径数组:"+ Arrays.toString(fl));
            try {
                out.putNextEntry(new ZipEntry(base+"/"));//写入此目录的进入点
                base = base.length()==0?"":base+"/";//判断参数是否为空
                for (int i = 0; i < fl.length; i++) {//遍历数组中的文件
                    zip(out, fl[i],base+fl[i]);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            try {
                out.putNextEntry(new ZipEntry(base.substring(3)));
                FileInputStream in = new FileInputStream(f);
                System.out.println(base.substring(3));//去掉根目录--》D:/
                int b;
                while ((b = in.read())!=-1){//如果没有到达流的尾部
                    out.write(b);//将字节写入当前zip条目
                }
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        zipTest zt = new zipTest();
        zt.zip("D:/zip测试.zip", new File("D:/zip测试"));//参数为压缩后的路径/文件名和要压缩的文件/目录路径
        System.out.println("压缩完成");
    }
}

 903bbd5600544867b2b5d433cf3a89a8.png

解压缩zip文件

        ZipInputStream类可读取ZIP压格式的文件,包括已压缩和未压缩的条目。构造方法:ZipInputStream(InputStream in);常用方法如下:

                read(byte[] b,int off,int len)//读取目标b数组内off偏移量的单位,长度是len的字符

                available()//判断是否已读完目前entry所指的数据。已读完返回0,反之返回1

                closeEntry()//关闭当前ZIP条目并定位流以读取下一个条目

                skip(long n)跳过当前ZIP条目中指定的字节数

                getNextEntry()//读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头

                createZipEntry(String name)//以指定的name参数新建一个ZipEntry对象

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class gZip {
    public static void main(String[] args) {
        try {
            ZipInputStream zin = new JarInputStream(new FileInputStream("D:\\zip测试.zip"));//指明要解压的文件
            ZipEntry zpe = zin.getNextEntry();//获取下一个ZipEntry
            while (((zpe = zin.getNextEntry()) != null) && !zpe.isDirectory()) {//如果entry不为空且不在同一目录下
                File file = new File("D:\\"+zpe.getName().substring(0, 5));//获取文件夹目录
                File file2 = new File("D:\\"+zpe.getName());//获取文件目录
                System.out.println(file);
                if (!file.exists()) {//如果文件不存在
                    file.mkdirs();//创建文件所在文件夹
                }
                file2.createNewFile();//创建文件
                zin.closeEntry();
                System.out.println(zpe.getName() + "解压成功");
            }
            zin.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ff0d95d4fc424958932fea6c8c1f5a32.png

打印流

因为用法和前面的一样,功能也一样,那我们就直接上代码吧

先看看创建对象时的参数列表吧

 然后是使用写入的参数列表

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class printIO {
    public static void main(String[] args) {
        PrintWriter printWriter = null;
        try {
            //创建一个打印流对象,传入一个文件对象
            printWriter = new PrintWriter(new File("D:\\catch\\ideas\\IO\\text"));
            printWriter.write("ass");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }finally {
            printWriter.close();
        }
    }
}

 

还有一个PrintStream和PrintWriter的区别就是前者有自动缓冲的参数,后者没有

小结

基本的java输入输出流到这结束!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尢词

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值