黑马程序员_IO输入与输出(2)

------- android培训java培训、期待与您交流! ----------

File概述

用来将文件或文件夹封装成对象。

方便文件与文件夹的属性信息进行操作。

File对象可以作为参数传递给流的构造函数(流只能操作数据)。

File类的常见方法:

1、  创建。

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

public staticvoid method_1() throws IOException
{
       Filef=new File(“file.txt”);
       f.deleteOnExit();//文件退出时删除
       sop(“create:”+f.createNewFile());
       sop(“delete”+f.delete());//删除
//创建文件夹
       Filedir=new File(“abc”);
       sop(“mkdir”+dir.mkdir());//只能创建一级目录
}

boolean mkdir():创建文件夹

booleanmkdirs():创建多级文件夹

2、  删除

booleandelete();删除失败返回false

voiddeleteOnExit();在程序退出时删除指定文件

3、  判断

File f=new File(“file.txt”);

sop(“execute:”+f.canExecute());测试应用程序是否可以执行此抽象路径名表示的文件

Boolean exists:文件是否存在

f .exists();判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是存在的,通过exists判断

isFile();

isDirectory();

isHidden();判断是否隐藏

sop(f.isAbsolute());绝对路径是true

4、  获取信息

getName();获取名称

getPaht()获取路径

getParent();获取父目录,该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果

getAbsolutePath();获取绝对路径

longlastModified();最后一次修改的时间

long length();文件大小

File f1=newFile(“c:\\Test.java”);

File f2=newFile(“d:\\hahah.java”);

f1.renameTo(f2);重命名,且换目录相当于剪切

import java.io.*;
class FileDemo
{
       publicstatic void main(String[] args)
       {          
	}
	//创建File对象
	public staticvoid main(Stirng[] args)
	{
       		//将a.txt封装成file对象,可以将已有的和未出现的文件或者文件夹封装成对象
		File f1=new File(“c:\\abc\\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);
		sop(f2);
		sop(f3);//打印结果一样
		File f4=new File(“c:”+File.separator+”abc”+File.separato+”a.txt”);//separator是跨平台分割符
	}
	public staticvoid sop(Object obj)
	{
      		 System.out.println(obj);
	}
}

//列出机器中的有效盘符

public static void listRootsDemo()
{
       File[]files=File.listRoots();
       for(Filef:files)
       {
              System.out.println(f);
	}
}

//list方法

public static void listDemo()
{
       Filef=new File(“c:\\”);
       String[]names=f.list();//打印c盘下的所有文件和文件夹的名称,包含隐藏文件。调用list方法的file对象必须是封装了一个目录,而且该目录必须存在
       for(Stringname:names)
	{
       		System.out.println(name);
	}
}

//list(接口类型)传一个匿名内部类

public static void main(String[] args)
{
       Filedir=new File(“d:\\java1223\\day18”);
       String[]arr=dir.list(new FilenameFilter()
	{
       		public boolean accept(File dir,Stringname)
       		{
              		returnname.endsWith(“.bmp”);//过滤bmp文件
		}
	});
	System.out.println(“len”:+arr.length);
       for(Stringname:arr)
       {
              System.out.println(name);
	}
}

需求:列出指定目录下的文件或者文件夹,包含子目录中的内容,也就是列出指定目录下的所有内容。

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。

这种表现形式,或者编程手法,称为递归。

递归要注意:

1、  限定条件;

2、  注意递归的次数,尽量避免内存溢出。

import java.io.*;
class FileDemo3
{
       publicstatic void main(String[] args)
       {
              File dir=new File(“d:\\testdir”);
              showDir(dir,0);
	}
	public staticString 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 staticvoid showDir(File dir,int level)
	{
		System.out.println(getLevel()+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(files[x]);
		}
	}
}

需求:删除一个带内容的目录

删除原理:

在window中,删除目录是从里面往外删除的。需要用到递归。

import java.io.*;
classs RemoveDir
{
       publicstatic void main(Strring[] args)
       {
              File dir=new File(“d:\\testdir”);
              removeDir(dir);
	}
	public staticvoid removeDir(File dir)
	{
      		File[] files=dir.listFiles();
       		for(int x=0;x<files.length;x++)
       		{
              		if(files[x].isDirectory())
                     		removeDir(files[x]);
              		else
                     		System.out.println(files[x].toString()+”::”+files[x].delete());
		}
		System.out.println(dir+”::dir::”+dir.delete());
	}
}


