---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
File类:用来将文件或者文件夹封装成对象。方便对文件与文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。
流只能操作数据,File对象操作数据封装成的文件信息。
File f1=new File("路径\\文件");//把文件做成File对象
File f2=new File("路径","文件");//和上面一样,后面参数可以传进来String参数变量
File d=new File("路径");
File f3=new File(d,"文件");//和上面二者一样
File类中有一个seperator静态变量,是File的目录分隔符,可以跨平台
File类常见方法
1创建
boolean createNewFile():指定位置创建文件,如果已存在,则返回false。和输出流不一样
File dir=new File("路径");dir.mkdir();//创建一层目录,返回true false
dir.mkdirs()//创建路径中的多层目录 返回true false
2删除
boolean delete();删除此对象文件,返回是否删成功
void deleteOnExit();退出java虚拟机时候删除此文件。这是为了防止,如果流正在对文件读写,删除文件是不会被允许的。本命令就是告诉程序,一会儿虚拟机停了,就把 这个文件删了。
3判断
boolean canExecute()判断文件是否能执行
boolean exists()判断文件是否存在
boolean isFile()
boolean isDirectory()是否文件夹
boolean isHidden()是否是隐藏文件
boolean isAbsolute()判断对象是否是绝对路径的,即使对象封装内容不存在也能够判断
在判断文件对象是否是文件或者目录时,必须先要判断该文件对象的封装的内容是否存在
4获取信息
getName()
getPath()
getParent()
getAbsolutePath()
long lastModified()
long length()
list();//获取此文件夹对象中的所有一级文件和文件夹名称,放在一个String类型数组中。如果被一个文件
File f=new File("c:\\");//对象调用,返回空。
String[] names=f.list();
f.listRoots()//获取系统所有的根目录列表,即所有磁盘盘符列表。返回一个File数组。
String[] list()//把文件夹对象中的一级文件文件夹名称都返回给一个String数组
String[] list(FilenameFilter filter)//把文件夹对象中的满足filter的一级文件文件夹名称都返回给一个String数组
File[] listFiles()返回一个文件对象数组,数组中是文件夹中所有的一级文件和目录的File对象。
File[] listFiles(FilenameFilter filter)把文件夹对象中的满足filter的一级文件文件夹对象都返回给一个File数组
public class FileDemo2 {
public static void main(String[]args){
//listDemo();
listDemo2();
}
public static void listDemo(){
File f=new File("c:\\");
//String[] list(FilenameFilter filter)把文件夹对象中的满足filter的一级文件文件夹名称都返回给一个
//String数组。
//过滤器要重写accept方法。
String[] names=f.list(new FilenameFilter(){
public boolean accept(File dir,String name){
return name.endsWith(".x");
}
});
for(String name:names){
System.out.println(name );
}
}
public static void listDemo2(){
File f=new File("c:\\");
//File[] list(FilenameFilter filter)把文件夹对象中的满足filter的一级文件文件夹名称都返回给一个
//File数组。
//过滤器要重写accept方法。
File[] files=f.listFiles(new FilenameFilter(){
public boolean accept(File dir,String name){
return name.endsWith(".x");
}
});
for(File file:files){
System.out.println("name:"+file.getName() );
System.out.println("path:"+file.getPath());
System.out.println("length:"+file.length());
}
}
public static void listRootsDemo(){
File[] files=File.listRoots();
for(File f:files){
System.out.println(f);
}
}
}
删除一个文件夹内所有文件
/*删除一个文件及其所有内容。从里往外删除,用递归*/
public class RemoveDir {
public static void main(String[]args){
removeDir(new File("e:\\111 test"));
}
public static void removeDir(File dir){
File[]files=dir.listFiles();
for(File f:files){
if(f.isDirectory()){
removeDir(f);
}
else System.out.println(f.toString()+"::"+f.delete());
}
System.out.println(dir.toString()+"--DIR::"+dir.delete());
}
}
/*将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表文件
* 思路:1对指定目录进行递归
* 2获取递归过程中所有的java文件的路径
* 3将这些路径存储到集合中
* 4将集合中的数据写入到文件中
*/
public class JavaFileList {
public static void main(String[]args) throws IOException{
List<File> list=new ArrayList<File>();
fileToList(new File("E:\\test"),list);
if(list.isEmpty()) System.out.println("没内容");
else{
for(File f:list){
System.out.println(f);
}
}
writeTofile(list);
}
public static void fileToList(File dir,List<File> list){
File[] files=dir.listFiles();
for(File f:files){
if(f.isDirectory()){
fileToList(f,list);
}else if(f.getName().endsWith(".java")){
list.add(f);
}
}
}
public static void writeTofile(List<File> list) throws IOException{
BufferedWriter buw=new BufferedWriter(new FileWriter("E:\\testto.txt"));
for(File f:list){
buw.write(f.getAbsolutePath());
buw.newLine();
buw.flush();
}
buw.close();
}
}
打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流PrintStream:构造函数可以接收的参数类型:
1 File对象:File
2 字符串路径:String
3 字节输出流:OutputStream
字符输出流PrintWriter:
1 File对象:File
2 字符串路径:String
3 字节输出流:OutputStream
4 字符输出流:Writer
合并流:SequenceInputStream。可以将多个字节输入流按顺序汇总到一起。需要用Vector的Enumeration对象,这是个有序集合对象,来有序装入各输入流
Vector<FileInputStream>v=new Vector<FileInputStream>();
v.add(new FileInputStream("E:\\1.txt"));
v.add(new FileInputStream("E:\\2.txt"));
v.add(new FileInputStream("E:\\3.txt"));
Enumeration<FileInputStream> en=v.elements();//Enumeration是一个枚举集合,通常用于接收vector的elements()方法得到的所有元素
SequenceInputStream sis=new SequenceInputStream(en);
现在sis就是一个字节输入流了,可以配一个字节输出流进行操作了。
切割文件:
一个输入流,一个固定大小字节数组,每次read一次填写入数组,然后new一个输出流到一个新文件。直到read值为-1.
public class SplitFile {
static int i=1;
public static void main(String[]args) throws IOException{
SplitFile();
HebingFile();
}
public static void SplitFile() throws IOException{
FileInputStream fis=new FileInputStream("E:\\Again4.mp3");
FileOutputStream fos=null;
byte[]b=new byte[1024*1024];
int len=0;
while((len=fis.read(b))!=-1){
fos=new FileOutputStream("E:\\SplitFiles\\"+(i++)+".part");
fos.write(b, 0, len);
fos.close();
}
fis.close();
}
public static void HebingFile() throws IOException{
Vector<FileInputStream> v=new Vector<FileInputStream>();
while(i>1){
v.add(new FileInputStream("E:\\SplitFiles\\"+(--i)+".part"));
}
Enumeration en=v.elements();
SequenceInputStream sis=new SequenceInputStream(en);
FileOutputStream fos=new FileOutputStream("E:\\Again5.mp3");
byte[] a=new byte[1024*1024];
int len;
while((len=sis.read(a))!=-1){
fos.write(a,0,len);
fos.flush();
}
fos.close();
sis.close();
}
}
对象的序列化:
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("文件"));
oos.writeObject(new Object());
实例化一个对象,并把此对象放入文件中,以便长期存储。
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("文件"));
Object obj=ois.readObject();
把对象从文件中读出来。
注意,对象序列化时候是把堆内存中的对象写入文件,类中如果有静态变量,因为是存在共享区,所以没有静态变量不能被序列化存储。每一个类都有一个序列号,这个序列号是通过其中的所有成员计算出来的。将一个类的对象序列化之后,对象同样也有序列号,用来和它的类对应。如果在读取对象的时候,这个类变了,那么读取对象就会失败,因为找不到对应的序列号来关联加载自己的类了。
管道流:
输入流和输出流成对儿绑定,二者分别写在两个线程中,以免死锁。因为二者绑定,所以一个写一个读都是同时操作的同一临界区。
public class PipeStreamDemo {
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();
}
}
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);
System.out.println("休息结束,开始输入");
out.write("pipe lai la".getBytes());//把内容写到管道流中默认的缓存区里面,输入流默认从这里读取数据
out.close();
} catch (Exception e) {
throw new RuntimeException("管道输出流失败");
}
}
}
RandomAccessFile类
该类不算是IO体系中的子类。而是直接继承Object。但是它是IO包中的成员。因为具备读写功能。内部封装了一个巨大数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获得指针位置,同时可以通过seek改变指针的位置。其实完成读写的原理就是内部封装了字节输入流和字节输出流。通过构造函数可以看出,该类只能操作文件。而且操作文件还有固定模式:r,rw,rws,rwd。
new此类新对象时,如果是读写rw模式,指定文件不存在,那么新建。如果指定文件已经存在,则不再新建,直接在原文件上读写。(不同于一般的流)
如果模式为只读r,不会创建文件,指定文件不存在,则异常。
通过这个类的特点可以实现多线程下载。
public class RandomAccessFileDemo {
public static void main(String[]args) throws IOException{
writeFile();
readFile();
}
public static void writeFile() throws IOException{
RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","rw");
raf.write("李四".getBytes());//写入两个汉字,是四个字节
raf.writeInt(258);//把输入内容补充到4个字节存储。
raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
public static void writeFile2() throws IOException{
RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","rw");
raf.seek(40);
raf.write("周七".getBytes());//通过seek方法,可以在数组中任意位置进行写
}
public static void readFile()throws IOException{
RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","r");
//调整对象中的指针
raf.seek(8);//指针指向缓存数组中角标为8的位置,之后read就从这里开始向后推进
//跳过指定的字节数
raf.skipBytes(8);//指针向后跳过8个字节。
byte[] buf=new byte[4];
raf.read(buf);//从缓存数组中读取buf长度的数据
String name=new String(buf);
int age=raf.readInt();//直接读取缓存中4个字节
System.out.print(name);
raf.close();
}
}
DataInputStream与DataOutputStream:可用于操作基本数据类型的数据流对象。
凡是操作基本数据类型就用这里两个流。
ublic class DataStreamDemo {
static OutputStreamWriter osw=null;
public static void main(String[]args) throws IOException{
//writeData();
//readData();
writeUTFDemo();//用UTF-8修改版写的数据只有相应的流readUTF才能读出来
osw=new OutputStreamWriter(new FileOutputStream("E:\\utf-8.txt"),"utf-8");
osw.write("你好");//标准utf-8写出的两个汉字是6字节
osw.close();
osw=osw=new OutputStreamWriter(new FileOutputStream("E:\\gbk.txt"),"gbk");
osw.write("你好");//gbk写出的两个汉字是4字节
osw.close();
}
public static void writeData() throws IOException{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("E:\\data.txt"));
dos.writeInt(234);//4个字节
dos.writeBoolean(true);//1个字节
dos.writeDouble(9887.543);//8个字节
dos.close();
}
public static void readData() throws IOException{
DataInputStream dis=new DataInputStream(new FileInputStream("E:\\data.txt"));
//读取时一定要按照顺序和类型读,因为存储的不同类型字节数不一样,读错了就乱码了
int num=dis.readInt();
boolean b=dis.readBoolean();
double d=dis.readDouble();
System.out.println(num);
System.out.println(b);
System.out.println(d);
dis.close();
}
//
public static void writeUTFDemo() throws IOException{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("E:\\utfdata.txt"));
dos.writeUTF("你好");//用UTF-8修改版编码来写入你好,这个修改版两个字占8个字节
dos.close();
}
}
ByteArrayInputStream和ByteArrayOutputStream
因为这两个流对象操作的都是数组,没有使用系统资源,所以关闭这个流无效。因为。这两个流都不调用底层资源。此类中的方法在关闭流后仍可被调用,而且不会产生任何IO异常。
ByteArrayInputStream在构造的时候,需要接受数据源,而且数据源是一个字节数组。
ByteArrayOutputStream的缓冲区会随着数据的不断写入而自动增长。 这个输出流的目的就是自带的被封装的这个缓冲数组。
流操作:
源设备:
键盘System.in,硬盘FileStream 内存ArrayStream
目的设备:
控制台System.out 硬盘FileStream内存ArrayStream
编码问题:
String Arrays.toString(Byte[]a)返回字节数组a的字符串表示形式,没有编码解码过程,仅仅是把数组内容以字符串形式输出。
编码:将字符串s中的字符都转换成字节的方法:s.getBytes();返回一个数组,数组中Byte元素对应字符串中每个字符
getBytes("码表");可以用指定码表编码,默认的是GBK。
解码:String s=new String(字节数组,"码表");返回s字符串是字节数组按照指定码表解码得到的字符串。码表默认是GBK码表。
服务器端一般用的是ISO8859-1码表,不支持中文。客户端发去的中文字符在服务器端无法正常解码。这个时候需要在服务器端对解码后的乱码重新用ISO8859-1编码,然后再用中文码表解码即可。这种重新编码再解码的方式只是用于中英文不兼容码表,如果是GBK和utf-8码表之间这样做就不行了。
联通问题:
现象:新建记事本里面输入联通两个字,保存退出,再打开,乱码。
解释:编码问题。utf-8的编码规则是,有时候一个字节读出一字符,有时候二字节,有时候三字节。怎样判断是该几个字节读取一字符?utf-8的字节都有标识位,字节第一位是0表示一个字节读一字符;第一字节前面是110,第二字节前面是10,表示这两个字节读一个字符;第一个字节前面是1110,第二个字节前面是10,第三个字节前面是10,表示这三个字节读一个字符。记事本在被输入联通两个字并保存时,也对联通进行了编码(默认GBK编码)。很偶然的情况是,GBK编码后得到的4个字节,恰好符合utf-8编码两字节读取一字符的标识位特点!然后解码的时候,记事本认出这些标志位,就错误的以为这是utf-8的编码并用utf-8进行解码,当然出来的是乱码。
解决方法:在联通前面加一个中文汉字,让记事本从第一个字节开始判断的时候不被骗就行。不能加英文,因为英文都一字节的,同样符合utf-8规则,依然会骗解码器。
键盘输入流+输出流+集合 示例
/*有五个学生,每个学生3门课成绩
* 键盘输入以上数据(姓名,三科成绩)
* 输入格式:如 zhangsan, 30, 40, 60 计算出总成绩
* 并把学生信息和总分数高低顺序存放在磁盘文件“stud.txt”中*/
public class StudentInfoTest {
static Reader r=null;
static Writer w=null;
static BufferedReader br=null;
static BufferedWriter bw=null;
static TreeSet<Studentw> ts=new TreeSet<Studentw>();
public static void main(String[]args) throws IOException{
shuru();
Iterator<Studentw> it=ts.iterator();
bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:\\stud.txt")));
while(it.hasNext()){
Studentw st=it.next();
String s=st.name+":语文"+st.yuwen+" 数学"+st.shuxue+" 英语"+st.yingyu+" 总分"+st.totle();
bw.write(s);
bw.newLine();
bw.flush();
}
bw.close();
}
public static void shuru() throws IOException{
for (int i=1;i<=5;i++){
System.out.print("请输入第"+i+"个学生的信息:");
br=new BufferedReader(new InputStreamReader(System.in));
String s=br.readLine();
String[] sp=s.split(", ");
ts.add(new Studentw(sp[0],Integer.parseInt(sp[1]),Integer.parseInt(sp[2]),Integer.parseInt(sp[3])));
}
br.close();
}
}
class Studentw implements Comparable<Studentw>{
String name;
int yuwen;
int shuxue;
int yingyu;
Studentw(String name,int yuwen,int shuxue,int yingyu){
this.name=name;
this.yuwen=yuwen;
this.shuxue=shuxue;
this.yingyu=yingyu;
}
public int totle(){
return yuwen+shuxue+yingyu;
}
public int hashcode(){
return name.hashCode()*77;
}
public boolean equeals(Object obj){
if(!(obj instanceof Studentw))
throw new ClassCastException("类型不匹配");
Studentw s=(Studentw)obj;
return this.name.equals(s.name) && this.totle()==s.totle();
}
public int compareTo(Studentw st1){
if(this.totle()==st1.totle()){
return this.name.compareTo(st1.name);
}else return this.totle()-st1.totle();
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------