文件输入输出流

文件输入输出流 FileInputStream 和 FileOutputStream 负责完成对本地磁盘文件的顺序输入输出操作。

【例 10-5】通过程序创建一个文件,从键盘输入字符,当遇到字符“#”时结束,在屏幕上显示该文件的所有内容。

  1. 【例 10-5】通过程序创建一个文件,从键盘输入字符,当遇到字符“#”时结束,在屏幕上显示该文件的所有内容。
  2. //********** ep10_5.java **********
  3. import java.io.*;
  4. class ep10_5{
  5. public static void main(String args[]){
  6. char ch;
  7. int data;
  8. try{
  9. FileInputStream a=new FileInputStream(FileDescriptor.in); //创建文件输入流对象
  10. FileOutputStream b=new FileOutputStream("ep10_5"); //创建文件输出流对象
  11. System.out.println("请输入字符,以#号结束:");
  12. while((ch=(char)a.read())!='#'){
  13. b.write(ch);
  14. }
  15. a.close();
  16. b.close();
  17. System.out.println();
  18. FileInputStream c=new FileInputStream("ep10_5");
  19. FileOutputStream d=new FileOutputStream(FileDescriptor.out);
  20. while(c.available()>0){
  21. data=c.read();
  22. d.write(data);
  23. }
  24. c.close();d.close();
  25. }
  26. catch(FileNotFoundException e){
  27. System.out.println("找不到该文件!");
  28. }
  29. catch(IOException e){}
  30. }
  31. }

运行后在程序目录建立一个名称为 ep10_5 的文件,运行结果如图 10-8 所示:


图 10-8  例 10_5 运行结果

FileDescriptor 是 java.io 中的一个类,该类不能实例化,其中包含三个静态成员:in、out 和err,分别对应于标准输入流、标准输出流和标准错误流,利用它们可以在标准输入输出流上建立文件输入输出流,实现键盘输入或屏幕输出操作。

【例 10-6】实现对二进制图形文件(.gif)的备份。

  1. 【例 10-6】实现对二进制图形文件(.gif)的备份。
  2. //********** ep10_6.java **********
  3. import java.io.*;
  4. class ep10_6{
  5. public static void main(String args[]) throws IOException{
  6. FileInputStream a=new FileInputStream("ep10_6.gif");
  7. FileOutputStream b=new FileOutputStream("ep10_6_a.gif");
  8. System.out.println("文件的大小为:"+a.available());
  9. byte c[]=new byte[a.available()];
  10. a.read(c); //将图形文件读入数组
  11. b.write(c); //将数组中的数据写入到新文件中
  12. System.out.println("文件已经被更名复制!");
  13. a.close();
  14. b.close();
  15. }
  16. }

运行后在程序目录备份了一个名称为 ep10_6_a.gif 的文件,运行结果如图 10-9 所示:


图 10-9  例 10_6 运行结果

过滤流

FilterInputStream 和 FileOutputStream 是 InputStream 和 OutputStream 的直接子类,分别实现了在数据的读、写操作的同时能对所传输的数据做指定类型或格式的转换,即可实现对二进制字节数据的理解和编码转换。

常用的两个过滤流是数据输入流 DataInputStream 和数据输出流 DataOutputStream。其构造方法为:
    DataInputStream(InputStream in);  //创建新输入流,从指定的输入流 in 读数据
    DataOutputStream(OutputStream out);  //创建新输出流,向指定的输出流 out 写数据

由于 DataInputStream 和 DataOutputStream 分别实现了 DataInput 和 DataOutput 两个接口(这两个接口规定了基本类型数据的输入输出方法)中定义的独立于具体机器的带格式的读写操作,从而实现了对不同类型数据的读写。由构造方法可以看出,输入输出流分别作为数据输入输出流的构造方法参数,即作为过滤流必须与相应的数据流相连。

DataInputStream 和 DataOutputStream 类提供了很多个针对不同类型数据的读写方法,具体内容读者可参看 Java 的帮助文档。

