Java程序设计输入输出

Posted BkbK-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java程序设计输入输出相关的知识,希望对你有一定的参考价值。

输入输出

在这里插入图片描述

一、输入输出的概念

(1)I/O (Input/Output)流

  • Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。

  • Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。

  • 一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。

  • Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中

(2)I/O流分类

输入流和输出流的类层次图:
在这里插入图片描述

  • 从流的方向划分
    ▫ 输入流
    ▫ 输出流
  • 从流的分工划分
    ▫ 节点流
    ▫ 处理流
  • 从流的内容划分
    ▫ 面向字符的流
    ▫ 面向字节的流

1.面向字符的流

在这里插入图片描述

针对字符数据的特点进行过优化,提供一些面向字符的有用特性。
源或目标通常是文本文件;
实现内部格式和文本文件中的外部格式之间转换。

  • java.io包中所有字符流的抽象超类。
    • Reader提供了输入字符的API。
    • Writer提供了输出字符的API。
  • Reader、Writer的子类又可分为两大类
    • 节点流:从数据源读入数据或往目的地写出数据;
    • 处理流:对数据执行某种处理。
  • 多数程序使用这两个抽象类的一系列子类来读入/写出文本信息
    • 例如FileReader/FileWriter用来读/写文本文件。

2.面向字节的流

在这里插入图片描述

• 数据源或目标中含有非字符数据,必须用字节流来输入/输出
• 通常被用来读写诸如图片、声音之类的二进制数据
• 绝大多数数据是被存储为二进制文件的,通常二进制文件要比含有相同数据量的文本文件小得多

(3)标准输入输出流对象

System类的静态成员变量:

  • System.in: InputStream类型的,代表标准输入流,默认状态对应于键盘输入。
  • System.out:PrintStream类型的,代表标准输出流,默认状态对应于显示器输出。
  • System.err:PrintStream类型的,代表标准错误信息输出流,默认状态对应于显示器输出。

(4)标准输入/输出重新定向

  • setIn(InputStream): 设置标准输入流
  • setOut(PrintStream):设置标准输出流
  • setErr(PrintStream):设置标准错误输出流

例:标准输入/输出重定向(复制文件)

import java.io.*;
public class Redirecting {
	public static void main(String[] args) throws IOException {
		BufferedInputStream in = new BufferedInputStream(
		new FileInputStream( "Redirecting.java"));
		PrintStream out = new PrintStream( new 
		BufferedOutputStream( new FileOutputStream("test.out")));
		System.setIn(in); System.setOut(out); System.setErr(out);
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s;
		while((s = br.readLine()) != null) System.out.println(s);
		in.close();
		out.close();
	}
}

(5)键盘输入输出

  • System.in
    程序启动时由Java系统自动创建的流对象,它是原始的字节流,不能直接从中读取字符,需要对其进行进一步的处理

  • InputStreamReader(System.in)
    以System.in为参数创建一个InputStreamReader流对象,相当于字节流和字符流之间的一座桥梁,读取字节并将其转换为字符

  • BufferedReader in
    对InputStreamReader处理后的信息进行缓冲,以提高效率

  • printX

    System.out.printf()
    
    System.out.println()
    
  • Scanner:
    一个方便的扫描API: 把文本转化成基本类型或者String

    Scanner s = new Scanner(System.in);
    int n = s.nextInt();
    

    还有下列方法:nextByte(),nextDouble(),nextFloat(),nextInt(),nextLine(),nextLong(),nextShort().

从键盘读入信息并在显示器上显示

import java.io.*;
public class Echo {
    public static void main(String[] args)  throws IOException {
        BufferedReader in = new BufferedReader(
                                        new InputStreamReader(System.in));
        String s;
        while((s = in.readLine()).length() != 0)
           System.out.println(s);
      }
  } 

二、文件读写

(1)写文本文件

1.写文本文件相关的类

  • FileWriter类

    (见附录)

  • BufferedWriter类

    • 如果需要写入的内容很多,就应该使用更为高效的缓冲器流类BufferedWriter

    • FileWriter和BufferedWriter类都用于输出字符流,包含的方法几乎完全一样,但BufferedWriter多提供了一个newLine()方法用于换行

    • 默认缓冲区大小构造字符缓冲输出流对象
      BufferedWriter(Writer out) :

    • 指定缓冲区大小

      BufferedWriter(Writer out,int size):
      

      out通常是类java.io.FileWriter的实例对象

      File file = new File("D:/Files/buffered.txt");
      Writer writer = new FileWriter(file);
      BufferedWriter bw = new BufferedWriter(writer);
      

2.写文本文件

