------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
1.IO概述:
(1)IO用来处理设备之间的数据传输。
(2)Java对数据的操作是通过流的方式。
(3)Java用于操作流的对象都在IO包中。
(4)流按操作数据分为两种:
1、字节流
2、字符流
(5)按流向分为:
1、输入流
2、输出流
2.IO流的常用基类:
(1)字节流的抽象基类:
1、InputStream:字节读取流。
2、OutputStream:字节写入流。
(2)字符流的抽象基类:
1、Reader:字符读取流。
2、writer:字符写入流。
这两个基类中都是抽象方法,需要被子类实现。
注:由这四个类派生出的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类 FileInputStream。
如:Reader 的子类 FileReader。
3.字符流:
(1)Writer中常用的方法:
writer() :将数据写入指定的文件中。
flash():数据一开始别没有直接写到文件中,而是在先写到了内存中的缓冲
区中,需要用到flash方法,也就是刷新。
close():关闭流资源,在关闭之前会刷新一次。
代码例子:
需求:在硬盘上,创建一个文件并写入一些数据。
import java.io.*;
class FileWriterDemo1
{
public static void main(String[] args)throws Exception
{
/*找到一个专门用于操作文件的writer子类对象,FileWriter,
创建一个FileWriter对象,该对象一被初始化就必须要明确
被操作的文件。盘符有可能写错,所以需要抛异常*/
FileWriter fw = new FileWriter("e:\\demo.txt");
//将数据写入文件中。
fw.write("haha");
fw.close(); //关闭流之前刷新了一次缓冲区。
}
}
结果:
当运行程序的时候,该文件会被创建到指定的目录下,在指定的目录下会产生一个指定名称的文件,如果该目录下已经有同名文件,那么将会覆盖原来的文件。
(2)那么为什么要关闭流呢?
其实java本身是不能往windows里边写数据的,如window和Linux写数据的方式不同,所以java得靠系统内部的方式来完成内部的书写,所以java会调用系统中的内容,来完成数据的建立,那么这些调用方式都是在使用windows的资源,使用完了以后要释放出来,那么就需要做一个动作,就是关闭流,也就是close,close是先调用了一次flush,然后才把资源关掉。
(3)IO流异常的处理方式:
代码例子:
import java.io.*;
class FileWriterDemo2
{
public static void main(String[] args)
{
FileWriter fw= null; //引用放在外边,各个语句都能调用到。
try
{
/*这里盘符容易写错,如写了不存在的盘符 k所以会发生异常,
所以需要处理,所以要写到try语句中。*/
fw = new FileWriter("e:\\demo1.txt");
fw.write("abcde");
}
catch (IOException e)
{
System.out.println("catch:"+e.toString());
}
finally
{
try
{
/*当写了不存在的盘符,就会出现异常,文件对象就会创建
失败,那么w= null,null能调用close,所以只有非null
的时候才能调用。*/
if(fw!=null)
fw.close();
}
catch (IOException e)
{
System.out.println("catch:"+e.toString());
}
}
}
}
发现:
为什么不把fw.close();放到第一个try语句中?因为,加入文件对象建立好了,写了好多数据,但是内存不够了,就会抛异常了,然后就去catch语句中执行去了,从而执行部到close,因此资源还在内存中,所以close一定要执行,所以放在finally语句中。
(4)文件的续写:
当有了处理方式以后,那么我们就可以成功的在硬盘上创建文件,并写入数据,可是硬盘上已经有同名的文件了,并且文件中还有数据,那么想在这个已有文件的基础上进行文件的续写,该怎么做呢?
代码例子:
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args) throws IOException
{
/*在FileWriter的构造函数里面传递一个true参数,代表不覆盖已有的
文件,并在已有文件的末尾处进行文件的续写。*/
FileWriter fw = new FileWriter("e:\\demo.txt",true);
fw.write("haha");
fw.close();
}
}
(5)文本文件的读取方式(一):
代码例子:
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args)
{
FileReader fr = null;
try
{
/*用到了Rerder的子类FileReader,创建一个读取流对象,和指定名
称的文件相关联。这里要保证该文件是已存在的,如果不存在,会
发生异常FileNotFoundExcrption。*/
fr =new FileReader("e:\\demo.txt");
int ch = 0;
//一次只读一个字符。
while((ch=fr.read())!=-1)
{
//因为read返回的是作为整数读取的字符,需要强转成字符。
System.out.println((char)ch);
}
}
catch (IOException e)
{
throw new RuntimeException("读取失败");
}
finally
{
try
{
if(fr!=null)
fr.close();
}
catch (IOException w)
{
throw new RuntimeException("关闭失败");
}
}
}
}
(6)文本文件的读取方式(二):
代码例子:
import java.io.*;
class FileWriterDemo4
{
public static void main(String[] args)
{
FileReader fr =null;
try
{
fr =new FileReader("e:\\demo.txt");
//定义一个字符数组,用于存放读到的字符。
char[] buf =new char[1024];
int num = 0;
//该read返回的是读到字符的个数。
while((num=fr.read(buf))!=-1)
{
/*用字符串的形式打印数组,buf表示传进来的数组,0代表从0角
标位开始读,num是取出字符的个数。*/
System.out.println(num+".."+new String(buf,0,num));
}
}
catch (IOException e)
{
throw new RuntimeException("读取失败");
}
finally
{
try
{
if(fr!=null)
fr.close();
}
catch (IOException w)
{
throw new RuntimeException("关闭失败");
}
}
}
}
(7)复制文本文件:
要求:
将e盘下的一个文本文件复制到d盘的一个文件中。
代码例子:
import java.io.*;
class Copy
{
public static void main(String[] args)
{
copy();
}
//将读写过程封装到一个方法中。
public static void copy()
{
FileWriter fw =null;
FileReader fr =null;
try
{
//创建写入流对象,在d盘创建一个文件。
fw=new FileWriter("d:\\copy.txt");
//创建读取流对象,与e盘文件相关联。
fr=new FileReader("e:\\javaio\\io11\\FileWriterDemo4.java");
/*此时数组还有一个作用,就是让FileReader和FileWriter
产生了联系,是一个中转站。*/
char[] ch =new char[1024];
int num=0;
while((num=fr.read(ch))!=-1)
{
//读一个,写一个。
fw.write(ch,0,num);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(fr!=null)
try
{
fr.close();
}
catch (IOException q)
{
throw new RuntimeException("读取流关闭失败");
}
if(fw!=null)
try
{
fw.close();
}
catch (IOException w)
{
throw new RuntimeException("写入流关闭失败");
}
}
}
}
(8)字符流缓冲区:
1、缓冲区的出现提高了对数据的读写效率。
2、对应的类有:1、BufferedWriter
2、BufferedReader
3、缓冲区要结合流才可以使用。
4、在流的基础上对流的功能进行增强。
5、字符流缓冲区提供了一个跨平台的换行符:newLine。
6、BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入。
7、BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取。
8、可以指定缓冲区的大小,或者接受默认的大小,一般情况下默认值足够大了。
(9)用缓冲区复制文本文件:
需求:通过缓冲区复制一个.java文件。
代码例子:
import java.io.*;
class CopyDemo
{
public static void main(String[] args)
{
BufferedWriter bw= null;
BufferedReader br= null;
try
{
/*创建一个写入流对象,为了提高效率加入缓冲技术,将字符写入流
作为参数传递给缓冲区的构造函数。*/
bw =new BufferedWriter(new FileWriter("bufwriter_copy.txt"));
/*创建一个读取流对象,并与文件相关,为了提高效率加入缓冲技术,
将字符读取流作为参数传递给缓冲区的构造函数。*/
Br = new BufferedReader(new FileReader(
"e:\\lianxidaima\\javaio\\day192\\BufferedReaderDemo.java"));
//变量也是中转站,使BufferedReader和BufferedWriter产生联系。
String line=null;
while((line=br.readLine())!=null)
{
bw.write(line);
//一次读一行。
bw.newLine();
//字符流缓冲区需要刷新。
bw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(bw!=null)
try
{
bw.close();
}
catch (IOException q)
{
throw new RuntimeException("关闭失败");
}
if(br!=null)
try
{
br.close();
}
catch (IOException w)
{
throw new RuntimeException("关闭失败");
}
}
}
}
(10)装饰设计模式:
什么是装饰设计模式:
当想要把已有的功能进行增强时,可以定义一个类,将已有对象传入,基于已有对象里面的功能,并提供加强功能,那么这个自定义的类称为装饰类。
装饰类通常会通过构造函数接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
(11)装饰和继承的区别:
1、装饰是为了优化以前的体系而存在的。使的以前的体系一优化完成一个更简单的方式,更具有扩展性。
2、装饰模式比继承更加灵活,避免了继承体系的复杂,而且降低了类与类之间的关系。
3、因为装饰类增强已有对象具备的功能和已有对象的功能是相同的,只不过是提供了更强的功能,所以装饰类和
被装饰类通常都是属于一个体系中的。
4、装饰类同属于同一个接口或者同一个类,从继承结构变为组合结构。
4.字节流:
需求:复制一个图片。
代码例子:
import java.io.*;
class CopyStream
{
public static void main(String[] args)
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
//创建一个字节写入流。
fos=new FileOutputStream("2.jpg");
//创建一个字节读取流与文件相关联。
fis=new FileInputStream("e:\\3.jpg");
//定义一个缓冲区,长度足够大。
byte[] b=new byte[1024*10];
int line =0;
while((line=fis.read(b))!=-1)
{
//字节流不需要刷新。
fos.write(b,0,line);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException q)
{
throw new RuntimeException("关闭写入流失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException w)
{
throw new RuntimeException("关闭输出流失败");
}
}
}
}
(1)字节流的缓冲区:
import java.io.*;
class CopyBufferedStream
{
public static void main(String[] args)
{
BufferedInputStream bufis = null;
BufferedOutputStream bufos = null;
try
{
bufis = new BufferedInputStream(new FileInputStream("e:\\1.mp3"));
bufos = new BufferedOutputStream(new FileOutputStream("e:\\0.mp3"));
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
try
{
if(bufis!=null)
bufis.close();
}
catch (IOException q)
{
throw new RuntimeException("关闭写入流失败");
}
try
{
if(bufos!=null)
bufos.close();
}
catch (IOException w)
{
throw new RuntimeException("关闭输出流失败");
}
}
}
}
(2)读取键盘录入:
System.out: out对应的是标准的输出设备,控制台。
System.in: in对应的是标准的输入设备,键盘。
import java.io.*;
class Readin
{
public static void main(String[] args)throws IOException
{
//获取键盘录入。
InputStream in=System.in;
//将键盘录入传给字节读取流。
InputStreamReader isr=new InputStreamReader(in);
//需要提高效率,用到字节流缓冲区。
BufferedReader br =new BufferedReader(isr);
String line =null;
while((line=br.readLine())!=null)
{
//录入小写,返回大写。
System.out.println(line.toUpperCase());
}
br.close();
}
}
(3)读取转换流:
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args)throws IOException
{
//获取键盘录入对象。
InputStream in = System.in;
//将字节流对象转成字符流对象。
InputStreamReader isr = new InputStreamReader(in);
/*为了提高效率,将字符串进行缓冲区技术高效操作,
使用BufferedReader。*/
BufferedReader bufr = new BufferedReader(isr);
String line= null;
while((line=bufr.readLine())!=null)
{
//定义一个结束标记,输入over就结束程序。
if("over".equals(line))
break;
System.out.println(line.toUpperCase());
}
bufr.close();
}
}
(4)写入转换流:
import java.io.*;
class TransStreamDemo2
{
public static void main(String[] args)throws IOException
{
//获取键盘录入对象。
InputStream in = System.in;
//将字节流对象转成字符流对象。
InputStreamReader isr = new InputStreamReader(in);
/*为了提高效率,将字符串进行缓冲区技术高效操作,
使用BufferedReader。*/
BufferedReader bufr = new BufferedReader(isr);
//获取键盘输出对象。
OutputStream out = System.out;
//将字节流对象转成字符流对象。
OutputStreamWriter osw = new OutputStreamWriter(out);
//为了提高效率使用BufferedWriter。
BufferedWriter bufw = new BufferedWriter(osw);
String line= null;
while((line=bufr.readLine())!=null)
{
//定义一个结束标记,输入over就结束程序。
if("over".equals(line))
break;
//字符流对象可以直接操作字符串。
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
bufr.close();
bufw.close();
}
}
(5)键盘录入的常见写法:
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
流操作的基本规律:
通过3个明确来完成:
1、明确源和目的。
源:输入流。InputStream Reader System.in
目的:输出流。OutputStream Writer System.out
2、操作的数据是否是纯文本。
如果是纯文本就使用字符流。
如果不是就使用字节流。
3、当体系明确后,再明确使用哪个具体的对象。通过设备来进行区分:
源设备:内存,硬盘,键盘。
目的设备:内存,硬盘,控制台。
5.File类
1、用来将文件或者文件夹的属性信息进行操作。
2、方便对文件与文件夹的属性信息进行操作。
3、File对象可以作为参数传递给流的构造函数。
4、了解File类中的常用方法。
5、这个类的出现弥补了流的不足,流对象能操作文件,但是它不能操作文件夹,文件的属性信息不能操作。
6、想要操作数据封装成文件的信息必须用到File对象。
(1)File类的常用方法:
1、创建:
1.1、boolean createNewFile();
特点:在指定位置创建文件,如果该文件已经存在,则不创建返回flase,和输出流不一样,输出流对象一建立
就创建文件,而且文件如果存在,可以覆盖。
1.2、boolean mkdir(); 创建文件夹,只能创建一级目录,创建成功就
返回true,否则返回flase。
1.3、boolean mkdirs(); 创建多级文件夹,创建成功就返回true,否则返回flase。
2、删除:
2.1、boolean delete(); 删除文件。
2. 2、void deleteonExit(); 在退出程序时删除指定文件。
3、判断:
3.1、boolean canExecute(); 这个文件是否可执行,如果有这个文件就
true,没有就返回flase。
3.2、boolean exists(); 这个文件是否存在,有就返回True,没有就返
回flase。
3.3、boolean isDirectory(); 判断是否是目录,前提是文件或目录存在。
3.4、boolean isFile(); 判断是否是文件,前提是文件或目录存在。
3.5、boolean Hidden(); 判断是否是隐藏文件。
3.6、boolean isAbsolute(); 判断是否是绝对路径,无论文件是否存在,
都可以判断。
4、获取信息:
4.1、String getName(); 获取名称。
4.2、String getPath(); 获取路径,封装什么路径就获取什路径。
4.3、String getParent(); 获取父目录,如果没有指定的绝对路径,
它就返回null,如果相对路径中有上一层目录,那么该目
录就是返回的结果。
4.4、String getAbsolutePath(); 获取绝对路径,无论你封装的是
相对路径还是绝对路径,它都取绝对路径。
4.5、long lastModified(); 文件最后一次被修改的时间。
4.6、long length(); 文件的大小。
代码例子:
文件列表一:
1、Static File[] listRoots(); 列出可用的文件系统根,操作的是共享数据,不
操作特有数据,所以不用写参数。这个方法是静态方法,返回的是数组。
代码例子:
import java.io.*;
class FileDemo
{
public static void main(String[] args)
{
ListRootsDemo();
}
public static void listRootsDemo()
{
File[] files = File.listRoots();
//高级for循环遍历数组。
for(File f:files)
{
//打印的是主机里面的有效盘符。
System.out.println(f);
}
}
}
注意:这里不可以使用length()方法,获取盘符所谓的长度没有意义。
2、String[] list(); 返回一个字符串数组,这些字符串指定路径表示的目录中
的文件和目录。
代码例子:
import java.io.*;
class FileDemo2
{
public static void main(String[] args)
{
listDemo();
}
public static void listDemo()
{
File f = new File("c:\\");
String[] names = f.list();
for(String name:names)
{
/*打印的结果是当前目录下c盘的所有文件名和目录,包含隐藏文件*/
System.out.println(name);
}
}
}
如果改成File f = new File("c:\\abc.txt"); 打印的结果是空指针异常。因为当list
方法所属的对象是一个文件的时候,因为文件里面没有东西,所以返回的数组就为空,为空了就不能被对象指向并且遍历了,里面调用了length属性。
注意:调用list方法的file对象必须是封装了一个目录,而且该目录必须存在。
文件列表二:
FileenameFilter 接口,实现此接口的类实例可用于过滤器文件名。它里面只有
一个方法,boolean accept(File dir, String name);
1、过滤哪一个目录中的文件,要先确定目录,目录是未知的。
2、要过滤目录中的哪一个文件,也是未知的。
所以定义两个参数,符合要求为true,不符合要求为flase。
代码例子:
import java.io.*;
class FileDemo3
{
public static void main(String[] args)
{
//封装一个已有的目录。
File dir = new File("e:\\lianxidaima\\javaio");
//用匿名内部类的形式创建子类对象。
String[] arr =dir.list(new FilenameFilter()
{
//复写FilenameFilter接口方法。
public boolean accept(File dir,String name)
{
return true;
}
});
//打印的是这个目录下项目的个数。
System.out.println(arr.length);
for(String name:arr)
{
//打印的结果为这个目录下的所有的文件名。
System.out.println(name);
}
}
}
如果返回的是flase的话,打印的长度为零。原来list方法它在依据new 这个对象的accept方法的返回值类判定这个文件是不是需要的文件。当为flase时,上边指定的目录就是要被过滤的目录,dir就是这个目录,打印dir,结果就是这个目录。Name是这个目录下的所有文件名,如果想要扩展名是.java的文件,只要判断name就行。例如:return name.endswith(".java"); 打印的结果都是.java的文件名。
File[] listFiles()
代码例子:
import java.io.*;
class FileDemo4
{
public static void main(String[] args)
{
File dir = new File("c:\\");
File[] files = dir.listFiles();
for(File f:files)
{
//打印结果是该路径下文件的名称和文件的大小,不能获取文件夹。
System.out.println(f.getName()+".."+f.length());
}
}
}
总结:
String[] list()方法对应的过滤器为:String[] list(FilenameFilter filter)
File[] listFiles()方法对应的过滤器为:1、File[] listFiles(FileFilter filter)
2、File[] listFiles(FilenameFilter filter)
(2)list与listFiles的区别:
List这个方法它返回的是当前目录下的文件以及文件夹名称,只能获取名称。
listFiles这个方法返回的是当前目录下的文件以及文件夹的对象,可以通过getName()来获取名称,也可以通过length()来获取大小,也可以通过getPath()来获取路径。listFiles在开发的时候比较常用。
List和listFile只能列出当前目录下的所有内容,如果目录下还有目录,该怎么列出呢?
列出目录下所有内容——递归
列出指定目录下文件或者文件夹,包含子目录中的内容,也就是列出指定目录下所有内容。
什么是递归:
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可,在列出的过程中出现的还是目录的话,还可以再次调用本功能,也就是函数自身调用自身,这种表现形式,或者编程手法,称为递归。
代码例子:
import java.io.*;
class FileDemo5
{
public static void main(String[] args)
{
File dir = new File("e:\\lianxidaima\\javaio");
showDir(dir);
}
public static void showDir(File dir)
{
//用来列出目录名。
System.out.println(dir);
//列出文件。
File[] files = dir.listFiles();
for(int x=0;x<files.length;x++)
{
//判断列出的文件是否是目录,如果是就再调用函数列出来。
if(files[x].isDirectory())
//调用自身功能再列一遍。
showDir(files[x]);
//如果不是就打印列出的文件。
else
System.out.println(files[x]);
}
}
}
递归要注意:1、限定条件。
2、要注意递归的次数,尽量避免内存溢出。
解释:例 public static void method()
{
//调用自身函数。
method();
}
这也是一个递归,但是它停不下来,所以要限定条件。
练习:
列出目录下所有内容——带层次。
代码例子:
import java.io.*;
class FileDemo6
{
public static void main(String[] args)
{
File dir =new File("e:\\lianxidaima");
showDir(dir,0);
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
for(int x=0;x<level;x++)
{
sb.append("");
}
return sb.toString();
}
public static void showDir(File dir,int level)
{
System.out.println(getLevel(level)+dir.getName());
level++;
File[] files = dir.listFiles();
for(int x=0;x<files.length;x++)
{
if(files[x].isDirectory())
showDir(files[x],level);
else
System.out.println(getLevel(level)+files[x]);
}
}
}
6.Properties概述:
1、Properties是hashtable的子类,它具备map集合的特点,而且它里面存储的键值对都是字符串。
2、是集合中和IO技术想结合的集合容器。
(1)Properties对象的特点:
1、可以用于键值对形式的配置文件,不仅可以操作键值对,而且可以操作硬盘的键值对信息。
2、在加载数据时,需要数据有固定的格式:键=值。
代码例子:
import java.io.*;
import java.util.*;
class PropertiesDemo
{
public static void main(String[] args)
{
setAndGet();
}
public static void setAndGet()
{
//创建一个集合对象。
Properties prop = new Properties();
//设置键值对。
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","35");
System.out.println(prop);
//获取值。
String value = prop.getProperty("lisi");
System.out.println(value);
//修改值。
prop.setProperty("lisi","89");
//遍历集合中的元素。
Set<String> names = prop.stringPropertyNames();
for(String s:names)
{
//打印键和对应的值。
System.out.println(s+"..."+prop.getProperty(s));
}
}
}
Properties存储配置文件:
import java.io.*;
import java.util.*;
class PropertiesDemo3
{
public static void main(String[] args)throws IOException
{
loadDemo();
}
public static void loadDemo()throws IOException
{
Properties prop = new Properties();
//与文件相关联。
FileInputStream fis = new FileInputStream("e:\\b.txt");
//将流中的数据加载进集合。
prop.load(fis);
//修改值。
prop.setProperty("wangwu","40");
//将值存进硬盘中。
FileOutputStream fos = new FileOutputStream("e:\\b.txt");
prop.store(fos,"haha");
prop.list(System.out);
}
}
7.打印流:
(1)PrintWriter
(2)PrintStream:
他输出流添加了功能,使它们能够方便地打印各种数据值表现形式。
该流提供了打印方法,可以将各种数据类型的数据都按原样打印。
PrintWriter:
构造函数可以接收的参数类型:
1、file对象,类型是File。
2、字符串路径,类型是String。
3、字节输出流,类型是OutputStream。
4、字符输出流,类型是Writer。
PrintStream:
构造函数可以接收的参数类型:
1、file对象,类型是File。
2、字符串路径,类型是String。
3、字节输出流,类型是OutputStream。
代码例子:
import java.io.*;
class PrintWriterDemo
{
public static void main(String[] args)throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out,true);
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
}
bufr.close();
out.close();
}
}
8.序列流:
SequenceInputStream:对多个流进行合并。
就是把多个流变成一个流。
代码例子:
import java.io.*;
import java.util.*;
class SequenceDemo
{
public static void main(String[] args)throws IOException
{
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("e:\\1.txt"));
v.add(new FileInputStream("e:\\2.txt"));
v.add(new FileInputStream("e:\\3.txt"));
//把3个流对象添加倒集合中。
Enumeration<FileInputStream> en = v.elements();
//把上边的3个流对象变成一个流对象。
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("e:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
切割文件:
FileInputStream fis = new FileInputStream("c:\\1.bmp");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1)
{
fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
9.对象的序列化:
操作对象:1、ObjectInputStream
2、ObjectOutputStream
它们可以操作对象的流,被操作的对象需要实现Serializable接口。
序列化的作用:
以为对象中要存储一些数据,如果在对内存中的话,程序结束以后,对象也就回收了,所以把对象存在硬盘上,如果需要用到里面的数据的话,只要读出来就可以。把对象存在硬盘上叫做对象的持久化存储。
通过ObjectInputStream读,就必须通过ObjectOutputStream写,它们是相对的。
ObjectOutputStream(OutputStream out)在构造的时候必须传一个目的,它的功能是让流和被操作的对象相结合。
注意:静态是不能被序列化的。
10.管道流:
(1)PipedInputStream。
(2)PipedOutputStream。
输入和输出可以直接进行比较,通过结合线程使用。
代码例子:
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in = in;
}
public void run()
{
try
{
byte[] buf = new byte[1024];
System.out.println("读取前,,没有数据阻塞");
int len = in.read(buf);
System.out.println("读到数据,,阻塞结束");
String s= new String(buf,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
{
private PipedOutputStream out;
Write (PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待6秒后。");
Thread.sleep(6000);
out.write("piped lai la".getBytes());
out.close();
}
catch (Exception e)
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args) throws IOException
{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
11.随机访问文件:
RandomAccessFile:是一个单独的工具类,只继承Objict。
1、随机访问文件,自身具备读写的方法。
2、通过skipBytes(int x),seek(int x)来达到随机访问。
(2)RandomAccessFile的特点:
1、该类不是IO体系中的子类,而是直接继承Objict。
2、是IO包中的成员,因为它具备读和写的功能,它在对象内部
封装了一个数组,而且通过指针对数组的元素进行操作。
3、可以通过getFilePointer来获取指针的位置,同时可以通过seek改变
指针的位置。
4、内部封装了字节输入流和字节输出流。
(3)RandomAccessFile的不足:
该类只能操作文件,而且操作文件还有模式。
(4)DataStream:用于操作基本数据类型。
1、DataInputStream
2、DataOutputStream
(5)ByteArrayStream:用于操作字节数组的流对象。
1、ByteArrayInputStream在构造的时候,需要接收数据源,而且数据源是一个字节数组。
2、ByteArrayOutputStream在构造的时候,不用定义数据目的,因为对象中已经封装了可变长度的字节数组。
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。
12.字符编码:
编码:字符串变成字节数组。
解码:字节数组变成字符串。
String 变成byte[];通过str.getBytes(charSetName);
byte[]变成String;通过 new String(byte[],charSetName)
数组 变成String:通过Arrays.toString();
默认的是GBK编码表。
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------