IO流之字符流,File类

字节流

抽象基类:InputStream  OutputStream

1、  字节输入流

InputStream也是一个抽象类,从流中得到的为字节

常用方法:

abstract int read()throws IOException从流中得到一个字节,用int表示,如果为-1表示到文件末尾。

int read(byte[]b) throws IOException得到多个字节,放入数组b中,返回实际得到的字节数,-1表示到流的末尾。

void close() throws IOException关闭流。

从流中得到一个字节进行输入的大致步骤

1、  创建一个字节流对象,指明从哪里输入

2、  int b = 0;//存储从流中得到的一个字节的内容

while(true){

            b=in.read();//得到内容并判断流是否结束

            if(b==-1)break;

处理流中得到的字节

}

In.close();//关闭流

简化形式:

         While((b=in.read())!=-1)

{

处理得到的字节b
}

In.close();

从流中得到多个字节进行输入的大致步骤

1、创建一个字节流对象,指明从哪里输入

2、int len =0;//存储从流中得到的字节数

   byte[] b = new byte[1024];//存储从流中得到的一个字节的内容

while(true){

            len=in.read(b);//得到内容并判断流是否结束

            if(len==-1)break;

处理流中得到的字节

}

In.close();//关闭流

简化形式:

         While((len=in.read(b))!=-1){

                处理得到的字节b
        }

         in.close();

常用子类:FileinputStream BufferedInputStream]

FileInputStream有两个构造方法:

FileInputStream(String name)   FileInputStream(File file)

文件读取流实例:

package IOTest;

import java.io.*;

public class FileInputStreamDemo {

	public static void main(String[] args)throws IOException {
		// TODO Auto-generated method stub
		FileInputStreamDemo demo = new FileInputStreamDemo();
		demo.readFile("FileInputStreamDemo.java");
	}
	public void readFile(String fileName)throws IOException
	{
		InputStream in = null;
		try{
			in = new FileInputStream(fileName);//指明从哪里输入
			int len = 0;
			byte[] b = new byte[1024];
			while((len=in.read(b))!=-1)//得到内容并判断是否为空
			{
				System.out.println(new String(b,0,len));
			}
		}finally
		{
			if(in !=null)
				in.close();//关闭流
				
		}
	}
}

BufferedInputStream 是一个缓冲字节流,可以套接在其他流上进行功能的增强。

BufferedInputStream使用实例:

package IOTest;
import java.io.*;
public class BufferedInputStreamDemo {

	public static void main(String[] args) throws IOException{
		BufferedInputStreamDemo demo = new BufferedInputStreamDemo();
		demo.readFile("BufferedInputStreamDemo.java");
	}
	private void readFile(String fileName) throws IOException
	{
		InputStream in = null;
		try{
			in = new BufferedInputStream(new FileInputStream(fileName));//指明从哪里输入
			int len = 0;
			byte[] b = new byte[1024];
			while((len=in.read(b))!=-1)//得到内容并判断是否为空
			{
				System.out.println(new String(b,0,len));
			}
		}finally
		{
			if(in !=null)
				in.close();//关闭流
				
		}
	}

}

拷贝一个图片的简单实现:

BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("1.jpg"));
BufferedOutputStreambufos = new BufferedOutputStream(new FileOutptStream("2.jpg"));
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.close();

字节流的read()方法读取一个字节。为什么返回的不是byte类型,而是int类型呢?

因为read方法读到末尾时返回的是-1.

而在所操作的数据中的很容易出现连续多个1的情况,而连续读到81,就是-1.

导致读取会提前停止。

所以将读到的一个字节给提升为一个int类型的数值,但是只保留原字节,并在剩余二进制位补0.

具体操作是:byte&255 or byte&0xff

对于write方法,可以一次写入一个字节,但接收的是一个int类型数值。

只写入该int类型的数值的最低一个字节(8位)。

简单说:read方法对读到的数据进行提升。write对操作的数据进行转换。

转换流:

特点:

