您的位置:首页 > 职场人生

黑马程序员---IO流及File类

2015-06-26 19:40 495 查看


一、IO流

概念:

流是一组有序的数据序列,依据操作的类型,可以分为输入流和输出流两种。
注:
所有输入流都是抽象类Reader或抽象类InputStream的子类;
所有输出流都是抽象类Writer或抽象类OutputStream的子类;

输入流:

字节流:InputStream类,其常用方法如下:
void  close()
关闭此输入流并释放与该流关联的所有系统资源。
void  mark(int readlimit)
在此输入流中标记当前的位置。
boolean  markSupported()
测试此输入流是否支持  mark 和  reset 方法。
abstract  int  read()
从输入流中读取数据的下一个字节。
int  read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组  b 中。
int  read(byte[] b, int off, int len)
将输入流中最多  len 个数据字节读入 byte 数组。
void  reset()
将此流重新定位到最后一次对此输入流调用  mark 方法时的位置。
long  skip(long n)
跳过和丢弃此输入流中数据的  n 个字节。


字符流:Reader类为Java中专门用于处理字节的,Java得字符用的是Unicode编码,双字节。其常用方法如下:

abstract  void  close()
关闭该流并释放与之关联的所有资源。
void  mark(int readAheadLimit)
标记流中的当前位置。
boolean  markSupported()
判断此流是否支持 mark() 操作。
int  read()
读取单个字符。
int  read(char[] cbuf)
将字符读入数组。
abstract  int  read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。
int  read(CharBuffer target)
试图将字符读入指定的字符缓冲区。
boolean  ready()
判断是否准备读取此流。
void  reset()
重置该流。
long  skip(long n)
跳过字符。

输出流:

字节流:OutputStream类,其常用方法如下:
void  close()
关闭此输出流并释放与此流有关的所有系统资源。
void  flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void  write(byte[] b)
将  b.length 个字节从指定的 byte 数组写入此输出流。
void  write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量  off 开始的  len 个字节写入此输出流。
abstract  void  write(int b)
将指定的字节写入此输出流。

字符流:Writer类,其常用方法如下:
Writer  append(char c)
将指定字符添加到此 writer。
Writer  append(CharSequence csq)
将指定字符序列添加到此 writer。
Writer  append(CharSequence csq, int start, int end)
将指定字符序列的子序列添加到此 writer.Appendable。
abstract  void  close()
关闭此流,但要先刷新它。
abstract  void  flush()
刷新该流的缓冲。
void  write(char[] cbuf)
写入字符数组。
abstract  void  write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
void  write(int c)
写入单个字符。
void  write(String str)
写入字符串。
void  write(String str, int off, int len)
写入字符串的某一部分。

二、缓冲区

目的:

缓冲区的出现是为了提高对数据的读写效率。临时存储数据,达到一定数量后一起处理。实现类有以下四种:BufferedInputStream类,BufferedOutputStream类,BufferedWriter类和BufferReadered类。

特有方法:

readLine()方法:

一次读取一行。返回包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null。只返回回车符之前的内容,不返回回车符。例如,

   
String line = null;
while((line=bufr.readLine())!= null)
{
System.out.println (line);
}
     该缓冲区提供了一次读一行的方法readLine(),方便了对文本数据的读取。

     readLine()原理:

无论是读一行还是读取多个字符,都是在硬盘上逐个读取。最终使用的是read()方法,一次读取一个。将字符临时 存到内部数组,遇到换行符不存,将之前的字符变成字符串返回,换行符相当于停止标识。代码如下:
public String myReadLine() throws IOException//readLine的原理
{
StringBuilder sb = new StringBuilder();//建立容器,存放字符。
int ch = 0;
while((ch=fr.read())!=-1)
{
if(ch=='\r')//换行符不能读取
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)//防止最后一行因为没有换行符而无法输出。
return sb.toString();
return null;
}

装饰设计模式

readLine()方法调用了read()方法,同时增强了read()方法的功能。将被增强的对象传给增强类,增强类提供更强的方法。所以,MyBufferedReader是对BufferedReader的增强。这种模式就是“装饰设计模式”。

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有类,并提供加强功能,那么这个自定义的类称为“装饰类”。
特点:

会通过构造函数接受被装饰的对象,并基于被装饰的对象的功能,提供增强功能。
package com.itheima;
import java.io.*;