import java.io.*;   
class FileWriterTester {
  public static void main ( String[] args ) {
    String fileName = "c:\\\\Hello.txt" ;
    try {  //将所有IO操作放入try块中
  	   FileWriter writer = new FileWriter( fileName ,true );
 	   writer.write( "Hello!\\n");  
    	   writer.write( "This is my first text file,\\n"  );  
    	   writer.write( "You can see how this is done. \\n" );
        writer.write("输入一行中文也可以\\n");
     	 writer.close();
    }
    catch ( IOException iox) { 
        System.out.println("Problem writing" + fileName ); }
    }
}
  • 运行此程序,会发现在原文件内容后面又追加了重复的内容,这就是将构造方法的第二个参数设为true的效果

  • 如果将文件属性改为只读属性,再运行本程序,就会出现IO错误,程序将转入catch块中,给出出错信息

  • 在给出文件名的情况下构造 FileWriter 对象,它具有指示是否追加写入数据的 boolean 值。

    FileWriter(String fileName, boolean append)
    

(2)读文本文件

1.读文本文件相关的类

  • FileReader类:
    • 从文本文件中读取字符。
    • 继承自Reader抽象类的子类InputStreamReader
  • BufferedReader
    • 读文本文件的缓冲器类。
    • 具有readLine()方法,可以对换行符进行鉴别,一行一行地读取输入流中的内容。
    • 继承自Reader。

2.读文本文件并显示在屏幕上

文件输入方法:

BufferedReader in = new BufferedReader(new FileReader( fileName) );

在这里插入图片描述

import java.io.*;
class BufferedReaderTester {
	public static void main ( String[] args ) {
		String fileName = "C:/Hello.txt" , line;
		try {
			BufferedReader in = new BufferedReader(new FileReader( fileName ) );
			line = in.readLine(); //读取一行内容
			while ( line != null ) { 
			System.out.println( line ); line = in.readLine();
			}
			in.close(); 
		}
		catch ( IOException iox ) { 
			System.out.println("Problem reading " + fileName );
		}
	} 
}
  • 运行该程序,屏幕上将逐行显示出Hello.txt文件中的内容。

  • FileReader对象:创建后将打开文件,如果文件不存在,会抛出一个IOException

  • BufferedReader类的readLine()方法:从一个面向字符的输入流中读取一行文本。如果其中不再有数据,返回null

  • Reader类的read()方法:也可用来判别文件结束。该方法返回的一个表示某个字符的int型整数,如果读到文件末尾,返回 -1。据此,可修改本例中的读文件部分:

    int c;
    while((c=in.read())!= -1) System.out.print((char)c);
    
  • close()方法:为了操作系统可以更为有效地利用有限的资源,应该在读取完毕后,调用该方法

(3)写二进制文件

将三个int型数字255/0/-1写入数据文件data1.dat

import java.io.*; 
class FileOutputstreamTester {
  public static void main ( String[] args ) { 
    String fileName = "c:/data1.dat" ;
     int value0  = 255, value1  = 0, value2 = -1;
     try {
        DataOutputStream out = new DataOutputStream(
                                        new FileOutputStream( fileName  ) );
        out.writeInt( value0 );
        out.writeInt( value1 );
        out.writeInt( value2 );
        out.close();
      }
      catch ( IOException iox ){
     	 System.out.println("Problem writing " + fileName );   }
      }
 }
  • 运行结果
    • 运行程序后,在C盘生成数据文件data1.dat
    • 用写字板打开没有任何显示
    • 用ultraEdit打开查看其二进制信息,内容为00 00 00 FF 00 00 00 00 FF FF FF FF,每个int数字都是32个bit的
  • 说明
    • FileOutputStream类的构造方法负责打开文件“data1.dat”用于写数据
    • FileOutputStream类的对象与DataOutputStream对象连接,写基本类型的数据

向文件中写入各种数据类型的数,并统计写入的字节数

import java.io.*; 
class BufferedOutputStreamTester {
  public static void main ( String[] args ) throws IOException {
    	String fileName = "mixedTypes.dat" ;
    	DataOutputStream dataOut = new DataOutputStream(
                             new BufferedOutputStream(
                               new FileOutputStream( fileName  ) ) );
    	dataOut.writeInt( 0 );
    	System.out.println( dataOut.size()  + " bytes have been written.");
    	dataOut.writeDouble( 31.2 );
    	System.out.println( dataOut.size()  + " bytes have been written.");
    	dataOut.writeBytes("JAVA");
    	System.out.println( dataOut.size()  + " bytes have been written.");
    	dataOut.close();
  }
}
  • 运行结果

    4 bytes have been written
    12 bytes have been written
    16 bytes have been written

  • BufferedOutputStream

    • 写二进制文件的缓冲流类
    • 类似于文本文件中的BufferedWriter
    • 对于大量数据的写入,可提高效率
    • 用法示例:
      DataOutputStream out = new DataOutputStream( 
                          new BufferedOutputStream( 
                 new FileOutputStream( fileName ) ) );
      

