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

黑马程序员_java基础视频第20天_JavaIO流续2

2011-10-03 17:22 441 查看
---------------------- android培训java培训、期待与您交流! ----------------------

---------------------------------------------File---------------------------------------------

用来将文件或者文件夹封装成对象
方便对文件与文件夹进行操作
File对象可以作为参数传递给流的构造函数.
下面来看一下File类的构造方法:



File file =new File("a.txt");

File file2 =new File("C:\\file\\test\\a.txt");
File d =new File("C:\\file\\test\\");
File file3 =new File(d,
"a.txt");
File file4 =new File("C:\\file\\test\\","a.txt");//这和file3是一回事
System.out.println(file +"\r\n" + file2 +
"\r\n" + file3 +"\r\n" + file4 +
"\r\n");
控制台输出为:

a.txt
C:\file\test\a.txt
C:\file\test\a.txt
C:\file\test\a.txt

但是我们在程序中,文件的路径分隔符只能在windows平台下,在Linux就不能用了,怎么现在跨平台呢?
File file5 = new File("C:"+File.separator+"file"+File.separator+"test"+File.separator+"", "a.txt");

接下来就是File类的常用方法了:
创建方法:
boolean createNewFile()在指定位置创建文件,如果文件不存在,则创建成功返回true,如果文件已经存在,则不创建,返回false
这和输出流不同,输出流一旦实例化就会创建文件,文件不存在创建,存在则覆盖.
mkdir()创建文件夹
mkdirs()创建文件夹,包括父文件夹
删除方法:

boolean
delete()
void
deleteOnExit()
这两个方法是有区别的:
delete()根据抽象的路径名称删除文件,如果程序出现异常没有执行到该行代码,那么这个文件就不会被执行,有人会说放在finally执行,但是如果一个程序正在使用该文件,那么这个文件还是不能被删除.
deleteOnExit()这个方法不会发生这种情况,因为该方法在虚拟机停终止,文件就会被删除.
判断方法:
exists() 表示抽象的路径名称所指示的文件或文件夹是否存在
canExecute()应用程序能否执行抽象路径名称所指示的文件

canRead()应用程序能否读取抽象路径名称所指示的文件
canWrite() 应用程序能否修改抽象路径名称所指示的文件
isDirectory()抽象路径名称所指示的是不是文件夹
isFile()抽象路径名称所指示的是不是文件
isAbsolute()判断是否是绝对路径

File file =new File("a.txt");
System.out.println("isDirectory:"+file.isDirectory());
System.out.println("isFile:"+file.isFile());
发现控制台输出
isDirectory:falseisFile:false

发现它既不是文件也不是目录,为什么会出现这样的情况呢?
原来用上面的两个方法判断时候,需要先判断该抽象的路径名称所指定的file和directory是否存在.存在才能进行判断.

获取信息:

File getAbsoluteFile() 返回File对象的绝对路径,但是他把这个字符串封装成了File对象返回 这也是和getAbsolutePath的主要区别

String getAbsolutePath() 返回File对象的绝对路径
String getPath() 返回File对象的路径,如果File里的抽象路径名称是绝对路径,如果是相对路径,就返回相对路径

String getName()如果File对象里的抽象路径名称指定的是目录,那么返回的目录最后的文件夹名称,如果是文件,则返回文件的名称
String getParent()如果File对象里的抽象路径名称指定的是目录,那么返回的目录最后的文件夹的上一个文件夹的名称,如果是文件,则返回文件所在目录的名称,如果象路径名称指定的是相对路径,有可能返回null,如:File
file = new File("a.txt");那么该file的父目录就是null.

File getParentFile()这和getParent的区别就是,这个方法把[b]getParent方法的返回值封装成了File对象[/b]

long length() 返回文件的大小

renameTo(File dest)
重命名:
例如:

File f =new File("C:\\test\\test.txt");
File f2 =new File("C:\\test\\testDemo.txt");
f.renameTo(f2);

如果盘符或者目录不同这就成了剪切了

文件列表:
File [] listRoots() 返回系统盘符的名称 如:C D盘等

String[] list() 返回File目录下的所有文件 如果抽象的路径名称指定的是一个文件将会出现空指针异常;并且该目录一定要存在

例如1:

for(File file: File.listRoots()){
System.out.println(file);
}
输出结果为:

C:\
D:\
E:\
F:\
G:\
例如2:

File file =new File("C:\\");
for (String name : file.list()) {
System.out.println(name);
}

