搜索
首页Javajava教程java i/o输入输出流的详细介绍

java i/o输入输出流的详细介绍

Jul 20, 2017 pm 02:23 PM
java输入输出

Java流的分类

按流向分:

输入流: 程序可以从中读取数据的流。

输出流: 程序能向其中写入数据的流。

按数据传输单位分:

字节流: 以字节为单位传输数据的流

字符流: 以字符为单位传输数据的流

按功能分:

节点流: 用于直接操作目标设备的流

处理流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

1、编码问题

String s = "哈喽ABC";byte[] bytes1 = s.getBytes();//转换成字节序列用的是项目默认的编码utf-8for (byte b : bytes1) {//把字节(转换成了int)以16进制的方式显示//把byte转换成int  其实就是把后8位前面添24个0变成32位变成4个字节//前24个0没有意义,所以位与上0xff是把前24个0去掉  只留下后8位System.out.print(Integer.toHexString(b&0xff)+"  ");//输出e5  93  88  e5  96  bd  41  42  43          }
        System.out.println();byte[] bytes2 = s.getBytes("gbk");for (byte b : bytes2) {
            System.out.print(Integer.toHexString(b&0xff)+" ");//输出b9 fe e0 b6 41 42 43         }//结论:gbk编码中文占用2个字节,英文占用1个字节;utf-8编码中文占用3个字节,英文占用1个字节        System.out.println();//java是双字节编码 utf-16bebyte[] bytes3 = s.getBytes("utf-16be");for (byte b : bytes3) {
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }//结论:utf-16be中文占用2个字节,英文占用2个字节        
        System.out.println();/* * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,
         * 也需要用这种编码方式,否则会出现乱码         */String str1 = new String(bytes3);
        System.out.println(str1);//输出:T�U� A B CString str2 = new String(bytes3,"utf-16be");
        System.out.println(str2);//输出:哈喽ABC/* * 文本文件 就是字节序列
         * 可以是任意编码的字节序列
         * 如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ANSI编码
         * 联通、联这是一种巧合,他们正好符合了utf-8编码的规则         */

2、File类的使用

java.io.File类用于表示文件(目录)

File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问

  (1)File类的常用api

File file = new File("e:\\javaio");
        File file2 = new File("e:"+File.separator+"javaio");
        System.out.println(file.exists());if(!file.exists())
            file.mkdir();elsefile.delete();//是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false        System.out.println(file.isDirectory());//是否是一个文件        System.out.println(file.isFile());
        
        File file3 = new File("e:"+File.separator+"javaio"+File.separator+"test.txt");//File file3 = new File("e:\\javaid","test.txt");if(!file3.exists())try {
                file3.createNewFile();
            } catch (IOException e) {// TODO Auto-generated catch block                e.printStackTrace();
            }elsefile3.delete();
        
        System.out.println(file);//file.toString()的内容//e:\javaioSystem.out.println(file.getAbsolutePath());//e:\javaioSystem.out.println(file.getName());//javaioSystem.out.println(file3.getName());//test.txtSystem.out.println(file.getParent());//e:\System.out.println(file3.getParent());//e:\javaioSystem.out.println(file.getParentFile().getAbsolutePath());//e:\

  (2)遍历目录

//列出File的一些常用的操作比如过滤、遍历等操作public class FileUtils {/**
 * 列出指定目录下(包括其子目录)的所有文件 */public static void listDirectory(File dir){if(!dir.exists()){throw new IllegalArgumentException("目录"+dir+"不存在");
        }if(!dir.isDirectory()){throw new IllegalArgumentException(dir+"不是目录");
        }//返回的是字符串数组 直接子的名称,不包含子目录下的内容String[] filenames = dir.list();for (String string : filenames) {
            System.out.println(dir+"\\"+string);
        }//如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的APIFile[] files = dir.listFiles();//返回的是直接子目录(文件)的抽象for (File file : files) {
            System.out.println(file);
        }if(files!=null&&files.length>0)for (File file : files) {if(file.isDirectory()){//递归                    listDirectory(file);
                }else{
                    System.out.println(file);
                }
            }
    }
}

3、RandomAccessFile  java提供的对文件内容的访问,既可以读文件,也可以写文件。

