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

------- 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培训 、期待与您交流! ---------


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值