输出结果为:C盘目录下的所有文件和目录包含隐藏文件,但是不包含子文件夹里的文件

文件过滤:
例如我想输出在某个文件夹下的java文件,那么这时候就要用到过滤文件:
String[] list(FilenameFilter filter)
我们查看API不难发现,FilenameFilter 是一个接口里面只有一个方法booleanaccept(File dir,String name)
publicstatic
void method_1() {

final File file =new File("D:\\");
String[] names = file.list(new FilenameFilter() {
publicboolean accept(File dir, String name) {
return name.endsWith(".java");
}
});

for (String name : names)
System.out.println(name);

}

下面来看一下:
File[] listFiles() ;这个方法和list()
方法的区别是list() 方法是返回一个个字符串的,而listFiles()是返回一个个File对象.那么就可以通过File对象获取文件的信息了,所以File[]listFiles()方法更使用一些.例如:

File file =new File("C:\\");
for(File file2 : file.listFiles()){
System.out.println(file2.getName());
}
listFiles()同样也有自己的过滤功能.通过listFiles(FileFilter filter)
方法可以实现.

通过递归实现列出目录下的所有文件

publicstatic
void main(String[] args) {
File file =new File("E:\\MyeclipseWorkbenck\\shop");
method_1(file);
}

publicstatic
void method_1(File file) {
System.out.println(file.getAbsolutePath());
File[] files = file.listFiles();
for (File file2 : files) {
if(file2.isDirectory()){
method_1(file2);
}else {
System.out.println(file2.getName());
}

}
}

删除带目录的文件,如果直接使用delete方法,则不能删除成功,因为java删除文件的原理是这样的,把最里面的文件删除,然后删除文件夹

publicstatic
void main(String[] args) {
File file =new File("D:\\java");
deleteDir(file);
}
publicstatic
void deleteDir(File file){
File[] files = file.listFiles();
for(File file2 : files){
//如果是目录
if(file2.isDirectory()){
//则使用递归 调用本身
deleteDir(file2);
}else {
//不是目录就直接删除
file2.delete();
}
}
//然后删除空文件夹
file.delete();
}

怎么把java文件的路径存在一个文件里面,方便以后查找.