1,是字节流和字符流之间的桥梁。

2,该流对象中可以对读取到的字节数据进行指定编码表的编码转换。

什么时候使用呢?

1,当字节和字符之间有转换动作时。

2,流操作的数据需要进行编码表的指定时。

具体的对象体现:

1InputStreamReader:字节到字符的桥梁。

2OutputStreamWriter:字符到字节的桥梁。

构造函数:

InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

InputStreamReader(InputStream,StringcharSet):通过该构造函数初始化,可以指定编码表。

OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

OutputStreamWriter(OutputStream,StringcharSet):通过该构造函数初始化,可以指定编码表。

操作文件的字符流对象是转换流的子类。

Reader

|--InputStreamReader

|--FileReader

Writer

|--OutputStreamWriter

|--FileWriter

转换流中的read方法。已经融入了编码表,

在底层调用字节流的read方法时将获取的一个或者多个字节数据进行临时存储,

并去查指定的编码表,如果编码表没有指定,

查的是默认码表。那么转流的read方法就可以返回一个字符比如中文。

转换流已经完成了编码转换的动作,对于直接操作的文本文件的FileReaer而言,就不用在重新定义了,

只要继承该转换流,获取其方法,就可以直接操作文本文件中的字符数据了。

注意:

在使用FileReader操作文本数据时,该对象使用的是默认的编码表。

如果要使用指定编码表时,必须使用转换流。

FileReader fr = newFileReader("a.txt");//操作a.txt的中的数据使用的本系统默认的GBK。

操作a.txt中的数据使用的也是本系统默认的GBK。

InputStreamReader isr = new InputStreamReader(newFileInputStream("a.txt"));

这两句的代码的意义相同。

如果a.txt中的文件中的字符数据是通过utf-8的形式编码。

那么在读取时,就必须指定编码表。

那么转换流必须使用。

InputStreamReader isr = new InputStreamReader(newFileInputStream("a.txt"),"utf-8");

流操作的基本规律。

1,明确数据源和数据汇(数据目的)。

其实是为了明确输入流还是输出流。

2,明确操作的数据是否是纯文本数据。

其实是为了明确字符流还是字节流。

数据源:键盘System.in,硬盘File开头的流对象,内存(数组)

数据汇:控制台System.out,硬盘File开头的流对象,内存(数组)

需求:

1,将键盘录入的数据存储到一个文件中。

数据源:System.in

既然是源,使用的就是输入流,可用的体系有InputStreamReader

因为键盘录入进来的一定是纯文本数据,所以可以使用专门操作字符数据的Reader

发现System.in对应的流是字节读取流。所以要将其进行转换,将字节转成字符即可。

所以要使用Reader体系中:InputStreamReader

接下来,是否需要提高效率呢?如果需要,那么就加入字符流的缓冲区:BufferedReader

BufferedReaderbur = new BufferedReader(new InputStreamReader(System.in));

数据汇:一个文件,硬盘。

既然是数据汇,那么一定是输出流,可以用的OutputStream,Writer

往文件中存储的都是文本数据,那么可以使用字符流较为方便:Writer

因为操作的是一个文件。所以使用Writer中的FileWriter。

是否要提高效率呢?是,那就使用BufferedWriter.

BufferedWriter bufr= new BufferedWriter(new FileWriter("a.txt"));

附加需求:希望将这些文本数据按照指定的编码表存入文件中。

既然是文本数据,而是还是写入到文件中,那么使用的体系还是Writer

因为要指定编码表,所以要使用Writer中的转换流,OutputStreamWriter

是否要提高效率,是,选择BufferedWriter

注意:虽然是最终是文件,但是不可以选择FileWriter。因为该对象是使用默认编码表。

输出转换流要接收一个字节输出流进来,所以要是用OutputStram体系,而最终输出到一个文件中,

那么就要使用OutputStream体系中可以操作的文件的字节流对象:FileOutputStream

//StringcharSet = System.getProperty("file.encoding");

StringcharSet = "utf-8";

