1、在程序中设定路径时会有系统相依性的问题,java.io.File类提供一个抽象的、与系统独立的路径表示。
给它一个路径字符串,它会将其转换成与系统无关的抽象路径表示,这个路径可以指向一个文件、目录或是URL。
一个File的实例被建立时,它就不能再被改变内容。
要注意的是:不管是文件还是目录,在Java中都是以File的实例来表示。
下面是个操作File实例的简单示例,可以指定查询某个目录下的所有文件和目录名称。
Java中将数据于目的地及来源之间的流动抽象化为一个流(Stream),而流中流动的则是位数据。
InputStream是所有表示位输入流的类之父类,是一个抽象类!
InputStream是从装置来源地读取数据的抽象表示,例如System中的标准输入流in就是一个InputStream类型的实例。
OutputStream是所有表示位输出流的类之父类,是一个抽象类!
OutputStream是将数据写入目的地的抽象表示,例如System中的标准输出流对象out其类型是java.io.PrintStream,
这个类是OutputStream的子类(java.io.FilterOutputStream继承OutputStream,PrintStream再继承FilterOutputStream)。
范例如下:
4、FileInputStream 和 FileOutputStream
FileInputStream是InputStream的子类,从指定的文件中读取数据至目的地;
FileOutputStream是OutputStream的子类,从来源地写入数据至指定的文件。
当建立FileInputStream或FileOutputStream实例时,必须指定文件位置及文件名称,实例被建立时文件的流就会开启;
而不使用流时,必须关闭文件流,以释放与流相依的系统资源,完成文件读/写的动作。
FileInputStream可以使用read()方法一次读入一个字节,并以int类型返回,
或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少个字节。
在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区。
下面的例子实现复制文件:先从来源文件读取数据至byte数组,再将byte数组的数据写入目的文件。
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数据写至目的地,而不是每次都对目的地作写入的动作。
下面这个范例同样实现复制文件,但不用自行设定缓冲区:
要注意的是: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_原文件名”。
若想要存取的是一个文本文件,可以直接使用FileReader和FileWriter类,它们分别继承自InputStreamReader和OutputStreamWriter。
可以直接指定文件名或File对象来打开指定的文本文件,并读入流转换后的字符,字符的转换会根据系统默认的编码。
下面的范例,可以读入Linux下编写的文本文件,再写入另一个文件,
在读取过程中若遇到\n字符,就取代为\r和\n连个连续字符,这样新的文件在Windows中显示时,就有断行效果。
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字符即可。
给它一个路径字符串,它会将其转换成与系统无关的抽象路径表示,这个路径可以指向一个文件、目录或是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();
}
}
}