publicclass JavaFileItem {
publicstatic
void main(String[] args) {
List<File> list =new ArrayList<File>();
saveJavaFilePath(new File("E:\\MyeclipseWorkbenck\\HeimaTest"),
list);
writeFilePath(list,"javaItem.txt");
}
//则把java文件放在集合中
publicstatic
void saveJavaFilePath(File dir, List<File> list) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
saveJavaFilePath(file, list);
}else {
//如果是java文件,则把该文件放在集合中
if (file.getAbsolutePath().endsWith(".java"))
list.add(file);
}
}
}
//把java的路径信息写入文件中
publicstatic
void writeFilePath(List<File> files, String targetFile) {
BufferedWriter buffw =null;
try {
FileWriter fw =new FileWriter(targetFile);
buffw =new BufferedWriter(fw);
for (File file : files) {
//把java文件的绝对路径写入文件
buffw.write(file.getAbsolutePath());
//换行
buffw.newLine();
//使用字符流注意刷新
buffw.flush();
}
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (buffw !=null)
buffw.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里就是使用递归和IO操作的结合了.
----------------------------------------------------关于Properties类:--------------------------------------------

关于Properties类:
Properties是Hashtable的子类,也就是说它具备map结婚的特点,而且它里面存储的键值对都是字符串
他是集合和IO相结合的集合容器
该对象的特点是可以用于键值对形式的配置文件
getProperty(String key)
根据key从Properties对象中获取值

setProperty(String key,String value)
为Properties对象设置key和value

store(OutputStream out,String comments)
把Properties对象储存到一个文件里面去,底层通过字节输出流处理

store(Writer writer,String comments)
这是JDK1.6后才有的,直接使用字符输出流就可以把Properties对象储存到文件中

load(InputStream inStream)
读取属性列表从字节输入流中,加载某个键值对文件,使得Properties与该文件相关联

load(Reader reader)
这是JDK1.6后才出现的,读取属性列表从字符输入流中,

模拟限制软件使用次数:

publicstatic
void count()throws IOException{
Properties properties =new Properties();
File file =new File("count.ini");
if(!file.exists()){
file.createNewFile();
}
InputStream is =new FileInputStream(file);
properties.load(is);
String times = properties.getProperty("times");
int count = 0;
if(times!=null){
count = Integer.parseInt(times);
if(count>=5)
System.out.println("你使用的次数已到,请续费!");
}
count++;
OutputStream os =new FileOutputStream(file);
properties.setProperty("times", count+"");
properties.store(os,"count times");
os.close();
is.close();
}

-----------------------------------------------------打印流---------------------------------------------------------------------------
下面学习打印流对象PrintStream PrintWriter
首先PrintStream



大概的意思是说PrintStream相比其他的输出流增强了许多功能,也就是很方便的打印数据,另外PrintStream还可以自动刷新,也就是说一个字节数组被写入或者调用println方法或者写入了换行字符或者字节\n 后这个flush方法会被自动调用
PrintStream的常用的构造方法:
PrintStream(File file)

PrintStream(OutputStream out)

PrintStream(OutputStream out,
boolean autoFlush)

PrintStream(String fileName)

PrintStream(OutputStream out,
boolean autoFlush, String encoding)

看一下PrintWriter的API



大概的意思是说,PrintWriter类不像PrintStream类,如果设置了自动刷新(PrintWriter(Writer out,
boolean autoFlush) 或者通过PrintWriter(OutputStream out,
boolean autoFlush) 设置),只有当调用println()printf() format()方法才会被刷新,而不是无论什么时候只要出现换行字符就会输出,这些方法使用的是平台自己的行分隔符标准,而不是使用换行字符.
接着看一下他的主要构造方法:
PrintWriter(File file)
PrintWriter(String fileName)

PrintWriter(OutputStream out)

PrintWriter(OutputStream out,
boolean autoFlush)

PrintWriter(Writer out)

PrintWriter(Writer out,
boolean autoFlush)
比较PrintStream和PrintWriter的构造方法的最大区别PrintWriter可以接受字符输出流Writer而PrintStream不能,所以PrintWriter更常用.
下面通过一个实例来运用它:

publicstatic
void print()throws IOException{
//获取键盘输入
BufferedReader buffr =new BufferedReader(new InputStreamReader(System.in));
//目的是控制台
PrintWriter pw =new PrintWriter(System.out);
String value =null;
while((value=buffr.readLine())!=null){
pw.write(value);
//注意刷新
pw.flush();
}
pw.close();
buffr.close();

}
控制太输出如下:



发现他没有换行,看上去不美观:怎么实现换行呢?我们来看一下这两个个方法
println(String x)
println()
API是这样解释println(String x)方法的Prints
a String and then terminates the line. This method behaves as though it invokes
print(String)
and then
println()
.
先打印字符串然后终止这行,也就是先调用print(String str)方法然后在调用println()方法.

API是这样解释println() 方法 的
Terminates the current line by writing the line separator string. The line separator string is defined by the system property[code]line.separator
, and is not necessarily a single newline character (
'\n'
). 也就是通过行分隔符终止当前行,行分隔符通过系统属性
line.separator设置的而不需要简单的换行符'\n'

是不是我们通过println();方法就可以解决上面的问题呢?
while((value=buffr.readLine())!=null){
pw.write(value);
pw.println();//终止一行
//手动刷新
pw.flush();
}
还有方法可以解决,因为上面说了可以通过设置是否自动刷新而不是手动刷新,所以可以把 pw.flush();注释掉如:

PrintWriter pw =new PrintWriter(System.out,true);//设置自动刷新
String value =null;
while((value=buffr.readLine())!=null){
pw.write(value);
pw.println();//因为println()printf()format()都会触发刷新
//pw.flush();
}

我们还可以不使用write(),使用println(String)就会更加简单
PrintWriter pw =new PrintWriter(System.out,true););//设置自动刷新

String value =null;
while((value=buffr.readLine())!=null){
pw.println(value);();//因为println()printf()format()都会触发刷新
}

我们还可以猜想:

PrintWriter pw =new PrintWriter(System.out,true););//设置自动刷新
String value =null;
while((value=buffr.readLine())!=null){
pw.write(value+"\r\n");//末尾加上换行符是否会触发自动刷新呢?
}
答案是否定的,在PrintWriter的API有这样一句话These methods use the platform's own notion of line separator rather than the newline character. 也就是说
是否会触发自动刷新,java内部不是使用换行符("\r\n")而是使用平台内部的行分隔符(当然在windows他们是一样的).
那么我们可不可以模拟这个java内部所谓的行分隔符呢?在学习System类的时候我们可以得到系统的环境变量,在里面我们发现了行分隔符"line.separator"

