9、输入输出

1、在程序中设定路径时会有系统相依性的问题,java.io.File类提供一个抽象的、与系统独立的路径表示。
   给它一个路径字符串,它会将其转换成与系统无关的抽象路径表示,这个路径可以指向一个文件、目录或是URL。
 
   一个File的实例被建立时,它就不能再被改变内容。
   要注意的是:不管是文件还是目录,在Java中都是以File的实例来表示。
   
   下面是个操作File实例的简单示例,可以指定查询某个目录下的所有文件和目录名称。
import java.util.Scanner;
import java.util.ArrayList;
import java.io.File;


public class Main
{
	public static void main(String[] args)
	{
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入文件路径");
		String path = scanner.next();


		try
		{
			File file = new File(path);


			if(file.isFile())  //是否是文件
			{
				System.out.println(path + " 文件");
				System.out.print(file.canRead() ? "可读 " : "不可读 ");
				System.out.print(file.canWrite() ? "可写 " : "不可写 ");
				System.out.println(file.length() + "字节");
			}
			else
			{
				//列出所有的文件及目录
				File[] files = file.listFiles();
				ArrayList<File> fileList = new ArrayList<File>();


				for(int i = 0; i < files.length; i++)
				{
					//先列出目录
					if(files[i].isDirectory())  //是否为目录
					{
						System.out.println("[" + files[i].getPath() + "]");
					}
					else
					{
						//文件先存入fileList,待会再列出
						fileList.add(files[i]);
					}
				}


				//列出文件
				for(File f : fileList)
					System.out.println(f.toString());
				System.out.println();
			}
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("using: java FileDemo pathname");
		}
	}
}

2、位流

   计算机中的数据都是以0,1存储,如果在两个装置间进行数据的存取,当然也是0,1进行;
   Java中将数据于目的地及来源之间的流动抽象化为一个流(Stream),而流中流动的则是位数据。

3、Inputstream和OutputStream

   在J2SE中有两个类用来作流的抽象表示:java.io.InputStream和java.io.OutputStream。
   InputStream是所有表示位输入流的类之父类,是一个抽象类!
   InputStream是从装置来源地读取数据的抽象表示,例如System中的标准输入流in就是一个InputStream类型的实例。
   OutputStream是所有表示位输出流的类之父类,是一个抽象类!
   OutputStream是将数据写入目的地的抽象表示,例如System中的标准输出流对象out其类型是java.io.PrintStream,
   这个类是OutputStream的子类(java.io.FilterOutputStream继承OutputStream,PrintStream再继承FilterOutputStream)。
   
   范例如下:

import java.io.*;
public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			System.out.print("输入字符:");
			System.out.println("输入字符十进制表示: " + System.in.read());
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}

   一般很少直接实现InputStream或OutputStream上的方法,通常是实现它们的子类。

4、FileInputStream 和 FileOutputStream
    
   FileInputStream是InputStream的子类,从指定的文件中读取数据至目的地;
   FileOutputStream是OutputStream的子类,从来源地写入数据至指定的文件。
   
   当建立FileInputStream或FileOutputStream实例时,必须指定文件位置及文件名称,实例被建立时文件的流就会开启;
   而不使用流时,必须关闭文件流,以释放与流相依的系统资源,完成文件读/写的动作。
   
   FileInputStream可以使用read()方法一次读入一个字节,并以int类型返回,
   或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少个字节。
   在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区。
   
   下面的例子实现复制文件:先从来源文件读取数据至byte数组,再将byte数组的数据写入目的文件。
import java.io.*;
import java.util.Scanner;

