------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
/*
1.File
File是文件和目录的抽象表示形式
构造方法
File(String pathname);根据一个路径得到File对象
File(String parent,String child);根据一个目录和一个子目录/文件得到一个File对象
File(File parent,String child);根据一个父File对象和一个子目录/文件得到一个File对象
主要功能:
创建功能
public boolean creatNewFile();创建文件,如果已经存在就会创建失败
public boolean mkdir();创建目录,如果已近存在就会创建失败
public boolean mkdirs();创建目录,如果父目录不存在会自动创建
删除功能
public boolean delete();删除目录或文件,入股目录中存在内容则删除失败
重命名
public boolean renameTo(File dest);
如果路径相同就是改名,如果不同就是移动,如果目标位置有同名文件/目录则修改失败。
判断功能
public boolean isDirectory();判断是否是目录
public boolean isFile();判断是否是文件
public boolean exists();判断是否存在
获取功能
public Stirng getAbsolutePath();获取绝对路径
public String getPath();获取相对路径
public String getName();获取名称
public long length();获取文件/目录字节大小
public long lastModified();获取最后一次修改的时间,毫秒值
特殊获取功能
public String[] list();获取指定目录下所有文件和文件夹的名称数组
publlic File[] listFiles();获取指定目录下所有文件和目录的File数组
利用文件名过滤器获取符合要求的数组
public String[] list(FilenameFilter filter);
public File[] listFiles(FilenameFilter filter);
如:获取指定目录下后缀名为.jpg的文件
//封装目录
File file = new File("e:\\");
//通过文件名过滤器获取符合要求的文件
String[] strArray = file.list(new FilenameFilter(){
public boolean accept(File dir,String name){
//这里的dir指的是被判断的目录,name指的是目录下的各个文件和目录的名称
return new File(dir,name).isFile() && name.endswith(".jpg");
}
});
2.FileOutputStream 字节输出流对象
构造方法
FileOutputStream(File file);
FileOutputStream(String name);——常用
写入方法
public void write(int b);写一个字节
public void write(byte[] b);写一个字节数组
public void write(byte[] b,int off,int len);写一个字节数组的一部分
两个小问题:
如何换行:write("\r\n".getBytes());
windows:\r\n
linux:\n
Mac:\r
如何追加写入:用构造方法带第二个参数是true的情况即可
FileOutputStream(File f,boolean flag);
3.FileInputStream 字节输入流对象
构造方法相同
读取方法:
public int read();
public int read(byte[] b);
举例:
一次读取一个字节
int by = 0;
while((by = fis.read())!=-1){
Syetem.out.println((char) by);
}
一次读取一个字节数组
byte[] bys = new byte[1024];
int len;
while((len = fis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
一个小问题:计算机是如何识别什么时候把两个字节转换为一个中文字的呢?
在计算机中中文的存储分两个字节:
第一个字节肯定是负数。
第二个字节常见的是负数,可能有正数。但是没影响。
4.字节缓冲区类
写数据:BufferedOutputStream(OutputStream out);
读数据:BufferedInputStream(InputStream in);
字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现。
所以需要传递一个OutputStream对象做参数。实际传递的是其子类实例。
5.转换流(把字节流转换为字符流)
写数据:
OutputStreamWriter(OutputStream out);根据默认编码转换字节流数据为字符流
OutputStreamWriter(OutputStream out,String charsetName);使用指定编码把字节流数据转换为字符流
读数据:
InputStreamReader(InputStream is);用默认编码读取数据
InputStreamReader(InputStream is,String charsetName);使用指定编码读取数据
字符流=字节流+编码表;默认使用GBK编码表,一般都是用默认。
InputStreamReader的方法:
int read();一次读取一个字符
int read(char[] chs);一次读取一个字符数组
实例:
int ch = 0 ;
while((ch=isr.read())!=-1){
System.out.println((char) ch);
}
char[] chs = new char[1024];
int len = 0;
while((len = isr.read())!=-1){
System.out.println(new String(chs,0,len));
}
OutputSreamWriter的方法
public void write(int c);写一个字符
public void write(char[] chs);写一个字符数组
public void write(char[] chs,int off,int len);写一个字符数组的一部分
public void write(String str);写一个字符串
public void write(String str,int off,int len);写一个字符串的一部分
一个小问题:字符流的写入必须刷新后数据才可以被写入。在执行close操作时也有刷新缓冲区操作。
转换流的名称有点长,所以,Java就提供了其子类供我们使用。可以直接传递文件名做参数
FileWriter(String name);
FileReader(String name);
6.字符缓冲区流/字符高效流
写入流:
BufferedWriter(Writer out);
特殊方法
public void Write(String str);一次写入一个字符串
public void newLine();写入换行符,根据系统来决定写入的换行符
BufferedReader(Reader in);
特殊方法
public String readLine();一次读取一行数据,包含数据不包含终止符,如果到达流末位,返回null
一个特殊类:LineNumberReader是BufferedReader的子类
特有方法:
public int getLineNumber();获得当前行号
public void setLineNumber(int lineNumber);设置行号
7.其他常用流
1).打印流
PrintStream
PrintWriter
特殊功能:
可以直接传递文本文件,也可以传递其他流;
只能写数据,不能读数据;
可以操作任意类型的数据;
启动自动刷新后可以自动刷新,但只限特殊构造方法可用,且仅限println()方法可以自动刷新;
public PrintStream(OutputStream out,boolean autoFlush);
public PrintWriter(OutputStream out,boolean autoFlush);
public PrintWriter(Writer out,boolean autoFlush);
主要方法:
print();
println();
这两个方法中的参数可以是任意基本类型和String类型。
具体来说:boolean/char/char[]/double/float/int/long/object/string
当启用了自动刷新时,该类的println()方法就相当于是BufferedReader的
write(); newLine(); flush(); 三个方法的效果。
实例:
String line = null;
while((line=br.readLine())!=null){
pw.println(line);
}
2).标准输入输出流
System类中的两个成员变量:
public static final InputStream in “标准”输入流。
public static final PrintStream out “标准”输出流。
由此可见,标准输出流其实是打印流对象;标准输入流是字节输入流对象。
InputStream is = System.in;
PrintStream ps = System.out;
标准输入流:System.in InputStream is = System.in;
此流是字节输入流,只能按字节读取键盘数据,
在jdk1.5之前包装此流用来接收键盘录入整行数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符串:");
String line = br.readLine();
且可以把读取到的字符串装换为需要的数据类型,如:
System.out.println("请输入一个整数:");
line = br.readLine();
int i = Integer.parseInt(line);
3).随机访问流RandomAccessFile
该类不算是IO体系中的子类,而是直接继承自Object类,但它又是IO包中的成员
因为它同时具备读和写的功能。
其内部封装了一个数组,而且通过指针对数组的元素进行操作。
构造方法:
RandomAccessFile(File file, String mode)
RandomAccessFile(String name, String mode)
常用模式是只读r和读写rw,模式对应功能,只读模式是不能写入数据的。
常用方法:
该类的方法中,有读取一行数据的方法readLine();但却没有写入字符串的方法。
String readLine();
int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
boolean readBoolean() readByte/Char/Double/Float/Int/Long/Short
write(int b)
write(byte[] b)
write(byte[] b, int off, int len) writeBoolean/Byte/Char/Double/Float/Long/Short
特殊用法:
使用writeInt()和readInt()方法与seek()和skipBytes()方法配合可以在文件中随机的写入和读取。
一次写入4个字节;一次读取4个字节;设置指针位置;
实例:
写数据:
raf.write("李四".getBytes());//一个汉字两个字节,写入了4个字节
raf.writeInt(97); //97虽然只占一个字节,但是writeInt写入了4个字节
raf.write("王五".getBytes());
raf.writeInt(99);
读数据:
raf.skipBytes(8);//跳过指定的字节数
//raf.seek(8*1); 也可以使用此方法来调整指针的位置
byte[] buf = new byte[4];//一次读取4个字节的数组
raf.read(buf); //每读取一次,指针做对应偏移
String name = new String(buf);
int age = raf.readInt(); //读取4个字节
System.out.println("name="+name);//王五
System.out.println("age="+age);//99
4).序列化流
ObjectOutputStream 序列化: 对象——数据流
ObjectInputStream 反序列化: 数据流——对象(即读取数据的结果是创建了一个对象)
构造方法:
ObjectInputStream(InputStream in)
ObjectOutputStream(OutputStream out)
特有方法:
该类肯定具备了父类的所有方法,既然是序列化流,肯定提供了特殊的方法。
readObject(Object obj) 还原对象
writeObject(Object obj) 把对象写入文本(其实写入的是地址值)
实例:
序列化:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
Person p = new Person("tony",28);
oos.writeObject(p);
oos.close();
反序列化:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txxt"));
Object obj = ois.readObject();
ois.close();
注意事项:
A:被序列化的对象需要实现Serializable接口
B:为了防止出现InvalidClassException异常,要自动生成一个序列化id值,也可以手写。
private static final long serialVersionUID = -2071565876962058344L;
C:可以使用transient关键字声明不需要序列化的成员变量。
private transient int age;
5).合并流SequenceInputStream
该流提供了特殊的构造方法,可以使用其他的字节流对象创建该类的对象,可以一次读取
所有对象的数据,所以可以实现合并。所以该流只提供读取流。
A:合并两个文件SequenceInputStream(InputStream s1, InputStream s2)
InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
InputStream s2 = new FileInputStream("DataStreamDemo.java");
SequenceInputStream sis = new SequenceInputStream(s1, s2);
B:合并多个文件SequenceInputStream(Enumeration e)
Enumeration是枚举接口也是Vector中的一个方法的返回值类型Enumeration<E> elements()
即通过把对象存入Vector集合,然后把其中包装的文件传递给该类的对象实现合并
Vector<InputStream> v = new Vector<InputStream>();
InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
InputStream s2 = new FileInputStream("CopyFileDemo.java");
InputStream s3 = new FileInputStream("DataStreamDemo.java");
v.add(s1);
v.add(s2);
v.add(s3);
Enumeration<InputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
但是,这样做并不是太好,因为Vector集合的效率较低,那么怎么改进呢?
通过ArrayList改进:把对象存入集合——获取集合的迭代器——通过迭代器创建枚举对象
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
al.add(s1);
al.add(s2);
al.add(s3);
final Iterator it = la.iterator(); //匿名内部类访问的成员变量需要使用final修饰
//通过匿名内部类实例化接口对象
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
//重写接口的抽象方法
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
C:既然可以合并,那么如何拆分文件呢????
思路是这样的:
A:先用输入流封装(关联)要被拆分的文件
B:因为要拆分为多个文件,所以目标对象不能马上封装
确定拆分后的每个文件的大小,据此来决定每次读取多大的文件
每读取一次,用输出流封装一个目标对象,然后读取的数据写入文本
实现文件拆分
实现:
FileInputStream fis = new FileInputStream("c:\\1.bmp");
FileOutputStream fos = null;
byte[] bys = new byte[1024*1024]; //切割文件大小为1M
int len = 0;
int count=1;
while((len=fis.read(bys))!=-1){
fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
fos.write(bys,0,len);
fos.close();
}
6).内存操作流
用于处理临时存储信息的,程序结束,数据就从内存中消失
即数据的读取和写入都是操作的内存,而不是文件。
构造方法
ByteArrayOutputStream()
ByteArrayInputStream(byte[] buf)
CharArrayWriter()
CharArrayReader(char[] buf)
StringWriter()
StringReader(String s)
可以发现:写入时不用传入参数,读取时传入对应的数据类型。
读取的数据也就是通过输入流的特殊方法获取的,对应方法为:
public byte[] toByteArray()
public char[] toCharArray()
public String toString()
实例:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int x = 0; x < 10; x++) {
baos.write(("hello" + x).getBytes());
}
// 通过查看源码我们知道这里什么都没做,所以根本需要close()
byte[] bys = baos.toByteArray();
// 读数据
// ByteArrayInputStream(byte[] buf)
ByteArrayInputStream bais = new ByteArrayInputStream(bys);
int by = 0;
while ((by = bais.read()) != -1) {
System.out.print((char) by);
}
特殊说明:
由于内存操作流,并没有调用系统的资源,所以不用close。
7).数据操作流
可以读写基本数据类型的数据,很少使用。
构造方法:
* 数据输入流:DataInputStream(InputStream in)
* 数据输出流:DataOutputStream(OutputStream out)
// 写数据了
dos.writeByte(10);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000);
dos.writeFloat(12.34F);
dos.writeDouble(12.56);
dos.writeChar('a');
dos.writeBoolean(true);
// 读数据
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
char c = dis.readChar();
boolean bb = dis.readBoolean();
8.与流有关的特殊类Properties
是Hashtable的子类,但是限制了只能存储String类型的键和值,所以不需使用泛型。
既然是map集合的一员,肯定具备了map集合的所有功能。
特殊功能:
public Object setProperty(String key,String value):添加元素
public String getProperty(String key):获取元素
public Set<String> stringPropertyNames():获取所有的键的集合
特有功能:
把文件中的数据读取到集合中
public void load(Reader reader);
把集合中的数据存储到文件,并给文件加上注释
public void store(Writer writer,String comments);
实例:
加载文件:
Properties prop = new Properties();
// 注意:这个文件的数据必须是键值对形式
Reader r = new FileReader("prop.txt");
prop.load(r);
r.close();
上传数据:
Properties prop = new Properties();
prop.setProperty("林青霞", "27");
prop.setProperty("武鑫", "30");
prop.setProperty("刘晓曲", "18");
//public void store(Writer writer,String comments):把集合中的数据存储到文件
Writer w = new FileWriter("name.txt");
prop.store(w, "helloworld");
w.close();
*/