我们来测试一下
PrintWriter pw =new PrintWriter(System.out,true););//设置自动刷新
while((value=buffr.readLine())!=null){
pw.write(value+System.getProperty("line.separator"));//我们使用writer方法,里面的字符串参数加上行分隔符,因为java
api里面说println()因为内部加上了行分隔符才会触发刷新的,那么现在我们手工加上行分隔符会触发刷新吗?

}
测试的结果还是不行!
那么为什么?java不是要系统的行分隔符吗?我现在已经加上了行分隔符还不行呢?
我们来看一下PrintWriter的源代码是怎么定义println(String)方法的
println(String)的定义:

publicvoid println(String x) {
synchronized (lock) {
print(x);//先打印数据
println();//再打印行分隔符,我们在进入println()是怎么定义的,
}
}

println()的定义:
publicvoid println() {
newLine();//打开是怎么样定义的
}

newLine()方法的定义:
privatevoid newLine() {
try {
synchronized (lock) {
ensureOpen();
out.write(lineSeparator);//写入行分隔符
if (autoFlush)//判断是否设置刷新
out.flush();//如果设置为true,那么调用flush()方法
}
}catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}catch (IOException x) {
trouble =true;
}
}
经过我查看writer()方法的源代码,没有发现他去判断是否刷新,
结论:尽管我们在使用writer(String)方法的String参数后面加上了行分隔符,但是在writer方法里面根本不去判断是否设置了autoFlush=true
所以我们在writer(String)方法的String参数后面加上了行分隔符也不能达到预期的效果!
如果我们想更加了解PrintStream和PrintWriter的区别,查看源代码是最好的帮手.PrintStream是字节输出流的子类,PrintWriter是字符输出流的子类.

-----------------------------------------序列流-合并流---------------------------------------------------------------------
简单的说就是把多个字节输入流合并成一个字节输入流,
SequenceInputStream(Enumeration<?
extends InputStream> e) 里面传一个Enumeration里面的元素使用了泛型限定.

SequenceInputStream(InputStream s1,InputStream s2)
里面传入两个字节输入流对象

实例:怎么把3个文件的内容输入到一个文件中:

//通过Vector可以获取Enumeration
Vector<InputStream> vector =new Vector<InputStream>();
vector.add(new FileInputStream("C:\\1.txt"));
vector.add(new FileInputStream("C:\\2.txt"));
vector.add(new FileInputStream("C:\\3.txt"));
//实例化合并流
SequenceInputStream sequence =new SequenceInputStream(vector.elements());
InputStreamReader isr =new InputStreamReader(sequence);
BufferedReader fr=new BufferedReader(isr);
BufferedWriter bw =new BufferedWriter(new FileWriter("C:\\123.txt"));
String value =null;
while((value=fr.readLine())!=null){
bw.write(value);
bw.newLine();
}
bw.close();
sequence.close();

-----------------------------------------切割流----------------------------------------------------------------------

需求 :一个MP3文件切割成几个文件:

publicstatic
void cut()throws Exception {
InputStream is =new FileInputStream("C:\\mp3\\卓依婷- 好人好梦.mp3");
OutputStream os =null;
byte[] buffer =new
byte[1024*1024];
int len=0;
int name = 1;
while ((len=is.read(buffer))!=-1) {
//每一次循环都会生成一个文件,这样就实现了切割
os =new FileOutputStream("C:\\mp3\\part\\"+(name++)+".part");
//每个文件写1M,最后一个文件可能没有1M
os.write(buffer,0,len);
os.close();
}
is.close();
}
发现part目录多了4个文件,并且大小和以前的文件一样:



从而也验证了前面4个文件都是1M最后一个没有1M的结论
现在怎么把上面的4个文件重新合并成一个文件

publicstatic
void merger()throws Exception {
List<InputStream> list =new ArrayList<InputStream>();
for (int i = 1; i <= 4; i++) {
list.add(new FileInputStream("C:\\mp3\\part\\" + (i) +".part"));
}
final Iterator<InputStream> iterator = list.iterator();
Enumeration<InputStream> enumeration =new Enumeration<InputStream>(){
publicboolean hasMoreElements() {
return iterator.hasNext();
}
public InputStream nextElement() {
return iterator.next();
}
};
SequenceInputStream sequence =new SequenceInputStream(enumeration);
OutputStream os =new FileOutputStream("C:\\mp3\\part\\卓依婷- 好人好梦.mp3");
byte[] buffer =new
byte[1024];
int len = 0;
while((len=sequence.read(buffer))!=-1){
os.write(buffer,0,len);
}
os.close();
sequence.close();
}



---------------------- android培训java培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: