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

黑马程序员—【Java基础篇】之IO流(二)———File类、递归、IO其它流和编码表

2015-04-28 11:05 591 查看
------- android培训java培训、期待与您交流!
---------
这篇我们继续下篇IO流,主要讲解有File类、递归、IO其它流和编码表这四块内容,额,小伙伴们继续吧。

一、File类

1、概述

/**
File类简介

(1)用来将文件或者文件夹封装成对象
(2)方便对文件与文件夹的属性信息进行操作。
(3)File对象可以作为参数传递给流的构造函数。
*/


2、创建方式

/**
方式(1):
File f =new File("a.txt");
将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。
方式(2):
File f2=newFile("c:\\abc","b.txt");
将文件所在目录路径和文件一起传入,指定文件路径。
方式(3):
File d=new File("c:\\abc");
File f3=new File(d,"c.txt");
将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。
小知识:
File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。
*/

3、方法

(1)创建
boolean createNewFile()://在指定位置创建文件,如果该文件已经存在,则不创建,返回false;和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

boolean mkdir()://创建文件夹。
boolean mkdirs()://创建多级文件夹。
(2)删除
boolean delete();//删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();//在程序退出时删除指定文件。

(3)判断
boolean exists() ;//文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();

(4)获取信息
getName():
getPath():
getParent():
getAbsolutePath()
long lastModified()
long length()
方法示例:

//需求:方法演示
class FileDemo
{
public static void main(String[] args) throws IOException
{
method_5();
}

public static void method_5()
{
File f1 = new File("c:\\Test.java");
File f2 = new File("d:\\hahaha.java");

sop("rename:"+f2.renameTo(f1));

}

public static void method_4()
{
File f = new File("file.txt");

sop("path:"+f.getPath());
sop("abspath:"+f.getAbsolutePath());
sop("parent:"+f.getParent());//该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
//如果相对路径中有上一层目录那么该目录就是返回结果。
}
public static void method_3()throws IOException
{
File f = new File("d:\\java1223\\day20\\file2.txt");
//f.createNewFile();
//f.mkdir();
//记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
//通过exists判断。
sop("dir:"+f.isDirectory());
sop("file:"+f.isFile());
sop(f.isAbsolute());
}

public static void method_2()
{
File f = new File("file.txt");

//sop("exists:"+f.exists());

//sop("execute:"+f.canExecute());

//创建文件夹
File dir = new File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa");

sop("mkdir:"+dir.mkdirs());
}

public static void method_1()throws IOException
{
File f = new File("file.txt");
//		sop("create:"+f.createNewFile());
//sop("delete:"+f.delete());

}
//创建File对象
public static void consMethod()
{
//将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
File f1 = new File("a.txt");
//
File f2 = new File("c:\\abc","b.txt");
File d = new File("c:\\abc");
File f3 = new File(d,"c.txt");
sop("f1:"+f1);
sop("f2:"+f2);
sop("f3:"+f3);
File f4 = new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt");

}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
练习:

/**
需求:列出指定目录下文件或者文件夹,包含子目录中的内容;也就是列出指定目录下所有内容。
分析:因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可;在列出过程中出现的还是目录的话,还可以再次调用本功能;也就是函数自身调用自身。
*/
import java.io.*;
class FileDemo3
{
public static void main(String[] args)
{
File dir = new File("d:\\testdir");
//showDir(dir,0);

//toBin(6);
//int n = getSum(8000);
//System.out.println("n="+n);

System.out.println(dir.delete());
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x=0; x<level; x++)
{
//sb.append("|--");
sb.insert(0,"|  ");

}
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]);
}
}<pre name="code" class="java">/**
示例中,其中列出过程中出现的还是目录的,还可以再次调用本功能即函数自身调用自身。这种表现形式,或者编程手法,称为递归。
*/


二、递归

1、概述

/**
(1)特点: 函数自己调用自己。
(2)注意事项:递归时一定要明确结束条件。
(3) 应用:
当某一功能要重复使用时。
*/