public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			byte[] buffer = new byte[1024];
			Scanner scanner = new Scanner(System.in);


			//Source File
			System.out.println("输入来源文件:");
			String sourceFile = scanner.next();
			//通过打开一个到实际文件的连接来实例化
			FileInputStream fileInputStream = new FileInputStream(new File(sourceFile));


			//Destination File
			System.out.println("输入目的文件:");
			String desFile = scanner.next();
			FileOutputStream fileOutputStream = new FileOutputStream(new File(desFile));


			//available()可取得未读取的数据长度
			System.out.println("复制文件:" + fileInputStream.available() + "字节");


			while(true)
			{
				if(fileInputStream.available() < 1024)
				{
					//一位一位读出再写入目的文件
					int remain = -1;
					//读不到数据返回-1
					while((remain = fileInputStream.read()) != -1)
					{
						fileOutputStream.write(remain);
					}
					break;
				}
				else
				{
					//从来源文件读取至缓冲区
					fileInputStream.read(buffer);
					//将数据写入目的文件
					fileOutputStream.write(buffer);
				}
			}


			//关闭流
			fileInputStream.close();
			fileOutputStream.close();


			System.out.println("复制完成");


		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("using: Java FileStreamDemo src des");
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
   除了使用File来建立FileInputStream、FileOutputStream的实例之外,也可以直接使用字符串路径来建立。
   FileOutputStream默认会以新建文件的方式来开启流,如果指定的文件名称已经存在,则原文件会被覆盖;
   如果想以append(附加)的模式来写入文件,则可以在构建FileOutputStream实例时指定为附加模式。
   
5、BufferedInputStream 和 BufferedOutputStream
   
   BufferedInputStream和BufferedOutputStream可以为InputStream、OutputStream类的对象增加缓冲区功能。
   构建BufferedInputStream实例时,需要给定一个InputStream类型的实例,实现BufferedInputStream,实际上最后是实现InputStream实例;
   BufferedOutputStream同样如此。
   
   BufferedInputStream的数据成员buf是一个位数组,默认为2048个字节。
   当读取数据来源时,例如文件,BufferedInputStream会尽量将buf填满。
   当使用read()方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取,因为硬盘存取速度远低于内存;
   当buf中的数据不足时,BufferedInputStream才会再实现给定的InputStream对象的read()方法,从指定装置读取数据。
   File -> FileInputStream -> buf -> Object
   
   BufferedOutputStream的数据成员是一个位数组,默认为512个字节。
   当使用write()方法写入数据时,实际上会先将数据写至buf中,当buf已满时才会实现给定的OutputStream对象的write()方法,
   将buf数据写至目的地,而不是每次都对目的地作写入的动作。
 
   下面这个范例同样实现复制文件,但不用自行设定缓冲区:
import java.io.*;
import java.util.Scanner;


public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			byte[] data = new byte[1];
			Scanner scanner = new Scanner(System.in);


			//Source File
			System.out.println("输入来源文件:");
			String srcFilePath = scanner.next();
			File srcFile = new File(srcFilePath);
			BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile));


			//Destination File
			System.out.println("输入目的文件:");
			String desFilePath = scanner.next();
			File desFile = new File(desFilePath);
			BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFile));


			System.out.println("复制文件:" + srcFile.length() + "字节");


			while(bufferedInputStream.read(data) != -1)
			{
				bufferedOutputStream.write(data);
			}


			bufferedOutputStream.flush();


			//关闭流
			bufferedInputStream.close();
			bufferedOutputStream.close();


			System.out.println("复制完成");


		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("using: Java FileStreamDemo src des");
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
   为了确保缓冲区中的数据一定被写出至目的地,建议最后执行flush()将缓冲区中的数据全部写出目的流中。
   要注意的是:BufferedInputStream和BufferedOutputStream并没有改变InputStream和OutputStream的行为!
   读出或写入时的动作还是InputStream和OutputStream负责,只是动态地为它们加上一些额外功能(像缓冲区功能)。   

6、字符流
   
   java.io.Reader、java.io.Writer与其子类是处理字符流的相关类。
   简单地说,就是对流数据以一个字符(两个字节)的长度为单位进行处理,并进行适当的字符编码转换处理。

7、Reader 和 Writer

   java.io.Reader和java.io.Writer在处理流数据时,会根据系统默认的字符编码来进行字符转换;
   Reader和Writer是抽象类,在进行文本文件的字符读写时真正会使用其子类,子类通常会重新定义相关方法。
   
8、InputStreamReader 和 OutputStreamWriter
   
   若想对InputStream和OutputStream进行字符处理,可以使用InputStreamReader和OutputStreamWriter为其加上
   字符处理的功能,它们分别是Reader和Writer的子类。
   举个例子来说,若想要显示纯文本文件的内容,不用费心地自行判断字符编码,只要将InputStream、OutputStream的实例
   作为构建InputStreamReader和OutputStreamWriter时的变量,来进行文本文件的读取,让它们完成字符判断与转换。
   
   下面范例打开一个纯文本文件,显示其中的字符内容,为了示范OutputStreamWriter的功能,范例
   会将文本文件复制为另一个文本文件“backup_原文件名”。