public class MyLineBufferReaderDemo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
MyLineBufferedReader myDemo=null;
try {
myDemo = new MyLineBufferedReader(new FileReader("D:\\HaxLogs1.txt"));
String str=null;
while((str=myDemo.readLine())!=null)
{
System.out.println(myDemo.getNum()+":"+str);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally
{
try {
myDemo.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
class MyLineBufferedReader extends Reader
{
private Reader in;
public MyLineBufferedReader(Reader in) {
// TODO 自动生成的构造函数存根
this.in = in;
}
private int  num =1;
public int getNum()
{
return num;
}
public String readLine()throws IOException
{
StringBuilder sb = new StringBuilder();
int ch;
while((ch=in.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
{
num++;
return sb.toString();
}
sb.append((char)ch);
}
return null;
}
public void setLineNum(int num)
{
this.num = num;
}
public void close() throws IOException {
// TODO 自动生成的方法存根
in.close();
}
public int read(char[] cbuf, int off, int len) throws IOException {
// TODO 自动生成的方法存根
return in.read(cbuf, off, len);
}
}

优点:

1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

LineNumberReader类(装饰类)

getLineNumber(),获得行号,默认从1开始。返回的是读取的这一行的行号。

setLineNumber(),设置行号,从多少开始。

继承了BufferedReader类,属于这个体系,增强了行号的功能。   
 

键盘录入

字段摘要
static PrintStream  err
“标准”错误输出流。
static InputStream  in
“标准”输入流。
static PrintStream  out
“标准”输出流。


复制文件的小Demo:
package com.itheima;
import java.io.FileReader;
import java.io.FileWriter;
public class CopyDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
FileWriter fileWriter = null;
FileReader fileReader = null;
try {
fileReader = new FileReader("D:\\HaxLogs1.txt");
fileWriter = new FileWriter("D:\\HaxLogs2.txt",true);
char[] ch = new char[1024];
int len;
while((len = fileReader.read(ch))!=-1)
{
fileWriter.write(ch,0,len);
fileWriter.flush();
}
} catch (Exception e) {
// TODO: handle exception
}
finally
{
try {
if(fileReader != null)
fileReader.close();
if(fileWriter!= null)
fileWriter.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}

编码表:
按照指定的编码表(UTF-8或者GBK),将录入的数据存入指定文件中

      平时的读写使用默认的字符编码表,即系统的编码,GBK。转换流可以指定编码表,这也是转换流存在的重要原因,不仅仅是调用readLine()和newLine()。也就是说,只要是涉及到字符编码转换,就需要使用转换流。

      使用不同的编码表,占用的空间不同。再就是,FileReader和FileWriter,默认GBK编码,无法处理UTF-8编码,需要使用转换流才能读取。转换流是以上两类的父类,具有使用多种编码的功能。依照文件的编码来确定使用何种数据处理类:GBK使用FileReader,UTF-8使用InputStreamReader。使用转换流更加广泛,但需要传入字节流,FileReader更加简便。

三、File类

解释:
File类是java.io包中唯一代表磁盘文件本身的对象。

构造方法:
1. File(String pathname);
2. File(String parent,String child)
3. File(File f,String child)

File类常用方法:
boolean  canExecute()
测试应用程序是否可以执行此抽象路径名表示的文件。
boolean  canRead()
测试应用程序是否可以读取此抽象路径名表示的文件。
boolean  canWrite()
测试应用程序是否可以修改此抽象路径名表示的文件。
int  compareTo(File pathname)
按字母顺序比较两个抽象路径名。
boolean  createNewFile()
当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
static File  createTempFile(String prefix, String suffix)
在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
static File  createTempFile(String prefix, String suffix, File directory)
在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
boolean  delete()
删除此抽象路径名表示的文件或目录。
void  deleteOnExit()
在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
boolean  equals(Object obj)
测试此抽象路径名与给定对象是否相等。
boolean  exists()
测试此抽象路径名表示的文件或目录是否存在。
File  getAbsoluteFile()
返回此抽象路径名的绝对路径名形式。
String  getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。
File  getCanonicalFile()
返回此抽象路径名的规范形式。
String  getCanonicalPath()
返回此抽象路径名的规范路径名字符串。
long  getFreeSpace()
返回此抽象路径名指定的分区中未分配的字节数。
String  getName()
返回由此抽象路径名表示的文件或目录的名称。
String  getParent()
返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回  null 。
File  getParentFile()
返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回  null 。
String  getPath()
将此抽象路径名转换为一个路径名字符串。
long  getTotalSpace()
返回此抽象路径名指定的分区大小。
long  getUsableSpace()
返回此抽象路径名指定的分区上可用于此虚拟机的字节数。
int  hashCode()
计算此抽象路径名的哈希码。
boolean  isAbsolute()
测试此抽象路径名是否为绝对路径名。
boolean  isDirectory()
测试此抽象路径名表示的文件是否是一个目录。
boolean  isFile()
测试此抽象路径名表示的文件是否是一个标准文件。
boolean  isHidden()
测试此抽象路径名指定的文件是否是一个隐藏文件。
long  lastModified()
返回此抽象路径名表示的文件最后一次被修改的时间。
long  length()
返回由此抽象路径名表示的文件的长度。
String[]  list()
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
String[]  list(FilenameFilter filter)
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[]  listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
File[]  listFiles(FileFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[]  listFiles(FilenameFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
static File[]  listRoots()
列出可用的文件系统根。
boolean  mkdir()
创建此抽象路径名指定的目录。
boolean  mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
boolean  renameTo(File dest)
重新命名此抽象路径名表示的文件。
boolean  setExecutable(boolean executable)
设置此抽象路径名所有者执行权限的一个便捷方法。
boolean  setExecutable(boolean executable, boolean ownerOnly)
设置此抽象路径名的所有者或所有用户的执行权限。
boolean  setLastModified(long time)
设置此抽象路径名指定的文件或目录的最后一次修改时间。
boolean  setReadable(boolean readable)
设置此抽象路径名所有者读权限的一个便捷方法。
boolean  setReadable(boolean readable, boolean ownerOnly)
设置此抽象路径名的所有者或所有用户的读权限。
boolean  setReadOnly()
标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。
boolean  setWritable(boolean writable)
设置此抽象路径名所有者写权限的一个便捷方法。
boolean  setWritable(boolean writable, boolean ownerOnly)
设置此抽象路径名的所有者或所有用户的写权限。
String  toString()
返回此抽象路径名的路径名字符串。
URI  toURI()
构造一个表示此抽象路径名的 file: URI。

示例:

package com.itheima;
import java.io.File;
public class FileTest{
<span style="white-space:pre"> </span>public static void main(String[] args){
<span style="white-space:pre"> </span>File file = new File("word.txt");
<span style="white-space:pre"> </span>if(file.exists()){
<span style="white-space:pre"> </span>String name = file.getName();
<span style="white-space:pre"> </span>long length = file.length();
<span style="white-space:pre"> </span>boolean hidden = file.isHidden();
<span style="white-space:pre"> </span>String absolutepath = file.getAbsolutePath();
<span style="white-space:pre"> </span>System.out.println("文件名为:"+name);
<span style="white-space:pre"> </span>System.out.println("文件长度为:"+length);
<span style="white-space:pre"> </span>System.out.println("文件的绝对路径为:"+absolutepath);
<span style="white-space:pre"> </span>System.out.println("文件是否隐藏:"+hidden);
<span style="white-space:pre"> </span>}else{
<span style="white-space:pre"> </span>System.out.println("文件不存在");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
} System.out.println(");")}
}

递归

:函数自己调用自己。这种编程模式称为“递归”。

注意:
1. 必须有限定条件,保证函数能够结束。
2. 小心递归的次数,尽量避免内存溢出。

递归原理:按照正常顺序依次执行,只是某些语句由函数代替,需要先将函数内的语句执行完毕才能继续向下执行。

举例
public void printJavaOfFolder(String folderName)
{
//打印文件夹中后缀名为.java的文件
File file = new File(folderName);
String[] filename= file.list();
for(String str:filename)
{
if(new File(folderName,str).isDirectory()) //通过递归方式获取下层文件夹中的文件夹
printJavaOfFolder(folderName+"\\"+str);
if(str.matches("\\w+\\.java"))
{
if(!(new File(folderName,str).isDirectory())) //剔除掉后缀名为.java的文件夹
System.out.println(folderName+"\\"+str);
}
}
}


Properties类

是HashTable的子类,具备了Map集合的特点,里面存储的键值对都是字符串。

加载信息时需要有固定格式:键=值。

 

常见方法

1. 获取、设置
setProperty(String key, String value);设置键值对,也可以通过覆盖重新设置值。
String getProperty(String key),通过键获得值
Set<String> stringPropertyNames(),返回一个Set<String>集合,通过遍历获得值。1.6以后出现。
 

2. 将文本文件中的键值对存到集合中进行操作。

步骤:1. 用一个流和文件关联。2. 读取一行数据,将该行数据用“=”切割。3. 等号右边为键,左边为值,存入集合中。例如,

3. 字节输出流,OutputStream。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  io流 File