2、练习

import java.io.*;

class  FileDemo2
{
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());
}

}

public static void listDemo_2()
{
File dir = new File("d:\\java1223\\day18");

String[] arr = dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{
return name.endsWith(".bmp");

}
}
System.out.println("len:"+arr.length);
for(String name : arr)
{
System.out.println(name);
}
}

public static void listDemo()
{
File f = new File("c:\\abc.txt");

String[] names = f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
for(String name : names)
{
System.out.println(name);
}
}
public static void listRootsDemo()
{
File[] files = File.listRoots();

for(File f : files)
{
System.out.println(f);
}
}
}

3、递归原理

通过二张图片,分析:



第二张图:



三、IO流其它类

1、RandomAccessFile类

/**
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)来达到随机访问。<pre name="code" class="java">(1)定义:该类不是算是IO体系中子类,而是直接继承自Object;但是它是IO包中成员,因为它具备读和写功能。
(2)缘由:内部封装了一个数组,而且通过指针对数组的元素进行操作;可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。通俗说它完成读写的原理就是内部封装了字节输入流和输出流。<pre name="code" class="java">*/




示例:
class RandomAccessFileDemo //RandomAccessFile示例
{
public static void main(String[] args) throws IOException
{
//writeFile_2();
//readFile();

//System.out.println(Integer.toBinaryString(258));

}

public static void readFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");

//调整对象中指针。
//raf.seek(8*1);

//跳过指定的字节数
raf.skipBytes(8);

byte[] buf = new byte[4];

raf.read(buf);

String name = new String(buf);

int age = raf.readInt();

System.out.println("name="+name);
System.out.println("age="+age);

raf.close();
}

public static void writeFile_2()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*0);
raf.write("周期".getBytes());
raf.writeInt(103);

raf.close();
}

public static void writeFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");

raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);

raf.close();
}
}

2、管道流

/**
(1)管道流
PipedInputStream和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。
*/
示例:

import java.io.*;
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();
}
}

3、打印流

/**
(1)概述
1、打印流包括:PrintStream和PrintWriter
2、该流提供了打印方法,可将各种类型的数据都原样打印。

(2)字节打印流:PrintStream
构造方法中可接收的参数类型:
a、File对象。File
b、字符串路径:String
c、字符输出流:OutputStream

(3)字符串打印流:PrintWriter
构造方法中可接受的参数类型
1、File对象:File
2、字符串路径:String
3、字节输出流:OutputStream
4、字符输出流:Writer
*/

示例:
import java.io.*;
class  PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
//键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));

//打印流关联文件,自动刷新
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);

String line = null;

while((line=bufr.readLine())!=null)
{
if("over".equals(line))//结束字符
break;
out.println(line.toUpperCase());
//out.flush();
}

//关流
out.close();
bufr.close();
}
}

4、合并流

/**
(1)概述
a、SequenceInputStream对多个流进行合并。也被称为合并流。
b、常用构造函数
SequenceInputStream(Enumeration<?extends FileInputStream> e)

(2)常见合并多个流文件步骤
a、创建集合,并将流对象添加进集合
b、创建Enumeration对象,将集合元素加入。
c、创建SequenceInputStream对象,合并流对象
d、创建写入流对象,FileOutputStream关联写入文件
e、利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。
*/
示例:

/**
SequenceInputStream
合并流
需求:将三个文本文件中的数据合并到一个文本文件中
思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中
2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration
3、输出流关联新文本文件
4、反复读写操作
*/
import java.util.*;
import java.io.*;