Properties是hashtable的子类。

也就是它具备map集合的特点。而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。

该对象的特点:可以用于键值对形式的配置文件。

那么在加载数据时,需要数据有固定格式:键=值。

import java.io.*;
import java.util.*;
class PropertiesDemo
{
	public staticvoid main(String[] args)
	{
		setAndGet();
		loadDemo();
	}
	//演示,如何将流中的数据存储到集合中。
	//想要将info.txt中键值数据存到集合中进行操作
	public staticvoid loadDemo()
	{
		Properties prop=new Properties();
		FileInputStream fils=new FileInputStream(“info.txt”);
		//将流中的数据加载进集合
		prop.load(fis);
		prop.setProperty(“wangwu”,”39”);//改变内存的结果
		FileOutputStream fos=new FileOutputStream(“info.txt”);
		prop.store(fos,”haha”);//haha是注释信息
		//System.out.println(prop);
		prop.list(System.out);
		fos.close();
		fis.close();
	}
/*
1、用一个流和info.txt文件关联
2、读取一行数据,将改行数据用“=”进行切割
3、等号左边作为键,右边作为值。存入到Properties集合中即可
*/
	public staticvoid method_1()
	{
		BufferedReader bufr=new BufferedReader(new FileReader(“info.txt”));
		String line=null;
		Properties prop=new Properties();
		while((line=bufr.readLine())!=null)
		{
			String[] arr=line.split(“=”);
			System.out.println(arr[0]+”...”+arr[1]);
			prop.setProperty(arr[0],arr[1]);
		}
		bufr.close();
	}
	//设置和获取元素
	public staticvoid setAndGet()
	{
		Properties prop=new Properties();
		prop.setProperty(“zhangsan”,”30”);
		prot.setProperty(“lisi”,”39”);
		String value=prop.getProperty(“lisi”);
		System.out.println(value);
		//修改lisi的值
		prop.setProperty(“lisi”,89+” ”);
		//遍历集合中的所有数据
		Set<String> names=prop.stringPropertyNames();
		for(String s : names)
		{
			System.out.println(s+”:”+prop.getProperty(s));
		}
	}
}


打印流

该流提供了打印方法,可以将各种数据类型的数据和都原样打印

1)字节打印流:

printStream

构造函数可以接收的参数类型:

1、file对象。File

2、字符串路径。String

3、字节输出流。OutputStream

2)字符打印流:

PrintWriter

构造函数可以接收的参数类型:

1、file对象。File

2、字符串路径。String

3、字节输出流。OutputStream

4、字符输出流,Writer

import java.io.*;
calss PrintStreamDemo
{
	public staticvoid main(String[] args)
	{
		BufferedReader bufr=new BufferedReader(newInputStreamReader(System.in));
		PrintWriter out=new PrintWriter(new FileWriter(“a.txt”));//将文件封装到流里面不用自动刷新
		String line=null;
		while((line=bufr.readLine())!null)
		{
			if(“over”.equal(line))
				break;
			out.println(line.toUpperCase());
			//out.flush();
		}
		out.close();
		out.close();
	}
}

合并流