import java.io.*;
import java.util.Scanner;


public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			Scanner scanner = new Scanner(System.in);
			System.out.println("请输入文件:");
			String filePath = scanner.next();


			//打开一个到实际文件的连接来创建一个 FileInputStream,
			//该文件通过文件系统中的路径名指定
			FileInputStream fileInputStream = new FileInputStream(filePath);
			//为FileInputStream加上字符处理功能
			InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);


			FileOutputStream fileOutputStream = new FileOutputStream("backup_" + filePath);
			//为FileOutputStream加上字符处理功能
			OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);


			int ch = 0;
			//以字符方式显示文件内容
			while((ch = inputStreamReader.read()) != -1)
			{
				System.out.print((char)ch);
				outputStreamWriter.write(ch);
			}
			System.out.println();


			inputStreamReader.close();
			outputStreamWriter.close();


		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("没有指定文件");
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
9、FileReader 和 FileWriter

   若想要存取的是一个文本文件,可以直接使用FileReader和FileWriter类,它们分别继承自InputStreamReader和OutputStreamWriter。
   可以直接指定文件名或File对象来打开指定的文本文件,并读入流转换后的字符,字符的转换会根据系统默认的编码。
   
   下面的范例,可以读入Linux下编写的文本文件,再写入另一个文件,
   在读取过程中若遇到\n字符,就取代为\r和\n连个连续字符,这样新的文件在Windows中显示时,就有断行效果。
import java.io.*;
import java.util.Scanner;


public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			Scanner scanner = new Scanner(System.in);
			System.out.println("请输入文件:");
			String filePath = scanner.next();


			FileReader fileReader = new FileReader(filePath);
			FileWriter fileWriter = new FileWriter(filePath + ".txt");


			int in = 0;
			char[] wlnChar = {'\r', '\n'};
			while((in = fileReader.read()) != -1)
			{
				if(in == '\n')
					fileWriter.write(wlnChar);
				else
					fileWriter.write(in);
			}
			fileReader.close();
			fileWriter.close();
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("没有指定文件");
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
10、BufferedReader 和 BufferedWriter
    
BufferedReader和BufferedWriter类各拥有8192字符的缓冲区。
当BufferedReader读取文本文件时,会先从文件读入字符到缓冲区,之后若使用read()方法,会先从缓冲区中读取,
若缓冲区数据不足,才会再从文件中读取;
BufferedWriter写入数据时,先存储到缓冲区,如果缓冲区数据满了,才会对目的地进行写出。

从标准输入流System.in中直接读取输入时,使用者每输入一个字符,System.in就读取一个字符。
为了能一次读取一行使用者的输入,使用了BufferedReader来对输入字符缓冲,
readLine()方法会在读取到使用者的换行字符时,再一次将整行字符串传入。

System.in是一个位流,为了转换字符流,可使用InputStreamReader为其进行字符转换,然后再使用BufferedReader为其增加缓冲功能。
例如:BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

下面范例,在文字模式下输入字符,程序会将输入的文字存储到指定的文件中,如果要结束程序,输入quit字符即可。
import java.io.*;
import java.util.Scanner;


public class Main
{
	public static void main(String[] args)
	{	
		try
		{
			Scanner scanner = new Scanner(System.in);
			System.out.println("请输入文件:");
			String filePath = scanner.next();


			//缓冲System.in输入流
			BufferedReader bufReader = new BufferedReader(new InputStreamReader(System.in));
			//缓冲FileWriter字符输出流
			BufferedWriter bufWriter = new BufferedWriter(new FileWriter(filePath));


			String input = null;


			//每读一行进行一次写入动作
			while(!(input = bufReader.readLine()).equals("quit"))
			{
				bufWriter.write(input);
				//newLine()方法写入与操作系统相依的换行符
				bufWriter.newLine();
			}


			bufReader.close();
			bufWriter.close();
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("没有指定文件");
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值