【例 10-7】将三个 int 型数字 100,0,-100 写入数据文件 ep10_6.dat 中。

  1. 【例 10-7】将三个 int 型数字 1000,-100 写入数据文件 ep10_6.dat 中。
  2. //********** ep10_7.java **********
  3. import java.io.*;
  4. class ep10_7{
  5. public static void main(String args[]){
  6. String fileName="ep10_7.dat";
  7. int value1=100,value2=0,value3=-100;
  8. try{
  9. //将 DataOutputStream 与 FileOutputStream 连接输出不同类型的数据
  10. DataOutputStream a=new DataOutputStream(new FileOutputStream(fileName));
  11. a.writeInt(value1);
  12. a.writeInt(value2);
  13. a.writeInt(value3);
  14. a.close();
  15. }
  16. catch(IOException i){
  17. System.out.println("出现错误!"+fileName);
  18. }
  19. }
  20. }

运行后在程序目录中生成数据文件 ep10_7.dat,用文本编辑器打开后发现内容为二进制的:

00 00 00 64 00 00 00 00 FF FF FF 9C。

【例 10-8】读取数据文件 ep10_6.dat 中的三个 int 型数字,求和并显示。

  1. 【例 10-8】读取数据文件 ep10_6.dat 中的三个 int 型数字,求和并显示。
  2. //********** ep10_8.java **********
  3. import java.io.*;
  4. class ep10_8{
  5. public static void main(String args[]){
  6. String fileName="D:\\myjava/ep10_7.dat";
  7. int sum=0;
  8. try{
  9. DataInputStream a=new DataInputStream(new BufferedInputStream(new FileInputStream(fileName)));
  10. sum+=a.readInt();
  11. sum+=a.readInt();
  12. sum+=a.readInt();
  13. System.out.println("三个数的和为:"+sum);
  14. a.close();
  15. }
  16. catch(IOException e){
  17. System.out.println("出现错误!"+fileName);
  18. }
  19. }
  20. }

运行结果:

三个数的和为:0

readInt 方法可以从输入输出流中读入 4 个字节并将其作为 int 型数据直接参与运算。由于已经知道文件中有 3 个数据,所以可以使用 3 个读入语句,但若只知道文件中是 int 型数据而不知道数据的个数时该怎么办呢?因为 DataInputStream 的读入操作如遇到文件结尾就会抛出 EOFException 异常,所以可将读操作放入 try 中。

  1. try{
  2. while(true)
  3. sum+=a.readInt();
  4. }
  5. catch(EOFException e){
  6. System.out.pritnln("三个数的和为:"+sum);
  7. a.close();
  8. }

EOFException 是 IOException 的子类,只有文件结束异常时才会被捕捉到,但如果没有读到文件结尾,在读取过程中出现异常就属于 IOException。

【例 10-9】从键盘输入一个整数,求该数的各位数字之和。

  1. 【例 10-9】从键盘输入一个整数,求该数的各位数字之和。
  2. //********** ep10_9.java **********
  3. import java.io.*;
  4. class ep10_9{
  5. public static void main(String args[]) throws IOException{
  6. DataInputStream a=new DataInputStream(System.in);
  7. System.out.print("请输入一个整数:");
  8. int b=a.readInt();
  9. int sum=0;
  10. int c=b;
  11. while(c>0){
  12. int d=c%10; //取最低位
  13. c=c/10; //去掉最低位
  14. sum=sum+d; //累加各位之和
  15. }
  16. System.out.println(b+"的各位数字之和="+sum);
  17. }
  18. }

运行结果:

请输入一个整数:26
842403082 的各位数字之和=31

需要注意的是,输入的数据 26 为变成了 842403082,原因在于输入数据不符合基本类型数据的格式,从键盘提供的数据是字符的字节码表示方式,若输入 26,只代表 2 和 6 两个字符的字节数据,而不是代表整数 26 的字节码。