class  SequenceInputStreamDemo
{
public static void main(String[] args)throws IOException
{
Vector<InputStream> ve=new Vector<InputStream>();//创建vector集合,并添加相关流对象
ve.add(new FileInputStream("1.txt"));
ve.add(new FileInputStream("2.txt"));
ve.add(new FileInputStream("3.txt"));

Enumeration<InputStream> en=ve.elements();//创建枚举对象
SequenceInputStream sis=new SequenceInputStream(en);//合并流

FileOutputStream fos=new FileOutputStream("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();
}
}
练习:

/**
切割文件
需求:将一个mp3文件按1M大小切割成几部分
思路:(1)使用文件字节流关联mp3文件
(2)定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中
步骤:<pre name="code" class="java">(1)先关联文件FileInputStream
(2)定义写入流变量:FileOutputStream
(3)创建数组,并定义切割所需的大小|
(4)循环读写数据,并每次创建一个新写入流,创建完后并写入文件中
(5)关闭流资源<pre name="code" class="java">*/<pre name="code" class="java">import java.util.*;
import java.io.*;

class  SplitFile
{
public static void main(String[] args) throws IOException
{
//指定要切割的文件
File file=new File("C:\\Users\\asus\\Desktop\\苏芮 - 一样的月光.mp3");
//将指定文件进行切割
splitFile(file);

//指定要合并到的文件
File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\一样的月光.mp3");
//将部分文件进行合并指定文件中
merge(file1);

}
//接收一个文件,将其按1M大小进行切割
public static void splitFile(File file)throws IOException
{
//关联要切割的文件
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));

BufferedOutputStream bos=null;

//定义1M大小存储容器
byte[] buf=new byte[1024*1024];
int len=0,x=0;
while ((len=bis.read(buf))!=-1)
{
//每满1M就写入一个新文件中
bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));
bos.write(buf,0,len);
bos.close();//没写完一个文件要记得关流
}
//关流
bis.close();
}

//将部分文件合并为一个可执行文件
public static void merge(File file)throws IOException
{
//定义一个集合存储这些部分文件关联路径数据
ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();

for (int x=1;x<=6 ; x++)
{
al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));
}

//因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类
final  ListIterator<FileInputStream> it=al.listIterator();
Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}

public FileInputStream nextElement()
{
return it.next();
}
};

//关联枚举对象
SequenceInputStream sis=new SequenceInputStream(en);

//将合并的文件数据写入指定文件中
FileOutputStream fos=new FileOutputStream(file);

//定义临时存储数据的数组
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);//写数据
}

//关流
fos.close();
sis.close();
}
}




四、编码表

1、概述

/**
(1)字符流的出现为了方便操作字符,更重要是的加入了编码转换,通过子类转换流来完成。
(2)编码表的由来:
计算机只能识别二进制数据,早期由来是电信号;为了方便应用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张表,于是就有了编码表。
(3)方式:
通过子类转换流来完成,InputStreamReader、OutputStreamWriter在两个对象进行构造的时候可以加入字符集。
*/

2、常见的码表

/**
(1)ASCII:美国标准信息交换码,用一个字节的7位可以表示。
(2)ISO8859-1:拉丁码表,欧洲码表
用一个字节的8位表示。
(3)GB2312:中国的中文编码表,GBK:中国的中文编码表升级,融合了更多的中文文字符号。
(4)Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode
(5)UTF-8:最多用三个字节来表示一个字符。
*/

3、应用

/**
(1)可以将字符以指定编码格式存储。
(2)可以对文本数据指定编码格式来解读。
(3)指定编码表的动作由构造函数完成。
*/

练习:

/**
编码:字符串变成字节数组。
解码:字节数组变成字符串。
String-->byte[];  str.getBytes(charsetName);
byte[] -->String: new String(byte[],charsetName);
*/
import java.util.*;
class  EncodeDemo
{
public static void main(String[] args)throws Exception
{
String s = "哈哈";

byte[] b1 = s.getBytes("GBK");

System.out.println(Arrays.toString(b1));
String s1 = new String(b1,"utf-8");
System.out.println("s1="+s1);

//对s1进行iso8859-1编码。
byte[] b2 = s1.getBytes("utf-8");
System.out.println(Arrays.toString(b2));

String s2 = new String(b2,"gbk");

System.out.println("s2="+s2);
}
}
图片1说明:



图片2说明:



好了,伙伴们,这篇IO流我们就分享到这里,下面见,伙伴们。

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