流
文件
文件分类
- 文本文件
- 文件内容为ascii编码或unicode编码的字符序列
- 二进制文件
- 其他非文本文件都可以看做二进制文件,二进制文件在进行处理时,通常是按字节来处理的。
- 文本文件也可以当做二进制文件处理,但二进制文件通常只按二进制文件而不当做文本文件处理。
File类
- File以一种系统无关的方式表示一个文件对象的属性。目录在Java中作为一种特殊的文件。此类的实例可能表示(也可能不表示)实际文件系统对象,如文件或目录。
- File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变,这就像String对象一样。
- File 类封装了对文件系统进行操作的功能。其对象属性包含了文件或目录的相关信息。
- File类关心的是文件在磁盘上的存储,而不是文件的内容。
名称分隔符
在不同的操作系统中,目录结构中的不同层次的分隔符不同,比如在类Unix操作系统中,文件名的分隔符为/,在Windows系统中,文件名的分隔符为\。由于\同转义符的前导符\相同,我们在java中在表示该符号的时候,我们写作'\\'。
因为Java是跨平台的编程语言,所以在File中定义了两个属性,分别为:public static final String separator和public static final char separatorChar,一个是字符串的表示,一个是字符的表示,在Unix系统中分别为:"/"、'/',在Windows中为:"\\"、'\\',我们在编写程序的时候是不需要关注它的具体值的。
路径分隔符
同样,在不同的操作系统中,路径之间的分隔符也是不同的,在类Unix操作系统中,路径的分隔符为:,在Windows系统,路径的分隔符为;。在File中也定义了两个属性,分别为:public static final String pathSeparator和public static final char pathSeparatorChar,同样一个是字符串的表示,一个是字符的表示。
路径的Parent
在Java中,看待路径和文件是统一的,都可以当作File,它的Parent由路径名前缀以及路径名名称序列中的每个名称(最后一个除外)组成,例如:"file://usr/local/bin"的Parent既是"file://usr/local。
File的构造方法
File(File parent, String child)根据parent和child路径名字符串创建一个新File实例。如果parent为null,则创建一个新的File实例,这与调用给定child路径名字符串的单参数File构造方法的效果一样。如果child参数为null,抛出NullPointerException异常File(String pathname)通过将给定路径名字符串来创建一个新File实例。如果pathname参数为null,抛出NullPointerException异常File(String parent, String child)根据parent路径名字符串和child路径名字符串创建一个新File实例。如果parent为null,则创建一个新的File实例,这与调用给定child路径名字符串的单参数File构造方法的效果一样。如果child参数为null,抛出NullPointerException异常File(URI uri)通过将给定的file: URI来创建一个新的File实例。如果uri参数为null,抛出NullPointerException异常,如果关于参数的前提不成立,抛出IllegalArgumentException异常
示例: 例1
String path="d:\\java\\";
File f1=new File(path,"old.txt");
例2
File f1=new File("d:\\java\\old.txt");
例3
String path="d:\\java\\";
File f1=new File(path);
File f2=new File(f1, "old.txt");
File中常用的方法
见JDK说明书
流
流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件、内存、或是网络连接。凡是从外部设备流向中央处理器CPU的数据流,称为输入流,如图:
类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,凡是从中央处理器CPU流向外部设备的数据流,称为输出流,如图:
Java流中流动的数据有两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。抽象类InputStream,OutputStream处理字节流;抽象类Reader,Writer处理字符流。Java中其他多种多样变化的流均是由它们派生继承来的。
针对字符流的类基本上都有与之相对应的字节流类。两个对应类实现的功能相似,只是在操作时不同。例如: CharArrayReader和ByteArrayInputStream的作用都是把流中的数据读入内存中的一个缓冲区,所不同的是前者是把字符数组作为缓冲区,而后者是把字节数组作为缓冲区。
InputStreamReader和OutputStreamWriter:把字节流转换成一个字符流。
对文件进行读写
与文件的输入输出相关的类有:FileInputStream、FileOutputStream、FileReader、FileWriter,前两个是将文件的内容看作是字节流,后两个将文件看作字符流。
示例1:
/**************************************
*下面的示例将文本文件的内容输出到屏幕 *
**************************************/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
class ReadFromFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String sBuffer;
try {
while ((sBuffer = br.readLine()) != null) {
System.out.println(sBuffer);
}
} catch (Exception e) {}
finally {
try {
br.close();
} catch (Exception e) {
}
}
} catch (Exception e) {
}
}
}
示例2:
/********************************************
*下面的示例将键盘中键入的内容存入文本文件中 *
********************************************/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
class WriteToFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
String sBuffer;
try {
while ((sBuffer = br.readLine()) != null) {
bw.write(sBuffer);
bw.newLine();
}
} catch (Exception e) {}
finally {
try {
br.close();
bw.close();
} catch (Exception e) {
}
}
} catch (Exception e) {
}
}
}
基本数据的输入输出
数据输入输出流允许应用程序以与机器无关方式读取或写入基本 Java 数据类型,包含两个类:DataInputStream、DataOutputStream。
示例1:
/********************************************
*本例将几个基本类型的数据存入文件中 *
********************************************/
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.File;
class WriteDataToFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
try {
dos.writeBoolean(true);
dos.writeBoolean(false);
dos.write(12);
dos.writeShort(12);
dos.writeInt(12);
dos.writeLong(12);
dos.writeChar('A');
//dos.writeChars("abc");
dos.writeFloat(1.2f);
dos.writeDouble(1.2);
} catch (Exception e) {
} finally {
try {
dos.close();
} catch (Exception e) {
}
}
} catch (Exception e) {
}
}
}
示例2:
/**********************************************
*本例将基本类型的数据从文件中读出并输出到屏幕 *
**********************************************/
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.File;
class ReadDataFromFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
DataInputStream dis = new DataInputStream(new FileInputStream(file));
try {
System.out.println(dis.readBoolean());
System.out.println(dis.readBoolean());
System.out.println(dis.read());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readChar());
//System.out.println(dis.readChars());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
//System.out.println(dis.readInt());
} catch (Exception e) {
} finally {
try {
dis.close();
} catch (Exception e) {
}
}
} catch (Exception e) {
}
}
}
对象的输入输出
在java中,不仅仅基本类型的数据可以在流中流动,我们还可以对实例数据进行输入输出。如果某个类的对象需要在流中流动,则该类必须进行序列化与反序列化。所谓对象序列化是把一个对象转换为字节流,反序列化就是把字节流转化为对象。为了实现这个目的,这个类需要实现Serializable接口。
示例1:
/********************************************
*本例将对象数据存入文件中 *
********************************************/
import java.io.File;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
class WriteObjectToFile {
public static void main(String[] args) {
File file = new File(args[0]);
Person p1 = new Person("tom", "01", 20);
Person p2 = new Person("Jerry", "02", 21);
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
try {
oos.writeObject(p1);
oos.writeObject(p2);
} catch (Exception e) {
try {
oos.close();
} catch (Exception e1) {
}
}
} catch (Exception e) {
}
}
}
class Person implements Serializable {
String name;
String id;
/*transient*/ int age;
public Person(String name, String id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String toString() {
return "name = " + name + ", id= " + id + ",age = " + age;
}
}
示例2:
/********************************************
*本例将对象数据存入文件中 *
********************************************/
import java.io.File;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.Serializable;
class ReadObjectFromFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
ObjectInputStream ios = new ObjectInputStream(new FileInputStream(file));
try {
Person person;
while ((person = (Person)ios.readObject()) != null)
System.out.println(person);
} catch (Exception e) {
try {
ios.close();
} catch (Exception e1) {
}
}
} catch (Exception e) {
}
}
}
class Person implements Serializable {
String name;
String id;
int age;
public Person(String name, String id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String toString() {
return "name = " + name + ", id= " + id + ",age = " + age;
}
}
管道的输入输出
管道流是JAVA中线程通讯的常用方式之一,基本流程如下:
- 创建管道输出流
PipedOutputStream pos和管道输入流PipedInputStream pis - 将
pos和pis匹配,pos.connect(pis); - 将
pos传递给输入数据线程,pis传递给获取数据线程,就可以实现线程间的通讯了
管道流只能实现单向发送,如果要两个线程之间互通讯,则需要两个管道流
示例:
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipeConnection {
public static void main(String[] args) throws InterruptedException {
/**
* 创建管道输出流
*/
PipedOutputStream pos = new PipedOutputStream();
/**
* 创建管道输入流
*/
PipedInputStream pis = new PipedInputStream();
try {
/**
* 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现
*/
pos.connect(pis);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 创建生产者线程
*/
Producer p = new Producer(pos);
/**
* 创建消费者线程
*/
Consumer c = new Consumer(pis);
/**
* 启动线程
*/
p.start();
c.start();
Thread.sleep(5000);
p.flag = false;
c.flag = false;
}
}
/**
* 生产者线程(与一个管道输入流相关联)
*
*/
class Producer extends Thread {
private PipedOutputStream pos;
boolean flag = true;
public Producer(PipedOutputStream pos) {
this.pos = pos;
}
public void run() {
int i = 0;
try {
while (flag) {
this.sleep(1000);
pos.write(i);
System.out.println("Producer:" + i);
i++;
}
} catch (Exception e) {
//e.printStackTrace();
}
}
}
/**
* 消费者线程(与一个管道输入流相关联)
*
*/
class Consumer extends Thread {
private PipedInputStream pis;
boolean flag = true;
public Consumer(PipedInputStream pis) {
this.pis = pis;
}
public void run() {
try {
while (flag) {
System.out.println("consumer:" + pis.read());
}
} catch (IOException e) {
//e.printStackTrace();
}
}
}
输入流的逻辑串联
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达流末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
该类有两个构造方法:
public SequenceInputStream(Enumeration<? extends InputStream> e)通过将需要串联的流通过Enumeration类型的参数,传递给新建的SequenceInputStream对象。将按顺序读取由该枚举参数生成的输入流,当用尽枚举中的每个输入流之后,将通过调用该流的 close 方法将其关闭。public SequenceInputStream(InputStream s1, InputStream s2)通过将需要串联的流以两个形式参数来创建新的的SequenceInputStream对象,将按顺序读取这两个参数,先读取 s1,然后读取 s2。
示例1:
/*
* 本例合并两个文件的内容到一个新的文件中,三个文件的名字由命令行参数指定
* 第一、二为需合并的文件的文件名
* 第三个为合并成的文件名字
*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.SequenceInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
public class CombineFile{
public static void main(String[] args) throws FileNotFoundException, IOException{
FileInputStream fis1 = new FileInputStream(args[0]);
FileInputStream fis2 = new FileInputStream(args[1]);
FileOutputStream fos = new FileOutputStream(args[2]);
SequenceInputStream sis = new SequenceInputStream(fis1, fis2);
int temp;
while((temp = sis.read())!=-1){
fos.write(temp);
}
sis.close();
fos.close();
}
}
PrintStream
PrintStream 类可以把数据以字符的形式打印到流中,比如System.out就是该类类型。该类中提供了print、println及printf等方法,与其他输出流不同,PrintStream 永远不会抛出 IOException。
PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
示例:
/********************************************
*本例将几个基本类型的数据以文本存入文件中 *
********************************************/
import java.io.PrintStream;
import java.io.File;
class PrintDataToFile {
public static void main(String[] args) {
File file = new File(args[0]);
try {
PrintStream ps = new PrintStream(file);
ps.print(true);
ps.print(false);
ps.print(12);
ps.print(12L);
ps.print('A');
ps.print("abc");
ps.print(1.2f);
ps.print(1.2);
} catch (Exception e) {
}
}
}
问题
- java dir 路径
- java dir 路径 文件后缀
- java mkdir 路径
- java rmdir 路径
- java copy 源文件 目的文件