BufferedWriterbufw = new BufferedWriter(new OutputStreamWriter(newFileOutputStream("a.txt"),charSet);

 

代码:

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
}

2、将一个文件显示在控制台上:

public static void readText_2() throws IOException, FileNotFoundException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_1.txt"),"utf-8");
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
isr.close();
}

File类:

该类的出现是对文件系统的中的文件以及文件夹进行对象的封装。

可以通过对象的思想来操作文件以及文件夹。

1,构造函数:

File(String filename):将一个字符串路径(相对或者绝对)封装成File对象,该路径是可存在的,也可以是不存在。

File(String parent,String child);

File(Fileparent,String child);

2,特别的字段:separator:跨平台的目录分隔符。

例子:File file = newFile("c:"+File.separator+"abc"+File.separator+"a.txt");

3,常见方法:

1,创建:

boolean createNewFile()throws IOException:创建文件,如果被创建的文件已经存在,则不创建。

boolean mkdir():创建文件夹。

boolean mkdirs(): 创建多级文件夹。

2,删除:

boolean delete():可用于删除文件或者文件夹。

注意:对于文件夹只能删除不带内容的空文件夹,

对于带有内容的文件夹,不可以直接删除,必须要从里往外删除。

void deleteOnExit(): 删除动作交给系统完成。无论是否反生异常,系统在退出时执行删除动作。

3,判断:

boolean canExecute():

boolean canWrite():

boolean canRead();

boolean exists():判断文件或者文件夹是否存在。

boolean isFile(): 判断File对象中封装的是否是文件。

boolean isDirectory():判断File对象中封装的是否是文件夹。

boolean isHidden():判断文件或者文件夹是否隐藏。在获取硬盘文件或者文件夹时,

对于系统目录中的文件,java是无法访问的,所以在遍历,可以避免遍历隐藏文件。

4,获取:

getName():获取文件或者文件夹的名称。

getPath():File对象中封装的路径是什么,获取的就是什么。

getAbsolutePath():无论File对象中封装的路径是什么,获取的都是绝对路径。

getParent(): 获取File对象封装文件或者文件夹的父目录。

注意:如果封装的是相对路径,那么返回的是null.

long length():获取文件大小。

longlastModified():获取文件或者文件最后一次修改的时间。

static File[] listRoots():获取的是被系统中有效的盘符。

String[] list():获取指定目录下当前的文件以及文件夹名称。

String[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。

File[] listFiles():获取指定目录下的文件以及文件夹对象。

5,重命名:

renameTo(File):

File f1 = newFile("c:\\a.txt");

File f2 = newFile("c:\\b.txt");

f1.renameTo(f2);//将c盘下的a.txt文件改名为b.txt文件。

递归:

其实就是在使用一个功能过程中,又对该功能有需求。

就出现了函数自身调用自身。

注意:

1,一定要限定条件,否则内存溢出。

2,使用递归时,调用次数不要过多,否则也会出现内存溢出。

需求:

1、想要列出指定目录下的文件以及文件夹中的文件(子文件)

import java.io.*;
public class FileExtFilter implements  FilenameFilter{
	private String ext;
	FileExtFilter(String ext)
	{
		this.ext = ext;
	}
	
	public boolean accept(File dir, String name) {
		if(new File(dir,name).isDirectory())
			return false;
		if(name.endsWith(ext))
			return true;
		return false;
		
	}
}
public class FileFilter implements FilenameFilter{
	private String ext;
	FileFilter(String ext)
	{
		this.ext = ext;
	}

	@Override
	public boolean accept(File dir, String name) {
		// TODO Auto-generated method stub
		if(new File(dir,name).isDirectory())
			return false;
		if(name.endsWith(ext))
			return true;
		return false;
	}

}

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

原理:从里往外删除,所以需要使用递归完成。

public void deleteAll(File dir)
{
File[] files = dir.listFiles();
for(int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
deleteAll(files[x]);
else
files[x].delete();
}
dir.delete();
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值