(4)读二进制文件

读取例上一个创建的数据文件中的3个int型数字,显示相加结果

import java.io.*;
class DataInputStreamTester {
	public static void main ( String[] args ) {
    	   String fileName = "c:\\\\data1.dat";
    	   int sum = 0;
        try {
           DataInputStream instr = new DataInputStream(
            new BufferedInputStream(new FileInputStream( fileName )));
           sum += instr.readInt();
            sum += instr.readInt();  
            sum += instr.readInt();
            System.out.println( "The sum is: " + sum );
            instr.close();
        }
    	   catch ( IOException iox ) {
    	        System.out.println("Problem reading " + fileName ); }
  	   }
    }
}
  • 该程序显示结果是254
  • 分析:
    • readInt方法可以从输入流中读入4个字节并将其当作int型数据
    • 由于知道文件中存储的是3个int型数据,所以使用了3个读入语句
    • 如果不知道数据的个数该怎么办呢?因为DataInputStream的读入操作如遇到文件结尾就会抛出EOFException异常,所以我们可以将读操作放入try块中
  • 过滤流
    • 读或写的同时对数据进行处理
    • 通过另外一个流来构造一个过滤流
    • 大部分java.io 包所提供过滤流都是FilterInputStream和FilterOutputStream的子类
      • DataInputStream 和 DataOutputStream
      • BufferedInputStream 和 BufferedOutputStream
      • LineNumberInputStream
      • PushbackInputStream
      • PrintStream

附:输入输出的重要类

(1)Java Scanner 类

java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。

Scanner s = new Scanner(System.in);
  • next 方法
    1、一定要读取到有效字符后才可以结束输入。
    2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
    3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
    next() 不能得到带有空格的字符串。

    import java.util.Scanner; 
     
    public class ScannerDemo {
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            // 从键盘接收数据
     
            // next方式接收字符串
            System.out.println("next方式接收:");
            // 判断是否还有输入
            if (scan.hasNext()) {
                String str1 = scan.next();
                System.out.println("输入的数据为:" + str1);
            }
            scan.close();
        }
    }
    

    next方式接收:
    runoob com
    输入的数据为:runoob

  • nextLine 方法
    1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
    2、可以获得空白。

    import java.util.Scanner;
     
    public class ScannerDemo {
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            // 从键盘接收数据
     
            // nextLine方式接收字符串
            System.out.println("nextLine方式接收:");
            // 判断是否还有输入
            if (scan.hasNextLine()) {
                String str2 = scan.nextLine();
                System.out.println("输入的数据为:" + str2);
            }
            scan.close();
        }
    }
    

    nextLine方式接收:
    runoob com
    输入的数据为:runoob com

  • nextXxx()方法
    如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:

import java.util.Scanner;
 
public class ScannerDemo {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        // 从键盘接收数据
        int i = 0;
        float f = 0.0f;
        System.out.print("输入整数:");
        if (scan.hasNextInt()) {
            // 判断输入的是否是整数
            i = scan.nextInt();
            // 接收整数
            System.out.println("整数数据:" + i);
        } else {
            // 输入错误的信息
            System.out.println("输入的不是整数!");
        }
        System.out.print("输入小数:");
        if (scan.hasNextFloat()) {
            // 判断输入的是否是小数
            f = scan.nextFloat();
            // 接收小数
            System.out.println("小数数据:" + f);
        } else {
            // 输入错误的信息
            System.out.println("输入的不是小数!");
        }
        scan.close();
    }
}

运行样例:

输入整数:1.2
输入的不是整数!
输入小数:小数数据:1.2

输入整数:12
整数数据:12
输入小数:1.2
小数数据:1.2

(2)Java File类

Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

1.创建对象

File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象:

  • 通过给定的父抽象路径名和子路径名字符串创建一个新的File实例

    File(File parent, String child);
    
  • 通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例

    File(String pathname) 
    
  • 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例

    File(String parent, String child) 
    
  • 通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例

    File(URI uri)
    

2.其他操作

public String getName()

返回由此抽象路径名表示的文件或目录的名称。

public String getParent()

返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null。

public File getParentFile()

返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null。

public String getPath()

将此抽象路径名转换为一个路径名字符串。

public boolean isAbsolute()

测试此抽象路径名是否为绝对路径名。

public String getAbsolutePath()

返回抽象路径名的绝对路径名字符串。

以上是关于Java程序设计输入输出的主要内容,如果未能解决你的问题,请参考以下文章

java代码在片段活动中不起作用

java输入输出程序代码

(转) Java中的负数及基本类型的转型详解

顶点着色器+片段着色器

求java程序,输入数字,输出相应行数的金字塔星星

C ++ 11 int8_t buggy输入/输出