import java.io.*;
import java.util.*;
class SequenceDemo
{
	public staticvoid main(Strring[] args)
	{
		Vector<FileInputStream> v=new Vector<FileInputStream>();
		v.add(new FileInputStream(“c:\\1.txt”));
		v.add(new FileInputStream(“c:\\2.txt”));
		v.add(new FileInputStream(“c:\\3.txt”));
		Enumeration<FileInputStream> en=v.elements();
		SequenceInputStream sis=new SequenceInputStream(en);//将多个读取流合并成一个读取流
		FileOutputStream fos=new FileOutputStream(“c:\\4.txt”);
		type[] buf=new byte[1024];
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
}

切割文件

一个读取流三个输出流

import java.util.*;
class SplitFile
{
	public staticvoid main(String[] args) throw IOException
	{
		splitFile();
		merge();
	}
	//合并
	public staticvoid merge() throws IOException
	{
		ArrayList<FileInputStream> al=newArrayList<FileInputStream>();
		for(int x=0;x<=3;x++)
		{
			al.add(new FileInputStream(“c:\\splitfiles\\”+x+”.part”));
		}.
		final Interator<FileInputStream> it=al.iterator();
		Enumeration<FileInputStream> en=newEnumeration<FileInputStream>()
		{
			public boolean hasMoreElemnets()
			{
				return it.hasNext();
			}
			public FileInputStream nextElement()
			{
				return it.next();
			}
		};
		SequenceInputStream sis=new SequenceInputStream(en);//源有了
		FileOutStream fos=new FileOutputStream(“c:\\splitfiles\\0.bmp”);
		byte[] buf=new byte[1024];
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
	//切割
	public staticvoid splitFile() throw IOException
	{
		FillInputStream fis=new FileInputStream(“c:\\1.bmp”);
		FileOutputStream fos=null;
		byte[] buf=new byte[1024*1024];
		int len=0;
		while((len=fis.read(buf))!=-1)
		{
			fos=new FileOutputStream(“c:\\splitfiles\\”+(count++)+”.part”);
			fos.write(buf,0,len);
			fos.close();
		}
	fis.close();
	}
}

对象的序列化

ObjectOutputStream ObjectInputStream 成对出现

import java.io.*;
class ObjectStreamDemo
{
	public staticvoid main(String [] ages) throws Exception
	{
		//writeObj();//对象就不在堆内存中的,对象存到obj.txt文件里面了
		readObj();
	}
	public staticvoid readObj() throws Exception
	{
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(“obj.txt”));
		Person p=(Person)ois.readObject();
		System.out.println(p);
		ois.close();
	}
	public staticvoid writeObj() throws IOException
	{
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(“obj.txt”);//传字节流,将对像写入到文件里面去,传操纵文件的流比较合适,在定义目的。把数据写到文件里面去,数据不是纯文本数据,是字节的。能直接操纵对象的类是Object。。
		//一般文件名不存成txt。存成.object
		oos.writeObject(new Persong(“lisi”,39,”kr”));//这个对象存在硬盘上了
		oos.close();
	}
}

类通过实现java.io.Serializable接口以启用其序列化功能

import java.io.*;
//没有方法的接口就是标记接口
class Person implements Serializable
{
	public staticfinal long serialVersionUID=42l;//自定义UID。不定义就是根据成员自动生成
	String name;
	transient intage;//非静态的也不想被序列化就加transient
	static Stringcountry=”cn”;//静态不能被序列化。静态在方法区,只能将堆里面的序列化
	Persong(Stringname,int age,String country)
	{
		this.name=name;
		this.age=age;
		this.country=country;
	}
	public StringtoString()
	{
		return name+”:”+age+”:”+name;
	}
}

管道流

PipedInputStream 和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。

import java.io.*;
class Read implements Runnable
{
	privatePipedInputStream in;
	Read(PipedInputStream  in)
	{
		this.in=in;
	}
	public voidrun()
	{
		//覆盖了方法,只能try,不能抛出
		try
		{
			byte[] buf=new byte[1024];
			int len=in.read(buf);//读取前没有数据就阻塞,读到数据,阻塞结束
			String s=new String(buf,0,len);
			System.out.println(s);
			in.close();
		}
		catch(IOException e)
		{
			throw new RuntimeException(“管道读取流失败”);
		}
	}
}
class Write implements Runnable
{
	privatePipedOutputStream out;
	Write(PipedOutputStreamout)
	{
		this.out=out;
	}
	public voidrun()
	{
		try
		{
			out.write(“piped lai le”.getBytes());
			out.close();
		}
		catch(IOException e)
		{
			throw new RuntimeException(“管道输出流失败”);
		}
	}
}
class PipedStreamDemo
{
	public staticvoid main(String[] args) throws IOException
	{
		PipedInputStream in=new PipedInputStream();
		PipedOutputStream out=new PipedIOutputStream();
		in.connect(out);
		Read r=new Read();
		Write w=new Write();
		new Thread(r).start();
		new Thread(w).start();
	}
}

RandomAccessFile

随机访问文件,自身具备读写的方法。

通过skipBytes(int x),seek(int x)来达到随机访问

该类不算是IO体系中的子类。而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能。

内部封装了一个数组,而且通过指针对数组的元素进行操作。

可以通过getFilePointer获取指针位置。

同时可以通过seek改变指针的位置

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出该类只能操作文件。而且操作文件还有模式:只读r,读写rw等。

如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在则会报异常;如果模式为rw,该对象的构造函数要操作的文件不存在,会自动创建。如果存在则不会覆盖,直接在文件中写数据

import java.io.*;
class RandomAccessFileDemo
{
	public staticvoid main(String[] args) throws IOException
	{
		writeFile();
		writeFile_2();
	}
	public staticvoid readFile() throws IOException
	{
		RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”r”);//只读
		//raf.write(“haha”.getBytes());只读权限,屏蔽了写操作
		//调整对象的指针
		//raf.seek(8*1);//取王五的值
		//跳过指定的字节数
		raf.skipBytes(8);//但是跳过不能往回跳
		byte[] buf=new byte[4];
		raf.read(buf);
		String name=new String(buf);
		int age=raf.readInt();//一次读一个32位整数,四个字节,读完自动转换
		System.out.println(“name”+name+”age”+age);
		raf.close();
	}
	public staticvoid writeFile_2()  throws IOException//随机可以往里读写,还能对数据进行修改
	{
		RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”rw”);
		raf.seek(8*3);
		raf.write(“周期”.getBytes());
		raf.writeInt(93);
		raf.close();
	}
	public staticvoid writeFile()  throws IOException
	{
		RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”rw”);
		raf.write(“李四”.getBytes());
		//raf.write(97);//取最低八位,容易丢数据
		raf.writeInt(97);// 取四个字节
		raf.write(“王五”.getBytes());
		raf.writeInt(93);// 取四个字节
		raf.close();
	}
}