RandomAccessFile 支持随机访问文件,可以访问文件的任意位置

(1)java文件模型

在硬盘上的文件是byte byte byte存储的,是数据的集合

(2)打开文件

有两种模式“rw”(读写)“r”(只读)

RandomAccessFile  raf = new RandomAccessFile (file,"rw");

文件指针,打开文件时指针在开头pointer=0;

(3)写方法

raf.write(int)--->只写一个字节(后8位),同事指针指向下一个位置,准备再次写入

(4)读方法

int b = raf.read()--->读一个字节

(5)文件读写完成以后一定要关闭。

File demo = new File("demo");if(!demo.exists())
            file.createNewFile();
        RandomAccessFile raf = new RandomAccessFile(file, "rw");//指针的位置        System.out.println(raf.getFilePointer());
        
        raf.write('A');//只写了一个字节        System.out.println(raf.getFilePointer());
        raf.write('B');        int i = 0x7fffffff;//用write方法每次只能写一个字节,如果要把i写进去就得写4次raf.write(i>>>24);//高8位raf.write(i>>>16);
        raf.write(i>>>8);
        raf.write(i);
        System.out.println(raf.getFilePointer());        //可以直接写一个int        raf.write(i);
        
        String s1 = "中";byte[] gbk = s1.getBytes("gbk");
        raf.write(gbk);
        System.out.println(raf.length());        //读文件,必须把指针移到头部raf.seek(0);//一次性读取,把文件中的内容都读到字节数组中byte[] buf = new byte[(int)raf.length()];
        raf.read(buf);
        System.out.println(Arrays.toString(buf));
        String s2 = new String(buf);for (byte b : buf) {
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }
        raf.close();

 4、IO流(输入流、输出流)

字节流、字符流

(1)字节流

1)InputStream、OutputStream

InputStream抽象了应用程序读取数据的方式

OutputStream抽象了应用程序写出数据的方式

2)EOF = End 读到-1就读到结尾

3)输入流基本方法

int b=in.read();读取一个字节无符号填充到int低8位。-1是EOF

in.read(byte[] buf) 读取数据填充到字节数组buf

in.read(byte[] buf,int start, int size)读取数据到字节数组buf,从buf的start位置开始存放size长度的数据

4)输出流基本方法

out.write(int b) 写出一个byte到流,b的低8位

out.write(byte[] buf) 将buf字节数组都写入到流

out.write(bytep[] buf, int start ,int size) 字节数组buf从start位置开始写size长度的字节到流

5)FileInputStream--->具体实现了在文件上读取数据

public class IOUtil {/** * 读取指定文件内容,按照16进制输出到控制台
     * 并且每输出10个byte换行
     * @param fileName     */public static void printHex(String fileName)throws IOException{//把文件作为字节流进行操作FileInputStream in = new FileInputStream(fileName);int b;int i = 1;while((b=in.read())!=-1){if(b<=0xf){//单位数前面补0System.out.print("0");
            }
            System.out.print(Integer.toHexString(b)+" ");//将整型b转换为16进制表示的字符串if(i++%10==0){
                System.out.println();
            }
        }
        in.close();
    }public static void printHexByByteArray(String fileName)throws IOException{
        FileInputStream in  = new FileInputStream(fileName);byte[] buf = new byte[20*1024];/* * 从in中批量读取字节,放入到buf这个字节数组中,
         * 从第0个位置开始放,最多放buf.length个
         * 返回的是读到的字节的个数         */int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大int j = 1;for (int i = 0; i < bytes; i++) {if(buf[i]<=0xf){
                System.out.println("0");
            }
            System.out.println(Integer.toHexString(buf[i]&0xff)+"  ");if(j++%10==0){
                System.out.println();
            }
        }        int bytes2 = 0;while((bytes2=in.read(buf,0,buf.length))!=-1){for (int i = 0; i < bytes2; i++) {//                byte类型8位,int类型32位,//                为了避免数据转换错误,通过&0xff将高24位清0System.out.println(Integer.toHexString(buf[i]&0xff)+"  ");if(j++%10==0){
                    System.out.println();
                }
            }
        }

6)FileOutputStream 实现了向文件中写出byte数据的方法

