Java IO(一)
---------------------
File类
所有的IO操作都保存在java.io包中。
在整个IO包中,唯一表示与文件本身有关的类就是File类,使用File类可以进行创建或删除文件等常用操作。要想使用File类,则首先要观察File类的构造方法,此类的常用构造方法如下所示:
publie File(String pathname) 实例化File类的时候,必须设置好路径。
实例操作一:创建一个新文件(使用greateNewFile()方法)
import java.io.File ;
import java.io.IOException ;
public class FileDemo03{
public static void main(String args[]){
File f = new File("d:"+File.separator+"test.txt") ; // 实例化File类的对象
try{
f.createNewFile() ; // 创建文件,根据给定的路径创建
}catch(IOException e){
e.printStackTrace() ; // 输出异常信息
}
}
};
实例操作二:删除一个指定文件
import java.io.File ;
import java.io.IOException ;
public class FileDemo05{
public static void main(String args[]){
File f = new File("d:"+File.separator+"test.txt") ; // 实例化File类的对象
if(f.exists()){ // 如果文件存在则删除
f.delete() ; // 删除文件
}
}
};
实例操作三:综合创建、删除文件的操作
import java.io.File ;
import java.io.IOException ;
public class FileDemo06{
public static void main(String args[]){
File f = new File("d:"+File.separator+"test.txt") ; // 实例化File类的对象
if(f.exists()){ // 如果文件存在则删除
f.delete() ; // 删除文件
}else{
try{
f.createNewFile() ; // 创建文件,根据给定的路径创建
}catch(IOException e){
e.printStackTrace() ; // 输出异常信息
}
}
}
};
实例操作四:创建文件夹
import java.io.File ;
import java.io.IOException ;
public class FileDemo07{
public static void main(String args[]){
File f = new File("d:"+File.separator+"mldn") ; // 实例化File类的对象
f.mkdir() ; // 创建文件夹
}
};
列出指定目妹的全部文件
如果现在给出了一个目录,则可以直接列出目录中的内容。但是列出的方法在File类中存在两个:
以字符串数组的形式返回:public String[] list()
以File数组的形式返回:public File[] listFiles()
操作一:合使list0列出全部内容
import java.io.File ;
import java.io.IOException ;
public class FileDemo08{
public static void main(String args[]){
File f = new File("d:"+File.separator) ; // 实例化File类的对象
String str[] = f.list() ; // 列出给定目录中的内容
for(int i=0;i<str.length;i++){
System.out.println(str[i]) ;
}
}
};
以上只是列出了全部的名字,包括文件夹的名字或是文件的名字等。
操作二:使用listFiles()列出
import java.io.File ;
import java.io.IOException ;
public class FileDemo09{
public static void main(String args[]){
File f = new File("d:"+File.separator) ; // 实例化File类的对象
File files[] = f.listFiles() ; // 列出全部内容
for(int i=0;i<files.length;i++){
System.out.println(files[i]) ;
}
}
};
以上列出的是一个完整的路径,这样对于程序本身来说是很容易操作的。
判断一个给定的路径是否是目录
在File类中直接使用:public boolean isDirectory()
实例:
import java.io.File ;
import java.io.IOException ;
public class FileDemo10{
public static void main(String args[]){
File f = new File("d:"+File.separator) ; // 实例化File类的对象
if(f.isDirectory()){ // 判断是否是目录
System.out.println(f.getPath() + "路径是目录。") ;
}else{
System.out.println(f.getPath() + "路径不是目录。") ;
}
}
};
实例操作:列出指定目录的全部内容
如果给定了一个目录,则要求将此目录中的全部文件都列出来,但是列的时候还会存在子文件夹。分析:应该采用调用形式。
import java.io.File ;
import java.io.IOException ;
public class FileDemo11{
public static void main(String args[]){
File my = new File("d:" + File.separator) ; // 操作路径
print(my) ;
}
public static void print(File file){ // 递归调用
if(file!=null){ // 判断对象是否为空
if(file.isDirectory()){ // 如果是目录
File f[] = file.listFiles() ; // 列出全部的文件
if(f!=null){ // 判断此目录能否列出
for(int i=0;i<f.length;i++){
print(f[i]) ; // 因为给的路径有可能是目录,所以,继续判断
}
}
}else{
System.out.println(file) ; // 输出路径
}
}
}
};
RandomAccessFile类
RandomAccessFile类的主要功能是完成随机读取功能,可以读取指定位置的内容。因为在文件中,所有的内容都是按照字节存放的,都有固定的保存位置。
实例化此类的时候需要传递File类,告诉程序应该操作的是那个文件,之后一个模式,文件的打开模式,常用的两种模式:
r:读模式
w:只写
rw:读写,如果使用此模式,如果文件不存在,则会自动创建。
实例一:
import java.io.File ;
import java.io.RandomAccessFile ;
public class RandomAccessFileDemo01{
// 所有的异常直接抛出,程序中不再进行处理
public static void main(String args[]) throws Exception{
File f = new File("d:" + File.separator + "test.txt") ; // 指定要操作的文件
RandomAccessFile rdf = null ; // 声明RandomAccessFile类的对象
rdf = new RandomAccessFile(f,"rw") ;// 读写模式,如果文件不存在,会自动创建
String name = null ;
int age = 0 ;
name = "zhangsan" ; // 字符串长度为8
age = 30 ; // 数字的长度为4
rdf.writeBytes(name) ; // 将姓名写入文件之中
rdf.writeInt(age) ; // 将年龄写入文件之中
name = "lisi " ; // 字符串长度为8
age = 31 ; // 数字的长度为4
rdf.writeBytes(name) ; // 将姓名写入文件之中
rdf.writeInt(age) ; // 将年龄写入文件之中
name = "wangwu " ; // 字符串长度为8
age = 32 ; // 数字的长度为4
rdf.writeBytes(name) ; // 将姓名写入文件之中
rdf.writeInt(age) ; // 将年龄写入文件之中
rdf.close() ; // 关闭
}
};
以上完成的写入的操作,每条数据的长度都是12位。
实例二:
import java.io.File ;
import java.io.RandomAccessFile ;
public class RandomAccessFileDemo02{
// 所有的异常直接抛出,程序中不再进行处理
public static void main(String args[]) throws Exception{
File f = new File("d:" + File.separator + "test.txt") ; // 指定要操作的文件
RandomAccessFile rdf = null ; // 声明RandomAccessFile类的对象
rdf = new RandomAccessFile(f,"r") ;// 以只读的方式打开文件
String name = null ;
int age = 0 ;
byte b[] = new byte[8] ; // 开辟byte数组
// 读取第二个人的信息,意味着要空出第一个人的信息
rdf.skipBytes(12) ; // 跳过第一个人的信息
for(int i=0;i<b.length;i++){
b[i] = rdf.readByte() ; // 读取一个字节
}
name = new String(b) ; // 将读取出来的byte数组变为字符串
age = rdf.readInt() ; // 读取数字
System.out.println("第二个人的信息 --> 姓名:" + name + ";年龄:" + age) ;
// 读取第一个人的信息
rdf.seek(0) ; // 指针回到文件的开头
for(int i=0;i<b.length;i++){
b[i] = rdf.readByte() ; // 读取一个字节
}
name = new String(b) ; // 将读取出来的byte数组变为字符串
age = rdf.readInt() ; // 读取数字
System.out.println("第一个人的信息 --> 姓名:" + name + ";年龄:" + age) ;
rdf.skipBytes(12) ; // 空出第二个人的信息
for(int i=0;i<b.length;i++){
b[i] = rdf.readByte() ; // 读取一个字节
}
name = new String(b) ; // 将读取出来的byte数组变为字符串
age = rdf.readInt() ; // 读取数字
System.out.println("第三个人的信息 --> 姓名:" + name + ";年龄:" + age) ;
rdf.close() ; // 关闭
}
};
如果要想操作文件内容的话,可以使用RandomAccessFile完成
字节流与字符流
流:在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。流中保存的实际上全都是字节文件。
在java.io包中操作文件内容的主要有两大类:字节流、字符流。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入主要是使用Reader类完成。
操作流程:
1、 使用File类打开一个文件
2、 通过字节流或字符流的子类,指定输出的位置
3、 进行读/写操作
4、 关闭输入/输出
字节流
字节流主要是操作byte类型数据,以byte数组为准,主要操作类就是OutputStream、InputStream。
字节输出流:OutputStream
OutputStream类是整个io包中字节流输出的最大父类,此类的定义如下:
public abstract class OutputStream extends Object implements Closeable,Flushable
从以上的定义中可以发现,此类是一个抽象类,如果要想使用此类的话,则首先必须通过子类实例化对象,那么如果现在要操作的是一个文件,则可以使用:FileOutputStream类。通过向上转型之后,可以为OutputStream实例化。
Clonseable表示可以关闭的操作,因为程序运行到最后肯定要关闭。
Fluashable表示刷新,清空内存中的数据。
实例:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
out.write(b) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
在操作的时候,如果文件本身不存在,则会为用户自动创建新文件。
在操作输出流的时候,也可以使用write(int i)的方法写出数据
实例:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
for(int i=0;i<b.length;i++){ // 采用循环方式写入
out.write(b[i]) ; // 每次只写入一个内容
}
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
以上的操作中在写入数据之后,文件之前的内容已经不存在了,因为在IO操作中默认的情况是将其进行覆盖,那么如果现在要想执行追加的功能,则必须设置追加的操作,找到FileOutputStream类。
实例:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f,true) ; // 此处表示在文件末尾追加内容
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
for(int i=0;i<b.length;i++){ // 采用循环方式写入
out.write(b[i]) ; // 每次只写入一个内容
}
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
程序中想换行的话,使用“\r\n”完成。
字节输入流:InputStream
既然程序可以向文文化人中写入内容,则就可以通过InputStream从文件中把内容读取进来,首先来看InputStream类的定义:
public abstract class InputStream extends Object implements Closeable
与OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,子类肯定是FileInputStream。
实例:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f,true) ; // 此处表示在文件末尾追加内容
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
for(int i=0;i<b.length;i++){ // 采用循环方式写入
out.write(b[i]) ; // 每次只写入一个内容
}
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
现在使用public abstract int read() throws IOException读取内容。
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo04{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[(int)f.length()] ; // 数组大小由文件决定
for(int i=0;i<b.length;i++){
b[i] = (byte)input.read() ; // 读取内容
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流\
System.out.println("内容为:" + new String(b)) ; // 把byte数组变为字符串输出
}
};
以上的操作,只适合于知道输入流的大小时,如果不知道大小应该采取以下操作:
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo05{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ; // 数组大小由文件决定
int len = 0 ;
int temp = 0 ; // 接收每一个读取进来的数据
while((temp=input.read())!=-1){
// 表示还有内容,文件没有读完
b[len] = (byte)temp ;
len++ ;
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流\
System.out.println("内容为:" + new String(b,0,len)) ; // 把byte数组变为字符串输出
}
};
字符流
在程序中一个字符等于2个字节,那么JAVA提供了Reader、Writer两个专门操作字符流的类。
字符输出流:Writer类
Writer本身是一个字符流的输出类,此类的定义如下:
public abstract class Writer extends Object implements Appendable,Closeable,Flushable
此类本身也是一个抽象类,如果想使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,所以应该使用FileWriter的子类。
实例:
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
使用字符流默认情况下依然是覆盖已有的文件,如果想要追加的话,则直接在FileWriter上增加一个可追加的标记即可。
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f,true) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "\r\nLIXINGHUA\r\nHello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
字符输入流:Reader
Reader是使用字符的方式从文件之中取出数据,Reader类的定义如下:
public abstract class Reader extends Object implements Readable,Closeable
Reader本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用FileReader子类。
以字符数组的形式读取出数据:
import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Reader input = null ; // 准备好一个输入的对象
input = new FileReader(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
char c[] = new char[1024] ; // 所有的内容都读到此数组之中
int len = input.read(c) ; // 读取内容
// 第4步、关闭输出流
input.close() ; // 关闭输出流
System.out.println("内容为:" + new String(c,0,len)) ; // 把字符数组变为字符串输出
}
};
也可以使用循环的方式,通过文件是否读到低的形式读取:
import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Reader input = null ; // 准备好一个输入的对象
input = new FileReader(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
char c[] = new char[1024] ; // 所有的内容都读到此数组之中
int temp = 0 ; // 接收每一个内容
int len = 0 ; // 读取内容
while((temp=input.read())!=-1){
// 如果不是-1就表示还有内容,可以继续读取
c[len] = (char)temp ;
len++ ;
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流
System.out.println("内容为:" + new String(c,0,len)) ; // 把字符数组变为字符串输出
}
};
字节流与字符流的区别:
字节流和字符流使用是非常相似的,字节流在操作的时候本身是不会用到缓冲区的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。
通过代码来验证字符流使用到了缓存:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo05{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
out.write(b) ; // 写入数据
// 第4步、关闭输出流
// out.close() ; // 关闭输出流
}
};
在使用字节流操作中,即使没有关闭,最终也是可以输出的:
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
// out.close() ; // 此时,没有关闭
}
};
以上的操作,没有输出任何内容出来,也就是说,所有的内容现在都是保存在了缓冲区之中,而如果执行关闭的时候,会强制性的刷新缓冲区,所以可以把内容输出。
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo04{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.flush() ; // 强制性清空缓冲区中的内容
// out.close() ; // 此时,没有关闭
}
};
问题:开发中是使用字节流好还是字符流好
在所有的硬盘上保存文件或是进行传输的时候都是以字节的方式进行的。包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。
操作范例:文件拷贝
采用边读边写的方式:
import java.io.* ;
public class Copy{
public static void main(String args[]){
if(args.length!=2){ // 判断是否是两个参数
System.out.println("输入的参数不正确。") ;
System.out.println("例:java Copy 源文件路径 目标文件路径") ;
System.exit(1) ; // 系统退出
}
File f1 = new File(args[0]) ; // 源文件的File对象
File f2 = new File(args[1]) ; // 目标文件的File对象
if(!f1.exists()){
System.out.println("源文件不存在!") ;
System.exit(1) ;
}
InputStream input = null ; // 准备好输入流对象,读取源文件
OutputStream out = null ; // 准备好输出流对象,写入目标文件
try{
input = new FileInputStream(f1) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
try{
out = new FileOutputStream(f2) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
if(input!=null && out!=null){ // 判断输入或输出是否准备好
int temp = 0 ;
try{
while((temp=input.read())!=-1){ // 开始拷贝
out.write(temp) ; // 边读边写
}
System.out.println("拷贝完成!") ;
}catch(IOException e){
e.printStackTrace() ;
System.out.println("拷贝失败!") ;
}
try{
input.close() ; // 关闭
out.close() ; // 关闭
}catch(IOException e){
e.printStackTrace() ;
}
}
}
}
字节流与字符汉的转换
OutputStreamWriter和InputStreamReader
在整个io包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换类。
OutputStreamWriter:是Writer的子类,将输出的字符流转变为字节流。
InputStreamReader:是Reader的子类,将输入的字节流变为字符流。
实例:将字节的文件输出汉,以字符的形式输出:
import java.io.* ;
public class OutputStreamWriterDemo01{
public static void main(String args[]) throws Exception { // 所有异常抛出
File f = new File("d:" + File.separator + "test.txt") ;
Writer out = null ; // 字符输出流
out = new OutputStreamWriter(new FileOutputStream(f)) ; // 字节流变为字符流
out.write("hello world!!") ; // 使用字符流输出
out.close() ;
}
};
实例:使用字符流的形式读取字节流的文件
import java.io.* ;
public class InputStreamReaderDemo01{
public static void main(String args[]) throws Exception{
File f = new File("d:" + File.separator + "test.txt") ;
Reader reader = null ;
reader = new InputStreamReader(new FileInputStream(f)) ; // 将字节流变为字符流
char c[] = new char[1024] ;
int len = reader.read(c) ; // 读取
reader.close() ; // 关闭
System.out.println(new String(c,0,len)) ;
}
};
FileWriter和FileReader的说明
从JDK文档中可以知道FileOutputStream是OutputStream的直接子类,FileInputStream也是InputStream的直接子类,但是在字符流文件的两个操作类却有一些特殊,FileWriter并不直接是Writer的子类,而是OutputStreamWriter的子类,而FileReader也不直接是Reader的子类,是InputStreamReader的子类,那么从这两个类的继承关系就可以清楚的发现,不管是使用字节流还是字符流实际上最终都是以字节的形式操作输入输出流的。
内存操作流
ByteArrayInputStream和ByteArrayOutputStream
之前的程序中,输出输入都是从文件中来的,当然,也可以将输出的位置设在内存之上,此时就要使用ByteArrayInputStream、ByteArrayOutputStream来完成输入,输出功能了。
ByteArrayInputStream主要完成将内容写入到内存之中。
ByteArrayOutputStream的功能主要是将内存中的数据输出。
以上操作的都时候 都应该以内存为操作点
实例:完成一个大小写字母转换程序:
import java.io.* ;
public class ByteArrayDemo01{
public static void main(String args[]){
String str = "HELLOWORLD" ; // 定义一个字符串,全部由大写字母组成
ByteArrayInputStream bis = null ; // 内存输入流
ByteArrayOutputStream bos = null ; // 内存输出流
bis = new ByteArrayInputStream(str.getBytes()) ; // 向内存中输出内容
bos = new ByteArrayOutputStream() ; // 准备从内存ByteArrayInputStream中读取内容
int temp = 0 ;
while((temp=bis.read())!=-1){
char c = (char) temp ; // 读取的数字变为字符
bos.write(Character.toLowerCase(c)) ; // 将字符变为小写
}
// 所有的数据就全部都在ByteArrayOutputStream中
String newStr = bos.toString() ; // 取出内容
try{
bis.close() ;
bos.close() ;
}catch(IOException e){
e.printStackTrace() ;
}
System.out.println(newStr) ;
}
};
管道流
管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutStream)、管道输入流(PipedInputStream),如果想进行管道输出,则必须把输出流连接在输入流之上,在PipedOutStream类上有如下的一个方法用于连接管道:
public void connect(PipedInputStream snk) throws IOException
实例操作
import java.io.* ;
class Send implements Runnable{ // 线程类
private PipedOutputStream pos = null ; // 管道输出流
public Send(){
this.pos = new PipedOutputStream() ; // 实例化输出流
}
public void run(){
String str = "Hello World!!!" ; // 要输出的内容
try{
this.pos.write(str.getBytes()) ;
}catch(IOException e){
e.printStackTrace() ;
}
try{
this.pos.close() ;
}catch(IOException e){
e.printStackTrace() ;
}
}
public PipedOutputStream getPos(){ // 得到此线程的管道输出流
return this.pos ;
}
};
class Receive implements Runnable{
private PipedInputStream pis = null ; // 管道输入流
public Receive(){
this.pis = new PipedInputStream() ; // 实例化输入流
}
public void run(){
byte b[] = new byte[1024] ; // 接收内容
int len = 0 ;
try{
len = this.pis.read(b) ; // 读取内容
}catch(IOException e){
e.printStackTrace() ;
}
try{
this.pis.close() ; // 关闭
}catch(IOException e){
e.printStackTrace() ;
}
System.out.println("接收的内容为:" + new String(b,0,len)) ;
}
public PipedInputStream getPis(){
return this.pis ;
}
};
public class PipedDemo{
public static void main(String args[]){
Send s = new Send() ;
Receive r = new Receive() ;
try{
s.getPos().connect(r.getPis()) ; // 连接管道
}catch(IOException e){
e.printStackTrace() ;
}
new Thread(s).start() ; // 启动线程
new Thread(r).start() ; // 启动线程
}
};