若要从键盘得到整数需要先读取字符串,再利用其他方法将字符串转化为整数。

标准输入输出

System.in、System.out、System.err 这 3 个标准输入输流对象定义在 java.lang.System 包中,这 3 个对象在 Java 源程序编译时会被自动加载。

  1. 标准输入:标准输入 System.in 是 BufferedInputStream 类的对象,当程序需要从键盘上读入数据时,只需要调用 System.in 的 read()方法即可,该方法从键盘缓冲区读入一个字节的二进制数据,返回以此字节为低位字节,高位字节为 0 的整型数据。
  2. 标准输出:标准输出 System.out 是打印输出流 PrintStream 类的对象。PrintStream 类是过滤输出流类 FilterOutputStream 的一个子类,其中定义了向屏幕输出不同类型数据的方法print()和 println()。
  3. 标准错误输出:System.err 用于为用户显示错误信息,也是由 PrintStream 类派生出来的错误流。Err 流的作用是使 print()和 println()将信息输出到 err 流并显示在屏幕上,以方便用户使用和调试程序。

【例 10-10】输入一串字符显示出来,并显示 System.in 和 System.out 所属的类。

  1. 【例 10-10】输入一串字符显示出来,并显示 System.in System.out 所属的类。
  2. //********** ep10_10.java **********
  3. import java.io.*;
  4. class ep10_10{
  5. public static void main(String args[]){
  6. try{
  7. byte a[]=new byte[128]; //设置输入缓冲区
  8. System.out.print("请输入字符串:");
  9. int count =System.in.read(a); //读取标准输入输出流
  10. System.out.println("输入的是:");
  11. for(int i=0;i<count;i++)
  12. System.out.print(a[i]+""); //输出数组元素的 ASCII 值
  13. System.out.println();
  14. for(int i=0;i<count-2;i++) //不显示回车和换行符
  15. System.out.print((char)a[i]+""); //按字符方式输出元素
  16. System.out.println();
  17. System.out.println("输入的字符个数为:"+count);
  18. Class InClass=System.in.getClass();
  19. Class OutClass=System.out.getClass();
  20. System.out.println("in 所在的类为:"+InClass.toString());
  21. System.out.println("out 所在的类为:"+OutClass.toString());
  22. }
  23. catch(IOException e){}
  24. }
  25. }

运行结果如图 10-10 所示:


图 10-10  例 10_10 运行结果

需要注意的是,输入了 3 个字符按回车后,输出的结果显示为 5 个字符。这是由于 Java 中回车被当作两个字符,一个是 ASCⅡ为 13 的回车符,一个是值为 10 的换行符。程序中 getClass()和 ToString()是 Object 类的方法,作用分别是返回当前对象所对应的类和返回当前对象的字符串表示。

系列文章:

