`
yidongkaifa
  • 浏览: 4038662 次
文章分类
社区版块
存档分类
最新评论

Java I/O流操作(三)---File文件操作及打印流和序列流-合并流

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

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

File file2 =newFile("C:\\file\\test\\a.txt");
File d =newFile("C:\\file\\test\\");
File file3 =newFile(d,"a.txt");
File file4 =newFile("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类的常用方法了:
创建方法:
booleancreateNewFile()在指定位置创建文件,如果文件不存在,则创建成功返回true,如果文件已经存在,则不创建,返回false
这和输出流不同,输出流一旦实例化就会创建文件,文件不存在创建,存在则覆盖.
mkdir()创建文件夹
mkdirs()创建文件夹,包括父文件夹
删除方法:
boolean delete()
void deleteOnExit()
这两个方法是有区别的:
delete()根据抽象的路径名称删除文件,如果程序出现异常没有执行到该行代码,那么这个文件就不会被执行,有人会说放在finally执行,但是如果一个程序正在使用该文件,那么这个文件还是不能被删除.
deleteOnExit()这个方法不会发生这种情况,因为该方法在虚拟机停终止,文件就会被删除.
判断方法:
exists()表示抽象的路径名称所指示的文件或文件夹是否存在
canExecute()应用程序能否执行抽象路径名称所指示的文件
canRead()应用程序能否读取抽象路径名称所指示的文件
canWrite()应用程序能否修改抽象路径名称所指示的文件
isDirectory()抽象路径名称所指示的是不是文件夹
isFile()抽象路径名称所指示的是不是文件
isAbsolute()判断是否是绝对路径
File file =newFile("a.txt");
System.out.println("isDirectory:"+file.isDirectory());
System.out.println("isFile:"+file.isFile());
发现控制台输出

isDirectory:falseisFile:false

发现它既不是文件也不是目录,为什么会出现这样的情况呢?
原来用上面的两个方法判断时候,需要先判断该抽象的路径名称所指定的file和directory是否存在.存在才能进行判断.
获取信息:
FilegetAbsoluteFile()返回File对象的绝对路径,但是他把这个字符串封装成了File对象返回 这也是和getAbsolutePath的主要区别
StringgetAbsolutePath()返回File对象的绝对路径
StringgetPath()返回File对象的路径,如果File里的抽象路径名称是绝对路径,如果是相对路径,就返回相对路径
StringgetName()如果File对象里的抽象路径名称指定的是目录,那么返回的目录最后的文件夹名称,如果是文件,则返回文件的名称
StringgetParent()如果File对象里的抽象路径名称指定的是目录,那么返回的目录最后的文件夹的上一个文件夹的名称,如果是文件,则返回文件所在目录的名称,如果象路径名称指定的是相对路径,有可能返回null,如:File file = new File("a.txt");那么该file的父目录就是null.
FilegetParentFile()这和getParent的区别就是,这个方法把getParent方法的返回值封装成了File对象
longlength()返回文件的大小

renameTo(Filedest)重命名:
例如:
File f =newFile("C:\\test\\test.txt");
File f2 =newFile("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 =newFile("C:\\");
for(String name : file.list()) {
System.out.println(name);
}
输出结果为:C盘目录下的所有文件和目录包含隐藏文件,但是不包含子文件夹里的文件
文件过滤:
例如我想输出在某个文件夹下的java文件,那么这时候就要用到过滤文件:
String[]list(FilenameFilterfilter)我们查看API不难发现,FilenameFilter是一个接口里面只有一个方法booleanaccept(Filedir,Stringname)

publicstaticvoidmethod_1() {

finalFile file =newFile("D:\\");
String[] names = file.list(newFilenameFilter() {
publicbooleanaccept(File dir, String name) {
returnname.endsWith(".java");
}
});
for(String name : names)
System.out.println(name);

}

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

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

通过递归实现列出目录下的所有文件
publicstaticvoidmain(String[] args) {
File file =newFile("E:\\MyeclipseWorkbenck\\shop");
method_1(file);
}
publicstaticvoidmethod_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删除文件的原理是这样的,把最里面的文件删除,然后删除文件夹
publicstaticvoidmain(String[] args) {
File file =newFile("D:\\java");
deleteDir(file);
}
publicstaticvoiddeleteDir(File file){
File[] files = file.listFiles();
for(File file2 : files){
//如果是目录
if(file2.isDirectory()){
//则使用递归 调用本身
deleteDir(file2);
}else{
//不是目录就直接删除
file2.delete();
}
}
//然后删除空文件夹
file.delete();
}
怎么把java文件的路径存在一个文件里面,方便以后查找.
publicclassJavaFileItem {
publicstaticvoidmain(String[] args) {
List<File> list =newArrayList<File>();
saveJavaFilePath(newFile("E:\\MyeclipseWorkbenck\\HeimaTest"), list);
writeFilePath(list,"javaItem.txt");
}
//则把java文件放在集合中
publicstaticvoidsaveJavaFilePath(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的路径信息写入文件中
publicstaticvoidwriteFilePath(List<File> files, String targetFile) {
BufferedWriter buffw =null;
try{
FileWriter fw =newFileWriter(targetFile);
buffw =newBufferedWriter(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(Stringkey)根据key从Properties对象中获取值
setProperty(Stringkey,Stringvalue)为Properties对象设置key和value
store(OutputStreamout,Stringcomments)把Properties对象储存到一个文件里面去,底层通过字节输出流处理
store(Writerwriter,Stringcomments)这是JDK1.6后才有的,直接使用字符输出流就可以把Properties对象储存到文件中
load(InputStreaminStream)读取属性列表从字节输入流中,加载某个键值对文件,使得Properties与该文件相关联
load(Readerreader)这是JDK1.6后才出现的,读取属性列表从字符输入流中,
模拟限制软件使用次数:
publicstaticvoidcount()throwsIOException{
Properties properties =newProperties();
File file =newFile("count.ini");
if(!file.exists()){
file.createNewFile();
}
InputStream is =newFileInputStream(file);
properties.load(is);
String times = properties.getProperty("times");
intcount = 0;
if(times!=null){
count = Integer.parseInt(times);
if(count>=5)
System.out.println("你使用的次数已到,请续费!");
}
count++;
OutputStream os =newFileOutputStream(file);
properties.setProperty("times", count+"");
properties.store(os,"count times");
os.close();
is.close();
}
----------------------------------打印流------------------------
下面学习打印流对象PrintStream PrintWriter
首先PrintStream

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

大概的意思是说,PrintWriter类不像PrintStream类,如果设置了自动刷新(PrintWriter(Writerout, booleanautoFlush)或者通过PrintWriter(OutputStreamout, booleanautoFlush)设置),只有当调用println()printf() format()方法才会被刷新,而不是无论什么时候只要出现换行字符就会输出,这些方法使用的是平台自己的行分隔符标准,而不是使用换行字符.
接着看一下他的主要构造方法:
PrintWriter(StringfileName)
PrintWriter(OutputStreamout)
PrintWriter(OutputStreamout, booleanautoFlush)
PrintWriter(Writerout)
PrintWriter(Writerout, booleanautoFlush)
比较PrintStream和PrintWriter的构造方法的最大区别PrintWriter可以接受字符输出流Writer而PrintStream不能,所以PrintWriter更常用.
下面通过一个实例来运用它:
publicstaticvoidprint()throwsIOException{
//获取键盘输入
BufferedReader buffr =newBufferedReader(newInputStreamReader(System.in));
//目的是控制台
PrintWriter pw =newPrintWriter(System.out);
String value =null;
while((value=buffr.readLine())!=null){
pw.write(value);
//注意刷新
pw.flush();
}
pw.close();
buffr.close();
}
控制太输出如下:

发现他没有换行,看上去不美观:怎么实现换行呢?我们来看一下这两个个方法
API是这样解释println(Stringx)方法的Prints a String and then terminates the line. This method behaves as though it invokesprint(String)and thenprintln().
先打印字符串然后终止这行,也就是先调用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 propertyline.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 =newPrintWriter(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 =newPrintWriter(System.out,true););//设置自动刷新
String value =null;
while((value=buffr.readLine())!=null){
pw.println(value);();//因为println()printf()format()都会触发刷新
}
我们还可以猜想:
PrintWriter pw =newPrintWriter(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 =newPrintWriter(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)的定义:
publicvoidprintln(String x) {
synchronized(lock) {
print(x);//先打印数据
println();//再打印行分隔符,我们在进入println()是怎么定义的,
}
}
println()的定义:
publicvoidprintln() {
newLine();//打开是怎么样定义的
}
newLine()方法的定义:
privatevoidnewLine() {
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<? extendsInputStream>e)里面传一个Enumeration里面的元素使用了泛型限定.
SequenceInputStream(InputStreams1,InputStreams2)里面传入两个字节输入流对象
实例:怎么把3个文件的内容输入到一个文件中:
//通过Vector可以获取Enumeration
Vector<InputStream> vector =newVector<InputStream>();
vector.add(newFileInputStream("C:\\1.txt"));
vector.add(newFileInputStream("C:\\2.txt"));
vector.add(newFileInputStream("C:\\3.txt"));
//实例化合并流
SequenceInputStream sequence =newSequenceInputStream(vector.elements());
InputStreamReader isr =newInputStreamReader(sequence);
BufferedReader fr=newBufferedReader(isr);
BufferedWriter bw =newBufferedWriter(newFileWriter("C:\\123.txt"));
String value =null;
while((value=fr.readLine())!=null){
bw.write(value);
bw.newLine();
}
bw.close();
sequence.close();
-----------------------------------------切割流------------------------------------------------
需求 :一个MP3文件切割成几个文件:
publicstaticvoidcut()throwsException {
InputStream is =newFileInputStream("C:\\mp3\\卓依婷- 好人好梦.mp3");
OutputStream os =null;
byte[] buffer =newbyte[1024*1024];
intlen=0;
intname = 1;
while((len=is.read(buffer))!=-1) {
//每一次循环都会生成一个文件,这样就实现了切割
os =newFileOutputStream("C:\\mp3\\part\\"+(name++)+".part");
//每个文件写1M,最后一个文件可能没有1M
os.write(buffer,0,len);
os.close();
}
is.close();
}
发现part目录多了4个文件,并且大小和以前的文件一样:

从而也验证了前面4个文件都是1M最后一个没有1M的结论
现在怎么把上面的4个文件重新合并成一个文件
publicstaticvoidmerger()throwsException {
List<InputStream> list =newArrayList<InputStream>();
for(inti = 1; i <= 4; i++) {
list.add(newFileInputStream("C:\\mp3\\part\\"+ (i) +".part"));
}
finalIterator<InputStream> iterator = list.iterator();
Enumeration<InputStream> enumeration =newEnumeration<InputStream>(){
publicbooleanhasMoreElements() {
returniterator.hasNext();
}
publicInputStream nextElement() {
returniterator.next();
}
};
SequenceInputStream sequence =newSequenceInputStream(enumeration);
OutputStream os =newFileOutputStream("C:\\mp3\\part\\卓依婷- 好人好梦.mp3");
byte[] buffer =newbyte[1024];
intlen = 0;
while((len=sequence.read(buffer))!=-1){
os.write(buffer,0,len);
}
os.close();
sequence.close();
}

转载请注明出处 : http://blog.csdn.net/johnny901114/article/details/8710433

分享到:
评论

相关推荐

    IO体系.java

    将多个读取流合并成一个读取流,可以方便操作多个读取流。原理(迭代器)。 OutputStream |--FileOutputStream/:文件输出流。用于将写入File和FileDescriptor的输出流。用来操作图像,声音,视频等原始字节流。 ...

    Java开发详解.zip

    031207_【第12章:JAVA IO】_打印流笔记.pdf 031208_【第12章:JAVA IO】_System类对IO的支持笔记.pdf 031209_【第12章:JAVA IO】_BufferedReader笔记.pdf 031210_〖第12章:JAVA IO〗_IO操作实例笔记.pdf 031211_...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm ------------------------------------------------- 本教程由yyc,spirit整理 ------------------------------------------------- “Thinking in Java...

    java 编程入门思考

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    13.16.3 用Java 1.1 AWT制作窗口和程序片 13.16.4 再探早期示例 13.16.5 动态绑定事件 13.16.6 将商业逻辑与UI逻辑区分开 13.16.7 推荐编码方法 13.17 Java 1.1 UI API 13.17.1 桌面颜色 13.17.2 打印 13.17.3 剪贴...

    Java初学者入门教学

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    java联想(中文)

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    JAVA_Thinking in Java

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in Java简体中文(全)

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in Java 中文第四版+习题答案

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Think in Java(中文版)chm格式

    13.16.3 用Java 1.1 AWT制作窗口和程序片 13.16.4 再探早期示例 13.16.5 动态绑定事件 13.16.6 将商业逻辑与UI逻辑区分开 13.16.7 推荐编码方法 13.17 Java 1.1 UI API 13.17.1 桌面颜色 13.17.2 打印 13.17...

    ORACLE9i_优化设计与系统调整

    §6.2.8 步骤8:优化I/O和物理结构 89 §6.2.9 步骤9:优化资源争用 89 §6.2.10 步骤10:优化所采用的平台 89 §6.3 应用优化方法 90 §6.3.1 设定明确的优化目标 90 §6.3.2 创建最少可重复测试 90 §6.3.3 测试...

    Hadoop硬实战 [(美)霍姆斯著][电子工业出版社][2015.01]_PDF电子书下载 带书签目录 高清完整版.rar )

    3 数据序列化――处理文本文件及其他格式的文件 3.1 了解MapReduce 中的输入和输出 3.1.1 数据输入 3.1.2 数据输出 3.2 处理常见的序列化格式 3.2.1 XML . 技术点12 MapReduce 和XML 3.2.2 JSON...

    ThinkInJava

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    简单来说是本身可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增、截取、更新、删除等操作。 常见的数据模型 1. 层次结构模型: 层次结构模型实质上是一种有根结点的定向有序树,IMS...

    Hadoop实战(第2版)

    10.2.1 序列化和反序列化技术点64 载入日志文件10.2.2 UDF、分区、分桶和压缩技术点65 编写UDF 和压缩分区表10.2.3 数据合并技术点66 优化Hive 合并10.2.4 分组、排序和explain 10.3 本章小结11 ...

    thinkinjava

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    kettle文档自己整理的带例子

    3.3)合并记录 7 3.4) 9 4、 转换 10 4.1)split field to rows 10 4.2)去掉重复记录 11 4.3)增加常量 12 4.4)增加序列 12 4.5)字段选择 13 4.6)拆分字段 14 4.7)排序记录 14 4.8)换转列 15 4.9)计算器 16 4.10)...

    HBU2019programingtext:2019河北大学HBU程序设计训练营

    使用语言主要为C++ 和 Java 可能存在诸多漏洞 欢迎指正 联系方式 :e-mail: :party_popper: :party_popper: FileTree.txt │ README.md │ ├─2019HBU小学期数组和链表专题 │ 7-14 最长对称子串 (25 分).cpp │ 7...

Global site tag (gtag.js) - Google Analytics