DateInputStream与DataOutputStream

可以用于操作基本数据类型的数据的流对象

import java.io.*;
class DataStreamDemo
{
	public staticvoid main(String[] args) throws IOException
	{
		//writeData();
		//readDate();
		writeUTFDemo();//gbk 4字节,下面utf 6字节,这个utf8字节
		OutputStreamWriter osw=new OutputStreamWriter(new FileOutStream(“utf.txt”,”utf-8”));
		osw.write(“你好”);
		osw,close();
		readUTFDemo();
	}
	public staticvoid readUTFDemo() throws IOException
	{
		DataInputStream dis=new DataInputStream(new FileInputStream(“utfdate.txt”));
		String s=dis.readUTF();
		System.out.println(s);//读出你好
		dis.close();
	}
	public staticvoid writeUTFDemo()  throws IOException
	{
		DataOutputStream dos=new DataOutputStream(new  FileOutputStream(“utfdate.txt”));
		dos.writeUTF(“你好”);//用这个写的只能用readUTF()读
		dos.close();
	}
	public staticvoid readData() throws IOException
	{
		DataInputStream dis=new DataInputStream(new FileInputStream(“data.txt”));
		int num=dis.readInt();
		boolean b=dis.readBoolean();
		double d=dis.readDouble();
		System.out.println(“num=”+num);
		System.out.println(“b=”+b);
		System.out.println(“d=”+d);
		dis.close();
	}
	public staticvoid writeData() throws IOException
	{
		DataOutputStream dos=new DataOutputStream(new  FileOutputStream(“data.txt”));
		dos.writeInt(234);
		dos.writeBoolean(true);
		dos.writeDouble(9887.543);
		dos.close();
	}
}

操作字节数组

ByteArrayInputStream(负责源)与ByteArrayOutputStream

ByteArrayInputStream:在构造的时候需要接收数据源,而且在数据源是一个字节数组。

ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字符数组,这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源,所以不用close关闭。

源设备:键盘System.in,硬盘FileStream,内存ArrayStream

目的设备:控制台System.out,硬盘FileStream,内存ArrayStream

用流的读写思想来操作数组

import java.io.*;
class ByteArrayStream
{
	public staticvoid main(String[] args)
	{
		//数据源
		ByteArrayInputStream bis =new ByteArrayInputStream(“ABCDED”.getBytes());
		//数据目的
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		System.out.println(bos.size());//0
		int by=0;
		while((by=bis.read())!=-1)
		{
			bos.write(by);
		}
		System.out.println(bos.size());//7
		System.out.println(bos.toString());//ABCDED
	}
}

操作字符数组

CharArrayReader与CharArrayWrite

操作字符串

StringReader与StringWriter

字符编码

字符流的出现为了方便操作字符。

更重要的是加入了编码转换。

通过子类转换流来完成:

InputStreamReader OutputStreamWriter

在两个对象进行构造的时候可以加入字符集。

编码表的由来:

计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。

ASCII:美国标准信息交换码。用一个字节的7位可以表示

ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示

GB2312:中国的中文编码表。从中国开始用两个字节了

GBK:中国的中文编码表升级,融合了更多的中文文字符号。

Unicode:国际标准码,融合了多种文字。所有文字都用两个字节表示,java语言用的就是unicode

UTF-8:最多用三个字节来表示一个字符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值