Java知多少(70)面向字节流的应用的更多相关文章

  1. Java知多少(69)面向字节的输入输出流

    字节流以字节为传输单位,用来读写8位的数据,除了能够处理纯文本文件之外,还能用来处理二进制文件的数据.InputStream类和OutputStream类是所有字节流的父类. InputStream类 ...

  2. Java知多少(67)面向字符的输入流

    字符流是针对字符数据的特点进行过优化的,因而提供一些面向字符的有用特性,字符流的源或目标通常是文本文件. Reader和Writer是java.io包中所有字符流的父类.由于它们都是抽象类,所以应使用 ...

  3. Java知多少(68)面向字符的输出流

    面向字符的输出流都是类 Writer 的子类,其类层次结构如图 10-5 所示. 图10-5 Writer的类层次结构图 表 10-3 列出了 Writer 的主要子类及说明. 表 10-3 Writ ...

  4. Java知多少(完结篇)

    Java知多少(1)语言概述 Java知多少(2)虚拟机(JVM)以及跨平台原理 Java知多少(3) 就业方向 Java知多少(4)J2SE.J2EE.J2ME的区别 Java知多少(5) Java ...

  5. Java知多少(66)输入输出(IO)和流的概述

    输入输出(I/O)是指程序与外部设备或其他计算机进行交互的操作.几乎所有的程序都具有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等.通过输入和输出操作可以从外界接收信息, ...

  6. Java知多少(中)

    Java知多少(上) )interface接口 )接口和抽象类的区别 )泛型详解 )泛型通配符和类型参数的范围 )异常处理基础 )异常类型 )未被捕获的异常 )try和catch的使用 )多重catc ...

  7. Java知多少(105)套接字(Socket)

    网络应用模式主要有: 主机/终端模式:集中计算,集中管理: 客户机/服务器(Client/Server,简称C/S)模式:分布计算,分布管理: 浏览器/服务器模式:利用Internet跨平台. www ...

  8. Java知多少(87)选择框和单选按钮(转)

    选择框.单选框和单选按钮都是选择组件,选择组件有两种状态,一种是选中(on),另一种是未选中(off),它们提供一种简单的 “on/off”选择功能,让用户在一组选择项目中作选择. 选择框 选择框(J ...

  9. Java知IO

    ---恢复内容开始--- Java将IO(文件.网络.终端)封装成非常多的类,看似繁杂,其实每个类的具有独特的功能. 按照存取的对象是二进制还是文本,java使用字节流和字符流实现IO. 流是java ...

随机推荐

  1. Project_Lemon测评系统使用经验

    Project_Lemon使用经验 如果您还没有安装Project_Lemon,那么请移步https://www.cnblogs.com/CreeperLKF/p/9201859.html去查阅安装教 ...

  2. 洛谷.2292.[HNOI2004]L语言(Trie DP)

    题目链接 /* 简单的DP,查找是否有字典中的单词时在Trie树上做 要注意在最初Match(0)一遍后,i还是要从0开始匹配,因为如果有长度为1的单词,Match(i+1)不会从1更新 1M=102 ...

  3. 闪烁的LED灯

    /* Main.c file generated by New Project wizard * * Created: 周五 五月 5 2017 * Processor: 80C31 * Compil ...

  4. 2017-2018-2 1723 『Java程序设计』课程 结对编程练习_四则运算第三周总结

    相关测试过程截图 测试了由中缀表达式转后缀表达式的Junit测试,分别进行了整数的和分数的,测试成功截图 由于生成问题和计算问题中,问题都是随机产生的,暂时不会进行Junit测试,故没有进行,但应是正 ...

  5. jquery终止函数

    jQuery如何退出each循环?如何退出function函数?1.在函数内部使用return false是跳出function;在each的回调函数中使用return false,是跳出each循环 ...

  6. Spark MLlib 之 aggregate和treeAggregate从原理到应用

    在阅读spark mllib源码的时候,发现一个出镜率很高的函数--aggregate和treeAggregate,比如matrix.columnSimilarities()中.为了好好理解这两个方法 ...

  7. Zookeeper学习笔记——2 Shell和Java API的使用

    ZooKeeper的使用一般都接触不到,因为平时工作甚少直接使用ZK.但是通过手动操作一下ZK,还是能对其中的门道了解各一二. shell 常用命令 help 查看所有支持的命令 [zk: local ...

  8. Windows下USB磁盘开发系列一:枚举系统中U盘的盘符

    个时候我们需要区分系统磁盘中,哪些是U盘,这样我们在访问的时候可以区别对待.具体方法如下: 1,调用GetLogicalDrives()返回系统盘符标记位 API GetLogicalDrives() ...

  9. hdu4607Park Visit 树的直径

    //给一棵双向树,数中边的权值为1,问对于这颗树中走k个节点的最短路径 //假设k小于这颗数的直径加1,那么走k个节点就没有反复的路,假设大于 //那么大于的节点都须要走两遍 #include< ...

  10. [leetcode]Permutation Sequence @ Python

    原题地址:https://oj.leetcode.com/submissions/detail/5341904/ 题意: The set [1,2,3,…,n] contains a total of ...