/** * 文件拷贝
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");
        }
        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){
            out.write(buf,0,b);
            out.flush();//最好加上        }
        in.close();
        out.close();
        
    }

7)DataOutputStream和DataInputStream

对“流”功能的扩展,可以更加方便的读取int,long,字符等类型数据

DataOutputStream

  writeInt()/writeDouble()/writeUTF()

String file = "dos.dat";
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
        dos.writeInt(20);
        dos.writeInt(-10);
        dos.writeLong(10l);
        dos.writeDouble(10.3);//采用utf-8编码写出dos.writeUTF("中国");//采用utf-16be编码写出dos.writeChars("中国");
        
        dos.close();
        IOUtil.printHex(file);

DataInputStream

String file2 = "dos.dat";
        IOUtil.printHex(file2);
        DataInputStream dis = new DataInputStream(new FileInputStream(file2));
        System.out.println();int i = dis.readInt();
        System.out.println(i);
        i = dis.readInt();
        System.out.println(i);long l = dis.readLong();
        System.out.println(l);double d = dis.readDouble();
        System.out.println(d);
        String s = dis.readUTF();
        System.out.println(s);
        dis.close();

8)BufferedInputStream和BufferedOutputStream

这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能

从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:

FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去

DataOutputStream--->writeXxx()方法相当于一瓢一瓢把水转移过去

BufferedOutputStream--->write()方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入到另一个缸中

/** * 文件拷贝
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");
        }
        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){
            out.write(buf,0,b);
            out.flush();//最好加上        }
        in.close();
        out.close();
        
    }    /** * 进行文件拷贝,利用DataInputStream和DataOutputStream
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFileByData(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件");
        }
        DataInputStream bis = new DataInputStream(new FileInputStream(srcFile));
        DataOutputStream bos = new DataOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){
            bos.write(buf,0,c);
            bos.flush();
        }
        bis.close();
        bos.close();
    }/** * 进行文件拷贝,利用带缓冲的字节流
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件");
        }
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){
            bos.write(buf,0,c);
            bos.flush();
        }
        bis.close();
        bos.close();
    }

(2)字符流

Reader   Writer

字符的处理,一次处理一个字符

字符的底层仍然是基本的字节序列

字符流的基本实现

  InputStreamReader 完成byte流解析为char流,按照编码解析

  OutputStreamWriter 提供char流到byte流,按照编码处理

InputStreamReader isr = new InputStreamReader(new FileInputStream("out.dat"),"gbk");//默认项目的编码,操作的时候要写文件本身的编码FileOutputStream out = new FileOutputStream("out2.dat");
        OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");//        int c;//        while((c=isr.read())!=-1){//            System.out.print((char)c);//        }char[] buffer = new char[8*1024];int c;//批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length//返回的是读到的字符的个数while((c=isr.read(buffer, 0, buffer.length))!=-1){//需要把这个字符数组构造成字符串String s = new String(buffer,0,c);
            System.out.print(s);
            osw.write(buffer,0,c);
            osw.flush();
        }
        isr.close();
        osw.close();

FileReader、FileWriter

FileReader fr = new FileReader("out.dat");
        FileWriter fw = new FileWriter("out3.dat");//        FileWriter fw = new FileWriter("out3.dat");char[] buffer = new char[2056];int c;while((c=fr.read(buffer ,0,buffer.length))!=-1){
            fw.write(buffer,0,c);
            fw.flush();
        }
        fr.close();
        fw.close();

字符流过滤器

BufferedReader --->readLine  一次读一行

BufferedWriter/PrinterWriter  --->写一行

//对文件进行读写操作BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("out.dat"),"gbk"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out4.dat")));
        PrintWriter pw = new PrintWriter("out5.dat");//PrintWriter pw2 = new PrintWriter(outputStream,boolean autoFlush);        String line;while((line=br.readLine())!=null){
            System.out.println(line);//一次读一行,并不能识别换行            bw.write(line);//单独写出换行操作bw.newLine();//换行操作            bw.flush();
            pw.println(line);
            pw.flush();
        }
        br.close();
        bw.close();
        pw.close();

5、对象的序列化,反序列化

(1)对象的序列化,就是将Object转换成byte序列,反之叫对象的反序列化

(2)序列化流(ObjectOutputStream),是过滤流----writeObject

   反序列化流(ObjectInputStream)----readObject

(3)序列化接口(Serializable)

  对象必须实现序列化接口,才能进行序列化,否则将出现异常

  这个接口,没有任何方法,只是一个标准

String file = "stu.dat";//1.对象的序列化ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        Student stu = new Student("10001","张三",20);
        oos.writeObject(stu);
        oos.flush();
        oos.close();        //2.对象的反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        Student stu1 = (Student)ois.readObject();
        System.out.println(stu1);
        ois.close();

(4)transient关键字

  private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException

  private void readObject(java.io.ObjectInputStream s)
  throws java.io.IOException, ClassNotFoundException

分析ArrayList源码中序列化和反序列化的问题

public class Student implements Serializable{private String stuno;private String stuname;private transient int stuage;//加了transient关键字,则该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化public Student(){}    public Student(String stuno, String stuname, int stuage) {super();this.stuno = stuno;this.stuname = stuname;this.stuage = stuage;
    }public String getStuno() {return stuno;
    }public void setStuno(String stuno) {this.stuno = stuno;
    }public String getStuname() {return stuname;
    }public void setStuname(String stuname) {this.stuname = stuname;
    }public int getStuage() {return stuage;
    }public void setStuage(int stuage) {this.stuage = stuage;
    }
    @Overridepublic String toString() {return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
                + stuage + "]";
    }private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{
        s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作s.writeInt(stuage);//自己完成student的序列化(stuage用transient修饰了,也可以自己序列化)    }private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException{
        s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作this.stuage = s.readInt();//自己完成stuage的反序列化操作    }
}

(5)序列化中 子类和父类构造函数的调用问题

一个类实现了序列化接口,那么其子类都可以进行序列化

对子类对象进行反序列化操作时,如果其父类没有实现序列化接口那么其父类的构造函数就会被调用,否则就不会被调用。

以上是java i/o输入输出流的详细介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何将Maven或Gradle用于高级Java项目管理,构建自动化和依赖性解决方案?如何将Maven或Gradle用于高级Java项目管理,构建自动化和依赖性解决方案?Mar 17, 2025 pm 05:46 PM

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

如何使用适当的版本控制和依赖项管理创建和使用自定义Java库(JAR文件)?如何使用适当的版本控制和依赖项管理创建和使用自定义Java库(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

如何使用咖啡因或Guava Cache等库在Java应用程序中实现多层缓存?如何使用咖啡因或Guava Cache等库在Java应用程序中实现多层缓存?Mar 17, 2025 pm 05:44 PM

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

如何将JPA(Java持久性API)用于具有高级功能(例如缓存和懒惰加载)的对象相关映射?如何将JPA(Java持久性API)用于具有高级功能(例如缓存和懒惰加载)的对象相关映射?Mar 17, 2025 pm 05:43 PM

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类负载机制如何起作用,包括不同的类载荷及其委托模型?Java的类负载机制如何起作用,包括不同的类载荷及其委托模型?Mar 17, 2025 pm 05:35 PM

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA

如何将Java的RMI(远程方法调用)用于分布式计算?如何将Java的RMI(远程方法调用)用于分布式计算?Mar 11, 2025 pm 05:53 PM

本文解释了用于构建分布式应用程序的Java的远程方法调用(RMI)。 它详细介绍了接口定义,实现,注册表设置和客户端调用,以解决网络问题和安全性等挑战。

如何使用Java的插座API进行网络通信?如何使用Java的插座API进行网络通信?Mar 11, 2025 pm 05:53 PM

本文详细介绍了用于网络通信的Java的套接字API,涵盖了客户服务器设置,数据处理和关键考虑因素,例如资源管理,错误处理和安全性。 它还探索了性能优化技术,我

如何在Java中创建自定义网络协议?如何在Java中创建自定义网络协议?Mar 11, 2025 pm 05:52 PM

本文详细介绍了创建自定义Java网络协议。 它涵盖协议定义(数据结构,框架,错误处理,版本控制),实现(使用插座),数据序列化和最佳实践(效率,安全性,维护

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)