精华内容
下载资源
问答
  • 字节流 InputStream(读)和OutputStream...任务1:用字节流将数据写入目标文本 import java.io.*; public class FileStream { public static void main(String[] args)throws IOException { writeFile(...

    字节流

    InputStream(读)和OutputStream(写)

    其实字节流和字符流很相似,我们掌握其中的规律即可掌握。


    任务1:用字节流将数据写入目标文本

    import java.io.*;
    public class FileStream
    {
    	public static void main(String[] args)throws IOException 
    	{
    		writeFile();
    	}
    
    	public static void writeFile()throws IOException
    	{
    		FileOutputStream fos=new FileOutputStream("fos.txt");
    		fos.write("abcde".getBytes());//字节流不支持直接写入字符串,所以将字符串变为字符数组
    		fos.close();//关闭资源
    	}
    }
    

    结果

    在这里插入图片描述


    任务2:将目标文件中的数据读出

    import java.io.*;
    public class FileStream
    {
    	public static void main(String[] args)throws IOException 
    	{
    		readFile1();
    	}
    
    	public static void readFile1()throws IOException
    	{
    		FileInputStream fis=new FileInputStream("fos.txt");
    		int ch=0;
    		while((ch=fis.read())!=-1)//一个一个读
    		{
    			System.out.println((char)ch);//ln 换行
    		}
    		fis.close();
    	}
    }
    

    结果

    在这里插入图片描述


    任务3:将上述读写数据的方法进行改进

    import java.io.*;
    public class FileStream
    {
    	public static void main(String[] args)throws IOException 
    	{
    		readFile2();
    	}
    
    	public static void readFile2()throws IOException
    	{
    		FileInputStream fis=new FileInputStream("fos.txt");
    		byte[] buf=new byte[1024];//创建一个数组
    		int len=0;
    		while((len=fis.read(buf))!=-1)//如果不是-1就一直往里面进行装
    		{
    			System.out.println(new String(buf,0,len));
    		}
    		fis.close();
    	}
    }
    

    结果

    在这里插入图片描述


    available() 的介绍和应用

    import java.io.*;
    public class FileStream
    {
    	public static void main(String[] args)throws IOException 
    	{
    		readFile3();
    	}
    
    	public static void readFile3()throws IOException
    	{
    		FileInputStream fis=new FileInputStream("fos.txt");
    		int num=fis.available();
    		System.out.println(num);
    	}
    }
    
    

    结果

    在这里插入图片描述

    我们发现了,available () 这个关键字的用法是可以获取文本中内容的字节数。

    那我们在变一下 我们在文本中 (原本为abcde )我们现在增加一个回车符号,并且加入g后,看看是多少个字节数。

    结果

    在这里插入图片描述

    我们发现了,个数为8,这就说明回车符号占了两个字节。这里就是\n\r


    利用字节流进行图片的复制

    这里我们讲到了字节流,就不得不学习和了解一下它有别于字符流的区别,就是在图片上可以进行操作和读取。

    代码

     /*
     任务:
         进行图片的拷贝
    	 思路:
    	 1.用字节读取流对象和图片关联
    	 2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据
    	 3。通过循环读写,完成数据的储存
    	 4.关闭资源
     */
     
     import java.io.*;
     public class CopyPicture 
    {
    	public static void main(String[] args)
    	{
    		FileOutputStream fos=null;
    		FileInputStream fis=null;
    		try//自定义 try-catch 也可以直接抛出
    		{
    			fos=new FileOutputStream("F:\\CloudMusic\\Copy_picture.jpg");//这个是写,是创建一个文件
    			fis=new FileInputStream("F:\\WeChat\\chakayanhu.jpg");//注意,这个是读,就是源文件
    
    			byte[] buf=new byte[1024];
    			int len=0;
    			while((len=fis.read(buf))!=-1)
    			{
    				fos.write(buf,0,len);
    			}
    		}
    		catch (IOException e)
    		{
    			throw new RuntimeException("复制文件失败");
    		
    		}
    		finally
    		{
    			try
    			{
    				if(fis!=null)
    					fis.close();
    			}
    			catch (IOException e)
    			{
    				throw new RuntimeException("读取文件失败");
    			}
    		}
    	}
    }
    
    

    原图是:在这里插入图片描述

    在这里插入图片描述

    结果

    在这里插入图片描述

    在这里插入图片描述

    搞定

    展开全文
  • 利用字节流字符流操作数据读写

    千次阅读 2017-08-23 16:41:59
    字节流操作数据读写   import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;   /**  * 利用流来拷贝文件  * @author ...

    字节流操作数据读写

     

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

     

    /**

     *利用流来拷贝文件

     * @author ALWZ

     *

     */

    public class CopyByteStream {

     public static void main(String[] args) {

    try {

    FileInputStream fiStream=new FileInputStream("ani.gif");//将一个动态图片读入字节流

    FileOutputStream fos =new FileOutputStream("ani_new.gif");//定一个输出流,输出新的拷贝图片

     

    byte input[] =new byte[50];

    while (fiStream.read(input)!=-1) {//如果读取的数据不是最后一个就将读的数据放入到input

    fos.write(input);//放入数据

     

    }

     

    fiStream.close();

    fos.close();

     

    System.out.println("CopyByteStream.main()");

    //运行之后刷新,就会看到一个新的ani_new.gif文件

     

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

     

    }

    }

     

     

    import java.io.BufferedInputStream;

    import java.io.BufferedOutputStream;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

     

    /**

     *利用缓冲区实现数据的复制

     * @author ALWZ

     *

     */

    public class CopyReadBufferedByteStream {

    public static void main(String[] args) {

    try {

    FileInputStream fis =new FileInputStream("movie.mp4");                

    BufferedInputStream bis =new BufferedInputStream(fis);//将读出来的字节流放入到缓冲区中,还可以设置缓冲区的大小//如果一个缓冲区设置的大小合理的话,会降低复制的时间

    //实现文件的复制,定义一个输出流

    FileOutputStream fos =new FileOutputStream("movie_new.mp4");

    BufferedOutputStream bos =new BufferedOutputStream(fos);

     

     

    byte input[]=new byte[100];//每次读取100个字节//如果一个数组设置的合理的话,会减少对磁盘io的操作

    int count=0;

    //计算使用了多少ms读取这个文件

    long before=System.currentTimeMillis();

     

    while (bis.read(input)!=-1) {

    bos.write(input);

    count++;

    }

    bis.close();

    fis.close();//先打开的后关闭

    bos.close();

    fos.close();

     

    System.out.println(System.currentTimeMillis()-before+"ms");//计算使用了多少毫秒

     

    System.out.println("读取了"+count+"");

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

     

    }

    }

    字符流操作数据读写

     

    读取的操作:

     

    package RWCharStream;

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.UnsupportedEncodingException;

     

    /**

     *用字符流读取数据

     * @author ALWZ

     *

     */

    public class RWByCharStream {

    public static void main(String[] args) {

    try {

    File file=new File("java.txt");

    FileInputStream fis=new FileInputStream(file);

    InputStreamReader isr=new InputStreamReader(fis,"UTF-8");//把文件读取成字符流

    char input[]=new char[100];

    while(isr.read(input)!=-1){//将字符流读取到字符数组中

    System.out.println(input);

    };

     

    isr.close();

    fis.close();

     

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

     

     

    }

    }

     

     


     

     

     

    还有另一种写法:因为有可能出现如下情况,到了输出文本的末尾没有结束,而是从头又输出了几个字符。


     

    解决方法如下

    package RWCharStream;

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.UnsupportedEncodingException;

     

    /**

     * 用字符流读取数据

     * @author ALWZ

     *

     */

    public class RWByCharStream {

    public static void main(String[] args) {

    try {

    File file=new File("java.txt");

    FileInputStream fis=new FileInputStream(file);

    InputStreamReader isr=new InputStreamReader(fis,"UTF-8");//把文件读取成字符流

    char input[]=new char[100];

    /*while(isr.read(input)!=-1){//将字符流读取到字符数组中

    System.out.println(new String(input));

    };*/

    //这样有可能会输出多余的数据,因为可能最后截取的字符,不够100,它又会重新开始读取几个字符来满足100的填充。

     

    //于是可以用下面的写法

    int length=0;

    while((length=isr.read(input))!=-1){//将字符流读取到字符数组中

    System.out.println(new String(input,0,length));//给输出的字符串设置偏移量为0,从头开始读,长度为读取字符串的最大长度。

    };

     

    isr.close();

    fis.close();

     

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

     

     

    }

    }

     

    这样运行结果和第一个是一样的,只不过可能最后如果读取的字符串不够100个字符,它也不会自动给你补充到100个了。

     


     

     

     

    写入,拷贝的操作

    package RWCharStream;

     

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.OutputStreamWriter;

    import java.io.UnsupportedEncodingException;

     

    /**

     * 用字符流拷贝

     * @author ALWZ

     *

     */

    public class WCharStream {

    public static void main(String[] args) {

    try {

    FileInputStream fis =new FileInputStream("java.txt");

    FileOutputStream fos=new FileOutputStream("java_new.txt");

    InputStreamReader isr=new InputStreamReader(fis,"UTF-8");//把文件读取成字符流

    OutputStreamWriter osr =new OutputStreamWriter(fos,"UTF-8");

     

    char input[]=new char[100];

     

    int length=0;

    while((length=isr.read(input))!=-1){//将字符流读取到字符数组中

    //String inputString=new String(input,0,length);//将字符输出

    osr.write(input,0,length);//将字符输出

    };

     

    isr.close();

    fis.close();

    osr.close();

    fos.close();

    System.out.println("WCharStream.main() done");

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

     

     

     


     

    带有缓冲的字符流的读写操作:

     

    package RWCharStream;

     

    import java.io.BufferedReader;

    import java.io.BufferedWriter;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.OutputStreamWriter;

    import java.io.PrintWriter;

    import java.io.UnsupportedEncodingException;

    /**

     *带有缓冲的字符流的读操作

     * @author ALWZ

     *

     */

    public class RByBufferCharStream {

     

    public static void main(String[] args) {

    try {

    FileInputStream fis =new FileInputStream("java.txt");

    FileOutputStream fos=new FileOutputStream("java_new_buffer.txt");

    InputStreamReader isr=new InputStreamReader(fis,"UTF-8");//把文件读取成字符流

    OutputStreamWriter osr =new OutputStreamWriter(fos,"UTF-8");

     

    //定义读写的缓冲流

    BufferedReader br =new BufferedReader(isr);

    //BufferedWriter bw =new BufferedWriter(osr);//使用这个api会导致生成的文件中的换行符都被替换掉,从而没有了格式

    PrintWriter pw =new PrintWriter(osr);//使用print可以输出流而不会被替换换行符

     

     

    String input;

    while ((input=br.readLine())!=null) {//读取一行数据

    //bw.write(input);//使用这个api会导致生成的文件中的换行符都被替换掉,从而没有了格式

    pw.println(input);//使用print可以输出流而不会被替换换行符。

     

    };

    pw.flush();//将缓冲区的内容强制输出,保证输出的文件是完整的。也可以用bw.flush

    //另外还可以在定义printWriter的时候定一个参数new PrintWriter(osr,true),这样当文件输出的时候就会自动强制输出缓存区的内容

     

     

    //bw.close();//使用这个api会导致生成的文件中的换行符都被替换掉,从而没有了格式

    pw.close();//使用print可以输出流而不会被替换换行符。

    br.close();

    isr.close();

    fis.close();

    osr.close();

    fos.close();

     

    System.out.println("WCharStream.main() done");

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

     

     

     

     





    展开全文
  • 【Java基础-3】吃透Java IO:字节流、字符流、缓冲流

    万次阅读 多人点赞 2020-09-23 20:12:33
    什么是Java-IO?字符流和字节流的区别与适用场景是什么?缓冲流到底实现了什么?如何高效地读写文件? 本文用大量的示例图和实例,带你吃透Java IO。

    前言

    有人曾问fastjson的作者(阿里技术专家高铁):“你开发fastjson,没得到什么好处,反而挨了骂背了锅,这种事情你为什么要做呢?”

    高铁答道:“因为热爱本身,就是奖励啊!”

    这个回答顿时触动了我。想想自己,又何尝不是如此。写作是个痛苦的过程,用心写作就更加煎熬,需字字斟酌,反复删改才有所成。然而,当一篇篇精良文章出自己手而呈现眼前时,那些痛苦煎熬就都那么值得。如果这些博文能有幸得大家阅读和认可,就更加是莫大的鼓舞了。技术人的快乐就是可以这么纯粹和简单。

    点波关注不迷路,一键三连好运连连!

    IO流是Java中的一个重要构成部分,也是我们经常打交道的。这篇关于Java IO的博文干货满满,堪称全网前三(请轻喷!)

    下面几个问题(问题还会继续补充),如果你能对答如流,那么恭喜你,IO知识掌握得很好,可以立即关闭文章。反之,你可以在后面得文章中寻找答案。

    1. Java IO流有什么特点?
    2. Java IO流分为几种类型?
    3. 字节流和字符流的关系与区别?
    4. 字符流是否使用了缓冲?
    5. 缓冲流的效率一定高吗?为什么?
    6. 缓冲流体现了Java中的哪种设计模式思想?
    7. 为什么要实现序列化?如何实现序列化?
    8. 序列化数据后,再次修改类文件,读取数据会出问题,如何解决呢?

    1 初识Java IO

    IO,即inout,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。

    Java 中是通过流处理IO 的,那么什么是流

    流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。

    当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

    一般来说关于流的特性有下面几点:

    1. 先进先出:最先写入输出流的数据最先被输入流读取到。
    2. 顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
    3. 只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

    1.1 IO流分类

    IO流主要的分类方式有以下3种:

    1. 按数据流的方向:输入流、输出流
    2. 按处理数据单位:字节流、字符流
    3. 按功能:节点流、处理流

    在这里插入图片描述

    1、输入流与输出流

    输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,这点很容易搞反。

    在这里插入图片描述
    2、字节流与字符流

    字节流和字符流的用法几乎完成全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。

    为什么要有字符流?

    Java中字符是采用Unicode标准,Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
    在这里插入图片描述
    而在UTF-8编码中,一个中文字符是3个字节。例如下面图中,“云深不知处”5个中文对应的是15个字节:-28-70-111-26-73-79-28-72-115-25-97-91-27-92-124
    在这里插入图片描述

    那么问题来了,如果使用字节流处理中文,如果一次读写一个字符对应的字节数就不会有问题,一旦将一个字符对应的字节分裂开来,就会出现乱码了。为了更方便地处理中文这些字符,Java就推出了字符流。

    字节流和字符流的其他区别:

    1. 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
    2. 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。详见文末效率对比。

    以写文件为例,我们查看字符流的源码,发现确实有利用到缓冲区:
    在这里插入图片描述
    在这里插入图片描述

    3、节点流和处理流

    节点流:直接操作数据读写的流类,比如FileInputStream

    处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能,例如BufferedInputStream(缓冲字节流)

    处理流和节点流应用了Java的装饰者设计模式。

    下图就很形象地描绘了节点流和处理流,处理流是对节点流的封装,最终的数据处理还是由节点流完成的。
    在这里插入图片描述
    在诸多处理流中,有一个非常重要,那就是缓冲流

    我们知道,程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。
    在这里插入图片描述

    联想一下生活中的例子,我们搬砖的时候,一块一块地往车上装肯定是很低效的。我们可以使用一个小推车,先把砖装到小推车上,再把这小推车推到车前,把砖装到车上。这个例子中,小推车可以视为缓冲区,小推车的存在,减少了我们装车次数,从而提高了效率。
    在这里插入图片描述
    需要注意的是,缓冲流效率一定高吗?不一定,某些情形下,缓冲流效率反而更低,具体请见IO流效率对比。

    完整的IO分类图如下:
    在这里插入图片描述

    1.2 案例实操

    接下来,我们看看如何使用Java IO。

    文本读写的例子,也就是文章开头所说的,将“松下问童子,言师采药去。只在此山中,云深不知处。”写入本地文本,然后再从文件读取内容并输出到控制台。

    1、FileInputStream、FileOutputStream(字节流)

    字节流的方式效率较低,不建议使用

    public class IOTest {
    	public static void main(String[] args) throws IOException {
    		File file = new File("D:/test.txt");
    
    		write(file);
    		System.out.println(read(file));
    	}
    
    	public static void write(File file) throws IOException {
    		OutputStream os = new FileOutputStream(file, true);
    
    		// 要写入的字符串
    		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    		// 写入文件
    		os.write(string.getBytes());
    		// 关闭流
    		os.close();
    	}
    
    	public static String read(File file) throws IOException {
    		InputStream in = new FileInputStream(file);
    
    		// 一次性取多少个字节
    		byte[] bytes = new byte[1024];
    		// 用来接收读取的字节数组
    		StringBuilder sb = new StringBuilder();
    		// 读取到的字节数组长度,为-1时表示没有数据
    		int length = 0;
    		// 循环取数据
    		while ((length = in.read(bytes)) != -1) {
    			// 将读取的内容转换成字符串
    			sb.append(new String(bytes, 0, length));
    		}
    		// 关闭流
    		in.close();
    
    		return sb.toString();
    	}
    }
    

    2、BufferedInputStream、BufferedOutputStream(缓冲字节流)

    缓冲字节流是为高效率而设计的,真正的读写操作还是靠FileOutputStreamFileInputStream,所以其构造方法入参是这两个类的对象也就不奇怪了。

    public class IOTest {
    
    	public static void write(File file) throws IOException {
    		// 缓冲字节流,提高了效率
    		BufferedOutputStream bis = new BufferedOutputStream(new FileOutputStream(file, true));
    
    		// 要写入的字符串
    		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    		// 写入文件
    		bis.write(string.getBytes());
    		// 关闭流
    		bis.close();
    	}
    
    	public static String read(File file) throws IOException {
    		BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
    
    		// 一次性取多少个字节
    		byte[] bytes = new byte[1024];
    		// 用来接收读取的字节数组
    		StringBuilder sb = new StringBuilder();
    		// 读取到的字节数组长度,为-1时表示没有数据
    		int length = 0;
    		// 循环取数据
    		while ((length = fis.read(bytes)) != -1) {
    			// 将读取的内容转换成字符串
    			sb.append(new String(bytes, 0, length));
    		}
    		// 关闭流
    		fis.close();
    
    		return sb.toString();
    	}
    }
    

    3、InputStreamReader、OutputStreamWriter(字符流)

    字符流适用于文本文件的读写OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象

    public class IOTest {
    	
    	public static void write(File file) throws IOException {
    		// OutputStreamWriter可以显示指定字符集,否则使用默认字符集
    		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");
    
    		// 要写入的字符串
    		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    		osw.write(string);
    		osw.close();
    	}
    
    	public static String read(File file) throws IOException {
    		InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
    		// 字符数组:一次读取多少个字符
    		char[] chars = new char[1024];
    		// 每次读取的字符数组先append到StringBuilder中
    		StringBuilder sb = new StringBuilder();
    		// 读取到的字符数组长度,为-1时表示没有数据
    		int length;
    		// 循环取数据
    		while ((length = isr.read(chars)) != -1) {
    			// 将读取的内容转换成字符串
    			sb.append(chars, 0, length);
    		}
    		// 关闭流
    		isr.close();
    
    		return sb.toString()
    	}
    }
    

    4、字符流便捷类

    Java提供了FileWriterFileReader简化字符流的读写,new FileWriter等同于new OutputStreamWriter(new FileOutputStream(file, true))

    public class IOTest {
    	
    	public static void write(File file) throws IOException {
    		FileWriter fw = new FileWriter(file, true);
    
    		// 要写入的字符串
    		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    		fw.write(string);
    		fw.close();
    	}
    
    	public static String read(File file) throws IOException {
    		FileReader fr = new FileReader(file);
    		// 一次性取多少个字节
    		char[] chars = new char[1024];
    		// 用来接收读取的字节数组
    		StringBuilder sb = new StringBuilder();
    		// 读取到的字节数组长度,为-1时表示没有数据
    		int length;
    		// 循环取数据
    		while ((length = fr.read(chars)) != -1) {
    			// 将读取的内容转换成字符串
    			sb.append(chars, 0, length);
    		}
    		// 关闭流
    		fr.close();
    
    		return sb.toString();
    	}
    }
    

    5、BufferedReader、BufferedWriter(字符缓冲流)

    public class IOTest {
    	
    	public static void write(File file) throws IOException {
    		// BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new
    		// FileOutputStream(file, true), "UTF-8"));
    		// FileWriter可以大幅度简化代码
    		BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));
    
    		// 要写入的字符串
    		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
    		bw.write(string);
    		bw.close();
    	}
    
    	public static String read(File file) throws IOException {
    		BufferedReader br = new BufferedReader(new FileReader(file));
    		// 用来接收读取的字节数组
    		StringBuilder sb = new StringBuilder();
    
    		// 按行读数据
    		String line;
    		// 循环取数据
    		while ((line = br.readLine()) != null) {
    			// 将读取的内容转换成字符串
    			sb.append(line);
    		}
    		// 关闭流
    		br.close();
    
    		return sb.toString();
    	}
    }
    

    2 IO流对象

    第一节中,我们大致了解了IO,并完成了几个案例,但对IO还缺乏更详细的认知,那么接下来我们就对Java IO细细分解,梳理出完整的知识体系来。

    Java种提供了40多个类,我们只需要详细了解一下其中比较重要的就可以满足日常应用了。

    2.1 File类

    File类是用来操作文件的类,但它不能操作文件中的数据。

    public class File extends Object implements Serializable, Comparable<File>
    

    File类实现了SerializableComparable<File>,说明它是支持序列化和排序的。

    File类的构造方法

    方法名说明
    File(File parent, String child)根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
    File(String pathname)通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
    File(String parent, String child)根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
    File(URI uri)通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。

    File类的常用方法

    方法说明
    createNewFile()当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
    delete()删除此抽象路径名表示的文件或目录。
    exists()测试此抽象路径名表示的文件或目录是否存在。
    getAbsoluteFile()返回此抽象路径名的绝对路径名形式。
    getAbsolutePath()返回此抽象路径名的绝对路径名字符串。
    length()返回由此抽象路径名表示的文件的长度。
    mkdir()创建此抽象路径名指定的目录。

    File类使用实例

    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file = new File("C:/Mu/fileTest.txt");
    
    		// 判断文件是否存在
    		if (!file.exists()) {
    			// 不存在则创建
    			file.createNewFile();
    		}
    		System.out.println("文件的绝对路径:" + file.getAbsolutePath());
    		System.out.println("文件的大小:" + file.length());
    
    		// 刪除文件
    		file.delete();
    	}
    }
    

    2.2 字节流

    InputStreamOutputStream是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。

    InputStream为例,它继承了Object,实现了Closeable

    public abstract class InputStream
    extends Object
    implements Closeable
    

    InputStream类有很多的实现子类,下面列举了一些比较常用的:
    在这里插入图片描述
    详细说明一下上图中的类:

    1. InputStreamInputStream是所有字节输入流的抽象基类,前面说过抽象类不能被实例化,实际上是作为模板而存在的,为所有实现类定义了处理输入流的方法。
    2. FileInputSream:文件输入流,一个非常重要的字节输入流,用于对文件进行读取操作。
    3. PipedInputStream:管道字节输入流,能实现多线程间的管道通信。
    4. ByteArrayInputStream:字节数组输入流,从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去。
    5. FilterInputStream:装饰者类,具体的装饰者继承该类,这些类都是处理类,作用是对节点类进行封装,实现一些特殊功能。
    6. DataInputStream:数据输入流,它是用来装饰其它输入流,作用是“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。
    7. BufferedInputStream:缓冲流,对节点流进行装饰,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送,效率更高。
    8. ObjectInputStream:对象输入流,用来提供对基本数据或对象的持久存储。通俗点说,也就是能直接传输对象,通常应用在反序列化中。它也是一种处理流,构造器的入参是一个InputStream的实例对象。

    OutputStream类继承关系图:
    在这里插入图片描述

    OutputStream类继承关系与InputStream类似,需要注意的是PrintStream.

    2.3 字符流

    与字节流类似,字符流也有两个抽象基类,分别是ReaderWriter。其他的字符流实现类都是继承了这两个类。

    Reader为例,它的主要实现子类如下图:
    在这里插入图片描述
    各个类的详细说明:

    1. InputStreamReader:从字节流到字符流的桥梁(InputStreamReader构造器入参是FileInputStream的实例对象),它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式给定,或者可以接受平台的默认字符集。
    2. BufferedReader:从字符输入流中读取文本,设置一个缓冲区来提高效率。BufferedReader是对InputStreamReader的封装,前者构造器的入参就是后者的一个实例对象。
    3. FileReader:用于读取字符文件的便利类,new FileReader(File file)等同于new InputStreamReader(new FileInputStream(file, true),"UTF-8"),但FileReader不能指定字符编码和默认字节缓冲区大小。
    4. PipedReader :管道字符输入流。实现多线程间的管道通信。
    5. CharArrayReader:从Char数组中读取数据的介质流。
    6. StringReader :从String中读取数据的介质流。

    WriterReader结构类似,方向相反,不再赘述。唯一有区别的是,Writer的子类PrintWriter

    2.4 序列化

    待续…

    3 IO流方法

    3.1 字节流方法

    字节输入流InputStream主要方法:

    • read() :从此输入流中读取一个数据字节。
    • read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
    • read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
    • close():关闭此输入流并释放与该流关联的所有系统资源。

    字节输出流OutputStream主要方法:

    • write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
    • write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
    • write(int b) :将指定字节写入此文件输出流。
    • close() :关闭此输入流并释放与该流关联的所有系统资源。

    3.2 字符流方法

    字符输入流Reader主要方法:

    • read():读取单个字符。
    • read(char[] cbuf) :将字符读入数组。
    • read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
    • read(CharBuffer target) :试图将字符读入指定的字符缓冲区。
    • flush() :刷新该流的缓冲。
    • close() :关闭此流,但要先刷新它。

    字符输出流Writer主要方法:

    • write(char[] cbuf) :写入字符数组。
    • write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
    • write(int c) :写入单个字符。
    • write(String str) :写入字符串。
    • write(String str, int off, int len) :写入字符串的某一部分。
    • flush() :刷新该流的缓冲。
    • close() :关闭此流,但要先刷新它。

    另外,字符缓冲流还有两个独特的方法:

    • BufferedWriternewLine()写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
    • BufferedReaderreadLine() :读取一个文本行。

    4 附加内容

    4.1 位、字节、字符

    字节(Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。

    字符(Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、’$’、’&'等。

    一般在英文状态下一个字母或字符占用一个字节,一个汉字用两个字节表示。

    字节与字符:

    • ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。
    • UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。
    • Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
    • 符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 . 占1个字节的大小,中文句号 。占2个字节的大小。
    • UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
    • UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。

    4.2 IO流效率对比

    首先,对比下普通字节流和缓冲字节流的效率:

    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		File file = new File("C:/Mu/test.txt");
    		StringBuilder sb = new StringBuilder();
    
    		for (int i = 0; i < 3000000; i++) {
    			sb.append("abcdefghigklmnopqrstuvwsyz");
    		}
    		byte[] bytes = sb.toString().getBytes();
    
    		long start = System.currentTimeMillis();
    		write(file, bytes);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		bufferedWrite(file, bytes);
    		long end2 = System.currentTimeMillis();
    
    		System.out.println("普通字节流耗时:" + (end - start) + " ms");
    		System.out.println("缓冲字节流耗时:" + (end2 - start2) + " ms");
    
    	}
    
    	// 普通字节流
    	public static void write(File file, byte[] bytes) throws IOException {
    		OutputStream os = new FileOutputStream(file);
    		os.write(bytes);
    		os.close();
    	}
    
    	// 缓冲字节流
    	public static void bufferedWrite(File file, byte[] bytes) throws IOException {
    		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(file));
    		bo.write(bytes);
    		bo.close();
    	}
    }
    

    运行结果:

    普通字节流耗时:250 ms
    缓冲字节流耗时:268 ms
    

    这个结果让我大跌眼镜,不是说好缓冲流效率很高么?要知道为什么,只能去源码里找答案了。翻看字节缓冲流的write方法:

    public synchronized void write(byte b[], int off, int len) throws IOException {
        if (len >= buf.length) {
            /* If the request length exceeds the size of the output buffer,
               flush the output buffer and then write the data directly.
               In this way buffered streams will cascade harmlessly. */
            flushBuffer();
            out.write(b, off, len);
            return;
        }
        if (len > buf.length - count) {
            flushBuffer();
        }
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }
    

    注释里说得很明白:如果请求长度超过输出缓冲区的大小,刷新输出缓冲区,然后直接写入数据。这样,缓冲流将无害地级联。

    但是,至于为什么这么设计,我没有想明白,有哪位明白的大佬可以留言指点一下。

    基于上面的情形,要想对比普通字节流和缓冲字节流的效率差距,就要避免直接读写较长的字符串,于是,设计了下面这个对比案例:用字节流和缓冲字节流分别复制文件。

    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		File data = new File("C:/Mu/data.zip");
    		File a = new File("C:/Mu/a.zip");
    		File b = new File("C:/Mu/b.zip");
    
    		StringBuilder sb = new StringBuilder();
    
    		long start = System.currentTimeMillis();
    		copy(data, a);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		bufferedCopy(data, b);
    		long end2 = System.currentTimeMillis();
    
    		System.out.println("普通字节流耗时:" + (end - start) + " ms");
    		System.out.println("缓冲字节流耗时:" + (end2 - start2) + " ms");
    	}
    
    	// 普通字节流
    	public static void copy(File in, File out) throws IOException {
    		// 封装数据源
    		InputStream is = new FileInputStream(in);
    		// 封装目的地
    		OutputStream os = new FileOutputStream(out);
    		
    		int by = 0;
    		while ((by = is.read()) != -1) {
    			os.write(by);
    		}
    		is.close();
    		os.close();
    	}
    
    	// 缓冲字节流
    	public static void bufferedCopy(File in, File out) throws IOException {
    		// 封装数据源
    		BufferedInputStream bi = new BufferedInputStream(new FileInputStream(in));
    		// 封装目的地
    		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(out));
    		
    		int by = 0;
    		while ((by = bi.read()) != -1) {
    			bo.write(by);
    		}
    		bo.close();
    		bi.close();
    	}
    }
    

    运行结果:

    普通字节流耗时:184867 ms
    缓冲字节流耗时:752 ms
    

    这次,普通字节流和缓冲字节流的效率差异就很明显了,达到了245倍。

    再看看字符流和缓冲字符流的效率对比:

    public class IOTest {
    	public static void main(String[] args) throws IOException {
    		// 数据准备
    		dataReady();
    
    		File data = new File("C:/Mu/data.txt");
    		File a = new File("C:/Mu/a.txt");
    		File b = new File("C:/Mu/b.txt");
    		File c = new File("C:/Mu/c.txt");
    
    		long start = System.currentTimeMillis();
    		copy(data, a);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		copyChars(data, b);
    		long end2 = System.currentTimeMillis();
    
    		long start3 = System.currentTimeMillis();
    		bufferedCopy(data, c);
    		long end3 = System.currentTimeMillis();
    
    		System.out.println("普通字节流1耗时:" + (end - start) + " ms,文件大小:" + a.length() / 1024 + " kb");
    		System.out.println("普通字节流2耗时:" + (end2 - start2) + " ms,文件大小:" + b.length() / 1024 + " kb");
    		System.out.println("缓冲字节流耗时:" + (end3 - start3) + " ms,文件大小:" + c.length() / 1024 + " kb");
    	}
    
    	// 普通字符流不使用数组
    	public static void copy(File in, File out) throws IOException {
    		Reader reader = new FileReader(in);
    		Writer writer = new FileWriter(out);
    
    		int ch = 0;
    		while ((ch = reader.read()) != -1) {
    			writer.write((char) ch);
    		}
    		reader.close();
    		writer.close();
    	}
    
    	// 普通字符流使用字符流
    	public static void copyChars(File in, File out) throws IOException {
    		Reader reader = new FileReader(in);
    		Writer writer = new FileWriter(out);
    
    		char[] chs = new char[1024];
    		while ((reader.read(chs)) != -1) {
    			writer.write(chs);
    		}
    		reader.close();
    		writer.close();
    	}
    
    	// 缓冲字符流
    	public static void bufferedCopy(File in, File out) throws IOException {
    		BufferedReader br = new BufferedReader(new FileReader(in));
    		BufferedWriter bw = new BufferedWriter(new FileWriter(out));
    
    		String line = null;
    		while ((line = br.readLine()) != null) {
    			bw.write(line);
    			bw.newLine();
    			bw.flush();
    		}
    
    		// 释放资源
    		bw.close();
    		br.close();
    	}
    
    	// 数据准备
    	public static void dataReady() throws IOException {
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < 600000; i++) {
    			sb.append("abcdefghijklmnopqrstuvwxyz");
    		}
    		OutputStream os = new FileOutputStream(new File("C:/Mu/data.txt"));
    		os.write(sb.toString().getBytes());
    
    		os.close();
    		System.out.println("完毕");
    	}
    }
    

    运行结果:

    普通字符流1耗时:1337 ms,文件大小:15234 kb
    普通字符流2耗时:82 ms,文件大小:15235 kb
    缓冲字符流耗时:205 ms,文件大小:15234 kb
    

    测试多次,结果差不多,可见字符缓冲流效率上并没有明显提高,我们更多的是要使用它的readLine()newLine()方法。

    4.3 NIO

    待续…

    展开全文
  • * 计算机是如何识别什么时候该把两个字节转换为一个中文呢? * 在计算机中中文的存储分两个字节: * 第一个字节肯定是负数。 * 第二个字节常见的是负数,可能有正数。但是没影响。 */ public class StringDemo {...

     
    import java.util.Arrays;
     
    /*
     * 计算机是如何识别什么时候该把两个字节转换为一个中文呢?
     * 在计算机中中文的存储分两个字节:
     * 第一个字节肯定是负数。
     * 第二个字节常见的是负数,可能有正数。但是没影响。
     */
    public class StringDemo {
    public static void main(String[] args) {
    // String s = "abcde";
    // // [97, 98, 99, 100, 101]
     
    String s = "我爱你中国";
    // [-50, -46, -80, -82, -60, -29, -42, -48, -71, -6]
     
    byte[] bys = s.getBytes();
    System.out.println(Arrays.toString(bys));
    }
    }
    转换流出现的原因及思想
    
    由于字节流操作中文不是特别方便,所以,java就提供了转换流。
    字符流=字节流+编码表。
     
    import java.io.FileInputStream;
    import java.io.IOException;
     
    /*
     * 字节流读取中文可能出现的小问题:
     */
    public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
    // 创建字节输入流对象
    FileInputStream fis = new FileInputStream("a.txt");
     
    // 读取数据
    // int by = 0;
    // while ((by = fis.read()) != -1) {
    // System.out.print((char) by);
    // }
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = fis.read(bys)) != -1) {
    System.out.print(new String(bys, 0, len));
    }
     
    // 释放资源
    fis.close();
    }
    }
    编码表概述和常见的编码表
    
    编码表
      由字符及其对应的数值组成的一张表
     
    计算机只能识别二进制数据,早期由来是电信号。
    为了方便应用计算机,让它可以识别各个国家的文字。
    就将各个国家的文字用数字来表示,并一一对应,形成一张表。
     
    ASCII:美国标准信息交换码。
    用一个字节的7位可以表示。
    ISO8859-1:拉丁码表。欧洲码表
    用一个字节的8位表示。
    GB2312:中国的中文编码表。
    GBK:中国的中文编码表升级,融合了更多的中文文字符号。
    GB18030:GBK的取代版本
    BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。
    Unicode:国际标准码,融合了多种文字。
    所有文字都用两个字节来表示,Java语言使用的就是unicode
    UTF-8:最多用三个字节来表示一个字符。
     
    UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:
    它将Unicode编码为00000000-0000007F的字符,用单个字节来表示
    它将Unicode编码为00000080-000007FF的字符用两个字节表示 
    它将Unicode编码为00000800-0000FFFF的字符用3字节表示 
     
     
     
     
     
    字符串中的编码问题
    
    编码
      把看得懂的变成看不懂的
    解码
      把看不懂的变成看得懂的
     
    import java.io.UnsupportedEncodingException;
    import java.util.Arrays;
     
    /*
     * String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
     * byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
     *
     * 编码:把看得懂的变成看不懂的
     * String -- byte[]
     *
     * 解码:把看不懂的变成看得懂的
     * byte[] -- String
     *
     * 举例:谍战片(发电报,接电报)
     *
     * 码表:小本子
     * 字符数值
     *
     * 要发送一段文字:
     * 今天晚上在老地方见
     *
     * 发送端:今 -- 数值 -- 二进制 -- 发出去
     * 接收端:接收 -- 二进制 -- 十进制 -- 数值 -- 字符 -- 今
     *
     * 今天晚上在老地方见
     *
     * 编码问题简单,只要编码解码的格式是一致的。
     */
    public class StringDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
    String s = "你好";
     
    // String -- byte[]
    byte[] bys = s.getBytes(); // [-60, -29, -70, -61]
    // byte[] bys = s.getBytes("GBK");// [-60, -29, -70, -61]
    // byte[] bys = s.getBytes("UTF-8");// [-28, -67, -96, -27, -91, -67]
    System.out.println(Arrays.toString(bys));
     
    // byte[] -- String
    String ss = new String(bys); // 你好
    // String ss = new String(bys, "GBK"); // 你好
    // String ss = new String(bys, "UTF-8"); // ???
    System.out.println(ss);
    }
    }
     
     
    转换流概述
    
    OutputStreamWriter 字符输出流
      public OutputStreamWriter(OutputStream out)
      public OutputStreamWriter(OutputStream out,String charsetName)
    InputStreamReader 字符输入流
      public InputStreamReader(InputStream in)
      public InputStreamReader(InputStream in,String charsetName)
     
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
     
    /*
     * OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
     * OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
     * 把字节流转换为字符流。
     * 字符流 = 字节流 +编码表。
     */
    public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {
    // 创建对象
    // OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
    // "osw.txt")); // 默认GBK
    // OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
    // "osw.txt"), "GBK"); // 指定GBK
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
    "osw.txt"), "UTF-8"); // 指定UTF-8
    // 写数据
    osw.write("中国");
     
    // 释放资源
    osw.close();
    }
    }
     
     
     
     
    /*
     * InputStreamReader(InputStream is):用默认的编码读取数据
     * InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
     */
    public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
    // 创建对象
    // InputStreamReader isr = new InputStreamReader(new FileInputStream(
    // "osw.txt"));
     
    // InputStreamReader isr = new InputStreamReader(new FileInputStream(
    // "osw.txt"), "GBK");
     
    InputStreamReader isr = new InputStreamReader(new FileInputStream(
    "osw.txt"), "UTF-8");
     
    // 读取数据
    // 一次读取一个字符
    int ch = 0;
    while ((ch = isr.read()) != -1) {
    System.out.print((char) ch);
    }
     
    // 释放资源
    isr.close();
    }
    }
     
     
    OutputStreamWriter写数据
    
    OutputStreamWriter写数据方法
    public void write(int c)
    public void write(char[] cbuf)
    public void write(char[] cbuf,int off,int len)
    public void write(String str)
    public void write(String str,int off,int len)
    字符流操作要注意的问题
    flush()的作用
    flush()和close()的区别
     
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
     
    /*
     * OutputStreamWriter的方法:
     * public void write(int c):写一个字符
     * public void write(char[] cbuf):写一个字符数组
     * public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
     * public void write(String str):写一个字符串
     * public void write(String str,int off,int len):写一个字符串的一部分
     *
     * 面试题:close()和flush()的区别?
     * A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
     * B:flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
     */
    public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {
    // 创建对象
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
    "osw2.txt"));
     
    // 写数据
    // public void write(int c):写一个字符
    // osw.write('a');
    // osw.write(97);
    // 为什么数据没有进去呢?
    // 原因是:字符 = 2字节
    // 文件中数据存储的基本单位是字节。
    // void flush()
     
    // public void write(char[] cbuf):写一个字符数组
    // char[] chs = {'a','b','c','d','e'};
    // osw.write(chs);
     
    // public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
    // osw.write(chs,1,3);
     
    // public void write(String str):写一个字符串
    // osw.write("我爱林青霞");
     
    // public void write(String str,int off,int len):写一个字符串的一部分
    osw.write("我爱林青霞", 2, 3);
     
    // 刷新缓冲区
    osw.flush();
    // osw.write("我爱林青霞", 2, 3);
     
    // 释放资源
    osw.close();
    // java.io.IOException: Stream closed
    // osw.write("我爱林青霞", 2, 3);
    }
    }
     
    读取文件
    
     
    /*
     * InputStreamReader的方法:
     * int read():一次读取一个字符
     * int read(char[] chs):一次读取一个字符数组
     */
    public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
    // 创建对象
    InputStreamReader isr = new InputStreamReader(new FileInputStream(
    "StringDemo.java"));
     
    // 一次读取一个字符
    // int ch = 0;
    // while ((ch = isr.read()) != -1) {
    // System.out.print((char) ch);
    // }
     
    // 一次读取一个字符数组
    char[] chs = new char[1024];
    int len = 0;
    while ((len = isr.read(chs)) != -1) {
    System.out.print(new String(chs, 0, len));
    }
     
    // 释放资源
    isr.close();
    }
    }
     
    字符流复制文本文件
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
     
    /*
     * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
     *
     * 数据源:
     * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader
     * 目的地:
     * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter
     */
    public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    InputStreamReader isr = new InputStreamReader(new FileInputStream(
    "a.txt"));
    // 封装目的地
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
    "b.txt"));
     
    // 读写数据
    // 方式1
    // int ch = 0;
    // while ((ch = isr.read()) != -1) {
    // osw.write(ch);
    // }
     
    // 方式2
    char[] chs = new char[1024];
    int len = 0;
    while ((len = isr.read(chs)) != -1) {
    osw.write(chs, 0, len);
    // osw.flush();
    }
     
    // 释放资源
    osw.close();
    isr.close();
    }
    }
    方案二
    
    转换流的简化写法
    
    转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。
    FileWriter
    FileReader
     
     
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
     
    /*
     * 由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。
     * 而转换流的名称有点长,所以,Java就提供了其子类供我们使用。
     * OutputStreamWriter = FileOutputStream + 编码表(GBK)
     * FileWriter = FileOutputStream + 编码表(GBK)
     *
     * InputStreamReader = FileInputStream + 编码表(GBK)
     * FileReader = FileInputStream + 编码表(GBK)
     *
     /*
     * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
     *
     * 数据源:
     * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader
     * 目的地:
     * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter
     */
    public class CopyFileDemo2 {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    FileReader fr = new FileReader("a.txt");
    // 封装目的地
    FileWriter fw = new FileWriter("b.txt");
     
    // 一次一个字符
    // int ch = 0;
    // while ((ch = fr.read()) != -1) {
    // fw.write(ch);
    // }
     
    // 一次一个字符数组
    char[] chs = new char[1024];
    int len = 0;
    while ((len = fr.read(chs)) != -1) {
    fw.write(chs, 0, len);
    fw.flush();
    }
     
    // 释放资源
    fw.close();
    fr.close();
    }
    }
    Demo3
    
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
     
    /*
     * 需求:把c:\\a.txt内容复制到d:\\b.txt中
     *
     * 数据源:
     * c:\\a.txt -- FileReader
     * 目的地:
     * d:\\b.txt -- FileWriter
     */
    public class CopyFileDemo3 {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    FileReader fr = new FileReader("c:\\a.txt");
    // 封装目的地
    FileWriter fw = new FileWriter("d:\\b.txt");
     
    // 读写数据
    // int ch = 0;
    int ch;
    while ((ch = fr.read()) != -1) {
    fw.write(ch);
    }
    //释放资源
    fw.close();
    fr.close();
    }
    }
     
     
     
    字符缓冲流
    
    BufferedWriter基本用法
    BufferedReader基本用法
    字符缓冲流复制文本文件
    特殊功能
       BufferedWriter
       void newLine()
       BufferedReader
       String readLine()
    字符缓冲流特殊功能复制文本文件
     
    /*
     * 字符流为了高效读写,也提供了对应的字符缓冲流。
     * BufferedWriter:字符缓冲输出流
     * BufferedReader:字符缓冲输入流
     *
     * BufferedWriter:字符缓冲输出流
     * 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
     * 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
     */
    public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
    // BufferedWriter(Writer out)
    // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
    // new FileOutputStream("bw.txt")));
     
    BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
     
    bw.write("hello");
    bw.write("world");
    bw.write("java");
    bw.flush();
     
    bw.close();
    }
    }
     
    BufferedReader
    
    /*
     * BufferedReader
     * 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
     * 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
     *
     * BufferedReader(Reader in)
     */
    public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
    // 创建字符缓冲输入流对象
    BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
     
    // 方式1
    // int ch = 0;
    // while ((ch = br.read()) != -1) {
    // System.out.print((char) ch);
    // }
     
    // 方式2
    char[] chs = new char[1024];
    int len = 0;
    while ((len = br.read(chs)) != -1) {
    System.out.print(new String(chs, 0, len));
    }
     
    // 释放资源
    br.close();
    }
    }
     
    字符缓冲流特殊功能复制文本文件
    
    /*
     * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
     *
     * 数据源:
     * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader
     * 目的地:
     * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter
     */
    public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    BufferedReader br = new BufferedReader(new FileReader("a.txt"));
    // 封装目的地
    BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
     
    // 两种方式其中的一种一次读写一个字符数组
    char[] chs = new char[1024];
    int len = 0;
    while ((len = br.read(chs)) != -1) {
    bw.write(chs, 0, len);
    bw.flush();
    }
     
    // 释放资源
    bw.close();
    br.close();
    }
    }
     
    字符缓冲流的特殊方法
    
    /*
     * 字符缓冲流的特殊方法:
     * BufferedWriter:
     * public void newLine():根据系统来决定换行符
     * BufferedReader:
     * public String readLine():一次读取一行数据
     * 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
     */
    public class BufferedDemo {
    public static void main(String[] args) throws IOException {
    // write();
    read();
    }
     
    private static void read() throws IOException {
    // 创建字符缓冲输入流对象
    BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
     
    // public String readLine():一次读取一行数据
    // String line = br.readLine();
    // System.out.println(line);
    // line = br.readLine();
    // System.out.println(line);
     
    // 最终版代码
    String line = null;
    while ((line = br.readLine()) != null) {
    System.out.println(line);
    }
    //释放资源
    br.close();
    }
     
    private static void write() throws IOException {
    // 创建字符缓冲输出流对象
    BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
    for (int x = 0; x < 10; x++) {
    bw.write("hello" + x);
    // bw.write("\r\n");
    bw.newLine();
    bw.flush();
    }
    bw.close();
    }
     
    }
     
     
    文件的复制
    
    /*
     * 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
     *
     * 数据源:
     * a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader
     * 目的地:
     * b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter
     */
    public class CopyFileDemo2 {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    BufferedReader br = new BufferedReader(new FileReader("a.txt"));
    // 封装目的地
    BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
     
    // 读写数据
    String line = null;
    while ((line = br.readLine()) != null) {
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
     
    // 释放资源
    bw.close();
    br.close();
    }
    }
     
    IO流小结
    
    字节流
      字节输入流
      字节输出流
    字符流
      字符输入流
      字符输出流
     
     
     
     
    复制文本
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
     
    /*
     * 复制文本文件
     *
     * 分析:
     * 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
     * 通过该原理,我们知道我们应该采用字符流更方便一些。
     * 而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。
     * 数据源:
     * c:\\a.txt -- FileReader -- BufferdReader
     * 目的地:
     * d:\\b.txt -- FileWriter -- BufferedWriter
     */
    public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
    String srcString = "c:\\a.txt";
    String destString = "d:\\b.txt";
    // method1(srcString, destString);
    // method2(srcString, destString);
    // method3(srcString, destString);
    // method4(srcString, destString);
    method5(srcString, destString);
    }
     
    // 字符缓冲流一次读写一个字符串
    private static void method5(String srcString, String destString)
    throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(srcString));
    BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
     
    String line = null;
    while ((line = br.readLine()) != null) {
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
     
    bw.close();
    br.close();
    }
     
    // 字符缓冲流一次读写一个字符数组
    private static void method4(String srcString, String destString)
    throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(srcString));
    BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
     
    char[] chs = new char[1024];
    int len = 0;
    while ((len = br.read(chs)) != -1) {
    bw.write(chs, 0, len);
    }
     
    bw.close();
    br.close();
    }
     
    // 字符缓冲流一次读写一个字符
    private static void method3(String srcString, String destString)
    throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(srcString));
    BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
     
    int ch = 0;
    while ((ch = br.read()) != -1) {
    bw.write(ch);
    }
     
    bw.close();
    br.close();
    }
     
    // 基本字符流一次读写一个字符数组
    private static void method2(String srcString, String destString)
    throws IOException {
    FileReader fr = new FileReader(srcString);
    FileWriter fw = new FileWriter(destString);
     
    char[] chs = new char[1024];
    int len = 0;
    while ((len = fr.read(chs)) != -1) {
    fw.write(chs, 0, len);
    }
     
    fw.close();
    fr.close();
    }
     
    // 基本字符流一次读写一个字符
    private static void method1(String srcString, String destString)
    throws IOException {
    FileReader fr = new FileReader(srcString);
    FileWriter fw = new FileWriter(destString);
     
    int ch = 0;
    while ((ch = fr.read()) != -1) {
    fw.write(ch);
    }
     
    fw.close();
    fr.close();
    }
    }
     
    复制图片
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
     
    /*
     * 复制图片
     *
     * 分析:
     * 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
     * 通过该原理,我们知道我们应该采用字节流。
     * 而字节流有4种方式,所以做这个题目我们有4种方式。推荐掌握第4种。
     *
     * 数据源:
     * c:\\a.jpg -- FileInputStream -- BufferedInputStream
     * 目的地:
     * d:\\b.jpg -- FileOutputStream -- BufferedOutputStream
     */
    public class CopyImageDemo {
    public static void main(String[] args) throws IOException {
    // 使用字符串作为路径
    // String srcString = "c:\\a.jpg";
    // String destString = "d:\\b.jpg";
    // 使用File对象做为参数
    File srcFile = new File("c:\\a.jpg");
    File destFile = new File("d:\\b.jpg");
     
    // method1(srcFile, destFile);
    // method2(srcFile, destFile);
    // method3(srcFile, destFile);
    method4(srcFile, destFile);
    }
     
    // 字节缓冲流一次读写一个字节数组
    private static void method4(File srcFile, File destFile) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
    srcFile));
    BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(destFile));
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = bis.read(bys)) != -1) {
    bos.write(bys, 0, len);
    }
     
    bos.close();
    bis.close();
    }
     
    // 字节缓冲流一次读写一个字节
    private static void method3(File srcFile, File destFile) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
    srcFile));
    BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(destFile));
     
    int by = 0;
    while ((by = bis.read()) != -1) {
    bos.write(by);
    }
     
    bos.close();
    bis.close();
    }
     
    // 基本字节流一次读写一个字节数组
    private static void method2(File srcFile, File destFile) throws IOException {
    FileInputStream fis = new FileInputStream(srcFile);
    FileOutputStream fos = new FileOutputStream(destFile);
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = fis.read(bys)) != -1) {
    fos.write(bys, 0, len);
    }
     
    fos.close();
    fis.close();
    }
     
    // 基本字节流一次读写一个字节
    private static void method1(File srcFile, File destFile) throws IOException {
    FileInputStream fis = new FileInputStream(srcFile);
    FileOutputStream fos = new FileOutputStream(destFile);
     
    int by = 0;
    while ((by = fis.read()) != -1) {
    fos.write(by);
    }
     
    fos.close();
    fis.close();
    }
    }
     
     
    把ArrayList集合中的字符串数据存储到文本文件
    
    /*
     * 需求:把ArrayList集合中的字符串数据存储到文本文件
     *
     * 分析:
     * 通过题目的意思我们可以知道如下的一些内容,
     * ArrayList集合里存储的是字符串。
     * 遍历ArrayList集合,把数据获取到。
     * 然后存储到文本文件中。
     * 文本文件说明使用字符流。
     *
     * 数据源:
     * ArrayList<String> -- 遍历得到每一个字符串数据
     * 目的地:
     * a.txt -- FileWriter -- BufferedWriter
     */
    public class ArrayListToFileDemo {
    public static void main(String[] args) throws IOException {
    // 封装数据与(创建集合对象)
    ArrayList<String> array = new ArrayList<String>();
    array.add("hello");
    array.add("world");
    array.add("java");
     
    // 封装目的地
    BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
     
    // 遍历集合
    for (String s : array) {
    // 写数据
    bw.write(s);
    bw.newLine();
    bw.flush();
    }
     
    // 释放资源
    bw.close();
    }
    }
    从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.ArrayList;
     
    /*
     * 需求:从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合
     *
     * 分析:
     * 通过题目的意思我们可以知道如下的一些内容,
     * 数据源是一个文本文件。
     * 目的地是一个集合。
     * 而且元素是字符串。
     *
     * 数据源:
     * b.txt -- FileReader -- BufferedReader
     * 目的地:
     * ArrayList<String>
     */
    public class FileToArrayListDemo {
    public static void main(String[] args) throws IOException {
    // 封装数据源
    BufferedReader br = new BufferedReader(new FileReader("b.txt"));
    // 封装目的地(创建集合对象)
    ArrayList<String> array = new ArrayList<String>();
     
    // 读取数据存储到集合中
    String line = null;
    while ((line = br.readLine()) != null) {
    array.add(line);
    }
     
    // 释放资源
    br.close();
     
    // 遍历集合
    for (String s : array) {
    System.out.println(s);
    }
    }
    }
     
    小游戏
    
    /*
     * 需求:我有一个文本文件中存储了几个名称,请大家写一个程序实现随机获取一个人的名字。
     *
     * 分析:
     * A:把文本文件中的数据存储到集合中
     * B:随机产生一个索引
     * C:根据该索引获取一个值
     */
    public class GetName {
    public static void main(String[] args) throws IOException {
    // 把文本文件中的数据存储到集合中
    BufferedReader br = new BufferedReader(new FileReader("b.txt"));
    ArrayList<String> array = new ArrayList<String>();
    String line = null;
    while ((line = br.readLine()) != null) {
    array.add(line);
    }
    br.close();
     
    // 随机产生一个索引
    Random r = new Random();
    int index = r.nextInt(array.size());
     
    // 根据该索引获取一个值
    String name = array.get(index);
    System.out.println("该幸运者是:" + name);
    }
    }
     
    复制单个文件夹
    
    /*
     * 需求:复制单个文件夹
     *
     * 数据源:e:\\demo
     * 目的地:e:\\test
     *
     * 分析:
     * A:封装目录
     * B:获取该目录下的所有文本的File数组
     * C:遍历该File数组,得到每一个File对象
     * D:把该File进行复制
     */
    public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
    // 封装目录
    File srcFolder = new File("e:\\demo");
    // 封装目的地
    File destFolder = new File("e:\\test");
    // 如果目的地文件夹不存在,就创建
    if (!destFolder.exists()) {
    destFolder.mkdir();
    }
     
    // 获取该目录下的所有文本的File数组
    File[] fileArray = srcFolder.listFiles();
     
    // 遍历该File数组,得到每一个File对象
    for (File file : fileArray) {
    // System.out.println(file);
    // 数据源:e:\\demo\\e.mp3
    // 目的地:e:\\test\\e.mp3
    String name = file.getName(); // e.mp3
    File newFile = new File(destFolder, name); // e:\\test\\e.mp3
     
    copyFile(file, newFile);
    }
    }
     
    private static void copyFile(File file, File newFile) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
    file));
    BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(newFile));
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = bis.read(bys)) != -1) {
    bos.write(bys, 0, len);
    }
     
    bos.close();
    bis.close();
    }
    }
     
    复制单极文件夹中指定文件并修改文件名称
    
     
    /*
     * 需求:复制指定目录下的指定文件,并修改后缀名。
     * 指定的文件是:.java文件。
     * 指定的后缀名是:.jad
     * 指定的目录是:jad
     *
     * 数据源:e:\\java\\A.java
     * 目的地:e:\\jad\\A.jad
     *
     * 分析:
     * A:封装目录
     * B:获取该目录下的java文件的File数组
     * C:遍历该File数组,得到每一个File对象
     * D:把该File进行复制
     * E:在目的地目录下改名
     */
    public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
    // 封装目录
    File srcFolder = new File("e:\\java");
    // 封装目的地
    File destFolder = new File("e:\\jad");
    // 如果目的地目录不存在,就创建
    if (!destFolder.exists()) {
    destFolder.mkdir();
    }
     
    // 获取该目录下的java文件的File数组
    File[] fileArray = srcFolder.listFiles(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String name) {
    return new File(dir, name).isFile() && name.endsWith(".java");
    }
    });
     
    // 遍历该File数组,得到每一个File对象
    for (File file : fileArray) {
    // System.out.println(file);
    // 数据源:e:\java\DataTypeDemo.java
    // 目的地:e:\\jad\DataTypeDemo.java
    String name = file.getName();
    File newFile = new File(destFolder, name);
    copyFile(file, newFile);
    }
     
    // 在目的地目录下改名
    File[] destFileArray = destFolder.listFiles();
    for (File destFile : destFileArray) {
    // System.out.println(destFile);
    // e:\jad\DataTypeDemo.java
    // e:\\jad\\DataTypeDemo.jad
    String name =destFile.getName(); //DataTypeDemo.java
    String newName = name.replace(".java", ".jad");//DataTypeDemo.jad
    File newFile = new File(destFolder,newName);
    destFile.renameTo(newFile);
    }
    }
     
    private static void copyFile(File file, File newFile) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
    file));
    BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(newFile));
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = bis.read(bys)) != -1) {
    bos.write(bys, 0, len);
    }
     
    bos.close();
    bis.close();
    }
    }
     
    复制多个文件夹
    
     
    /*
     * 需求:复制指定目录下的指定文件,并修改后缀名。
     * 指定的文件是:.java文件。
     * 指定的后缀名是:.jad
     * 指定的目录是:jad
     *
     * 数据源:e:\\java\\A.java
     * 目的地:e:\\jad\\A.jad
     *
     * 分析:
     * A:封装目录
     * B:获取该目录下的java文件的File数组
     * C:遍历该File数组,得到每一个File对象
     * D:把该File进行复制
     * E:在目的地目录下改名
     */
    public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
    // 封装目录
    File srcFolder = new File("e:\\java");
    // 封装目的地
    File destFolder = new File("e:\\jad");
    // 如果目的地目录不存在,就创建
    if (!destFolder.exists()) {
    destFolder.mkdir();
    }
     
    // 获取该目录下的java文件的File数组
    File[] fileArray = srcFolder.listFiles(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String name) {
    return new File(dir, name).isFile() && name.endsWith(".java");
    }
    });
     
    // 遍历该File数组,得到每一个File对象
    for (File file : fileArray) {
    // System.out.println(file);
    // 数据源:e:\java\DataTypeDemo.java
    // 目的地:e:\\jad\DataTypeDemo.java
    String name = file.getName();
    File newFile = new File(destFolder, name);
    copyFile(file, newFile);
    }
     
    // 在目的地目录下改名
    File[] destFileArray = destFolder.listFiles();
    for (File destFile : destFileArray) {
    // System.out.println(destFile);
    // e:\jad\DataTypeDemo.java
    // e:\\jad\\DataTypeDemo.jad
    String name =destFile.getName(); //DataTypeDemo.java
    String newName = name.replace(".java", ".jad");//DataTypeDemo.jad
    File newFile = new File(destFolder,newName);
    destFile.renameTo(newFile);
    }
    }
     
    private static void copyFile(File file, File newFile) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
    file));
    BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(newFile));
     
    byte[] bys = new byte[1024];
    int len = 0;
    while ((len = bis.read(bys)) != -1) {
    bos.write(bys, 0, len);
    }
     
    bos.close();
    bis.close();
    }
    }
    键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
    
    public class Student {
    // 姓名
    private String name;
    // 语文成绩
    private int chinese;
    // 数学成绩
    private int math;
    // 英语成绩
    private int english;
     
    public Student() {
    super();
    }
     
    public Student(String name, int chinese, int math, int english) {
    super();
    this.name = name;
    this.chinese = chinese;
    this.math = math;
    this.english = english;
    }
     
    public String getName() {
    return name;
    }
     
    public void setName(String name) {
    this.name = name;
    }
     
    public int getChinese() {
    return chinese;
    }
     
    public void setChinese(int chinese) {
    this.chinese = chinese;
    }
     
    public int getMath() {
    return math;
    }
     
    public void setMath(int math) {
    this.math = math;
    }
     
    public int getEnglish() {
    return english;
    }
     
    public void setEnglish(int english) {
    this.english = english;
    }
     
    public int getSum() {
    return this.chinese + this.math + this.english;
    }
    }
     
    /*
     * 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
     *
     * 分析:
     * A:创建学生类
     * B:创建集合对象
     * TreeSet<Student>
     * C:键盘录入学生信息存储到集合
     * D:遍历集合,把数据写到文本文件
     */
    public class StudentDemo {
    public static void main(String[] args) throws IOException {
    // 创建集合对象
    TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
    @Override
    public int compare(Student s1, Student s2) {
    int num = s2.getSum() - s1.getSum();
    int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
    int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
    int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
    int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName())
    : num4;
    return num5;
    }
    });
     
    // 键盘录入学生信息存储到集合
    for (int x = 1; x <= 5; x++) {
    Scanner sc = new Scanner(System.in);
    System.out.println("请录入第" + x + "个的学习信息");
    System.out.println("姓名:");
    String name = sc.nextLine();
    System.out.println("语文成绩:");
    int chinese = sc.nextInt();
    System.out.println("数学成绩:");
    int math = sc.nextInt();
    System.out.println("英语成绩:");
    int english = sc.nextInt();
     
    // 创建学生对象
    Student s = new Student();
    s.setName(name);
    s.setChinese(chinese);
    s.setMath(math);
    s.setEnglish(english);
     
    // 把学生信息添加到集合
    ts.add(s);
    }
     
    // 遍历集合,把数据写到文本文件
    BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"));
    bw.write("学生信息如下:");
    bw.newLine();
    bw.flush();
    bw.write("姓名,语文成绩,数学成绩,英语成绩");
    bw.newLine();
    bw.flush();
    for (Student s : ts) {
    StringBuilder sb = new StringBuilder();
    sb.append(s.getName()).append(",").append(s.getChinese())
    .append(",").append(s.getMath()).append(",")
    .append(s.getEnglish());
    bw.write(sb.toString());
    bw.newLine();
    bw.flush();
    }
    // 释放资源
    bw.close();
    System.out.println("学习信息存储完毕");
    }
    }
     
    已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl”
    
     请编写程序读取数据内容,把数据排序后写入ss.txt中。
    
    /*
     * 已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl”
     * 请编写程序读取数据内容,把数据排序后写入ss.txt中。
     *
     * 分析:
     * A:把s.txt这个文件给做出来
     * B:读取该文件的内容,存储到一个字符串中
     * C:把字符串转换为字符数组
     * D:对字符数组进行排序
     * E:把排序后的字符数组转换为字符串
     * F:把字符串再次写入ss.txt中
     */
    public class StringDemo {
    public static void main(String[] args) throws IOException {
    // 读取该文件的内容,存储到一个字符串中
    BufferedReader br = new BufferedReader(new FileReader("s.txt"));
    String line = br.readLine();
    br.close();
     
    // 把字符串转换为字符数组
    char[] chs = line.toCharArray();
     
    // 对字符数组进行排序
    Arrays.sort(chs);
     
    // 把排序后的字符数组转换为字符串
    String s = new String(chs);
     
    // 把字符串再次写入ss.txt中
    BufferedWriter bw = new BufferedWriter(new FileWriter("ss.txt"));
    bw.write(s);
    bw.newLine();
    bw.flush();
     
    bw.close();
    }
    }
     
     
    1:字符流(掌握)
    (1)字节流操作中文数据不是特别的方便,所以就出现了转换流。
       转换流的作用就是把字节流转换字符流来使用。
    (2)转换流其实是一个字符流
    字符流 = 字节流 + 编码表
    (3)编码表
    A:就是由字符和对应的数值组成的一张表
    B:常见的编码表
    ASCII
    ISO-8859-1
    GB2312
    GBK
    GB18030
    UTF-8
    C:字符串中的编码问题
    编码
    String -- byte[]
    解码
    byte[] -- String
    (4)IO流中的编码问题
    A:OutputStreamWriter
    OutputStreamWriter(OutputStream os):默认编码,GBK
    OutputStreamWriter(OutputStream os,String charsetName):指定编码。
    B:InputStreamReader
    InputStreamReader(InputStream is):默认编码,GBK
    InputStreamReader(InputStream is,String charsetName):指定编码
    C:编码问题其实很简单
    编码只要一致即可
    (5)字符流
    Reader
    |--InputStreamReader
    |--FileReader
    |--BufferedReader
    Writer
    |--OutputStreamWriter
    |--FileWriter
    |--BufferedWriter
    (6)复制文本文件(5种方式)
     
    2:IO流小结(掌握)
    IO流
    |--字节流
    |--字节输入流
    InputStream
    int read():一次读取一个字节
    int read(byte[] bys):一次读取一个字节数组
    |--FileInputStream
    |--BufferedInputStream
    |--字节输出流
    OutputStream
    void write(int by):一次写一个字节
    void write(byte[] bys,int index,int len):一次写一个字节数组的一部分
    |--FileOutputStream
    |--BufferedOutputStream
    |--字符流
    |--字符输入流
    Reader
    int read():一次读取一个字符
    int read(char[] chs):一次读取一个字符数组
    |--InputStreamReader
    |--FileReader
    |--BufferedReader
    String readLine():一次读取一个字符串
    |--字符输出流
    Writer
    void write(int ch):一次写一个字符
    void write(char[] chs,int index,int len):一次写一个字符数组的一部分
    |--OutputStreamWriter
    |--FileWriter
    |--BufferedWriter
    void newLine():写一个换行符
    void write(String line):一次写一个字符串
     
    3:案例(理解 练习一遍)
    A:复制文本文件 5种方式(掌握)
    B:复制图片(二进制流数据) 4种方式(掌握)
    C:把集合中的数据存储到文本文件
    D:把文本文件中的数据读取到集合并遍历集合
    E:复制单级文件夹
    F:复制单级文件夹中指定的文件并修改名称
    回顾一下批量修改名称
    H:键盘录入学生信息按照总分从高到低存储到文本文件
    I:把某个文件中的字符串排序后输出到另一个文本文件中
     
     
     
     
     
     
     
     
     
     
     


    展开全文
  • IO流---使用字节流读写文件

    千次阅读 2019-06-10 23:36:30
    如何读写文件? 通过来读写文件:是指一连串流动的字符,是以先进先出方式发送信息的通道 读入(read Input);...java中一个字符(Unicode2个字节),一个二进制字节(8位); JAVA的分类: ...
  • 如果我们有多个相同格式的文件,比如1.mp3,2.mp3,3.mp3,4.mp3,5.mp3,... 首先考虑的就是使用字节流,因为纯文本文件使用字符流还比较好用,其余的不是纯文本的文件都是使用字节流,因为硬盘上的所有文件都是以字节的形
  • 字符流就是基于字节流来实现的,我们知道一个字节是8个二进制位,在UTF-8中一个字节对应一个英文字符,人们发现用单个字节操作文本比较麻烦,所以就对字节流进行封装,当对文本进行操作的时候就不直接对字节流进行...
  • Java IO字符流与字节流

    千次阅读 2015-05-22 22:21:54
    数据: 字节流:二进制,可以处理文本文件,视频,音频等 。 字符流:文本文件,只能处理纯文本,全款为可见字符(.txt、.html)。 3.功能:节点:包裹源头 处理:增强功能,提高性能。三、字节流与字符流1.字节流...
  • 什么是字节流字节流的类通常以stream结尾 字节流--传输过程中,传输数据的最基本单位是字节的流。 什么是字符流? 字符流的类通常以reader和writer结尾 字符流--传输过程中,传输数据的最基本单位是字符的流。...
  • 字节流不但可以写文本还可以图片,音频 public static void main(String[] args){ FileInputStream f = new FileInputStream("/Users/lanou/Desktop/test/11.png"); FileInputStream f2 = new FileInput
  • Java讲课笔记24:字节流

    千次阅读 2020-05-25 12:15:16
    文章目录零、本讲学习目标1、了解字节流的概念及其分类2、学会使用字节流实现读写操作3、学会使用字节流实现文件拷贝一、I/O流概述1、I/O流定义2、I/O流分类3、I/O流层次结构4、数据的输出5、数据的输入6、声明I/O流...
  • Java字节流与字符流及文件操作

    千次阅读 2020-07-21 13:29:34
    目录Java.io知识点梳理File类字节流OutputStream字节流InputStream字符流Writer字符流Reader字节流与字符流的转换(了解)字节流与字符流的区别?两者如何使用? Java.io知识点梳理 如果要进行所有的文件以及文件...
  • Java学习笔记19:Java_File类_字节流

    千次阅读 2021-08-11 10:06:13
    字节流2.1 IO流概述和分类【理解】2.2字节流写数据【应用】2.3字节流写数据的三种方式【应用】2.4字节流写数据的两个小问题【应用】2.5字节流写数据加异常处理【应用】2.6字节流读数据(一次读一个字节数据)【应用】2
  • 描述:利用字节输出一次一个字节的方式,向D盘的a.txt文件输出字符‘a’。 答案 操作步骤: 1.创建字节输出FileOutputStream对象并指定文件路径。 2.调用字节输出的write(int byte)方法出数据 代码: public ...
  • java利用IO将内容输出到文本

    千次阅读 2018-03-07 09:57:54
    java利用IO将内容输出到文本 将网页保存到本地 需要的jar包下载地址 http://download.csdn.net/download/weixin_39549656/10272781 package baike; import java.io.File; import java.io.FileOutputStream;...
  • JAVA使用字节流将本地图片传到前端

    万次阅读 2018-04-09 10:18:55
    JAVA使用字节流将本地图片传到前端 01.基本介绍 02.代码介绍 03.结果展示 JAVA使用字节流将本地图片传到前端 01.基本介绍 在我们日常的开发中,会遇到对验证码的使用问题(验证码的作用这里不多多说,...
  • 先说总结:复制文本文件,既可用字符流方式,也可以用字节流方式.复制非文本文件,只能用字节流方式.字符流的读取与写入方式: 按单个字符按字符数组按行字符输入流FileReaderread()read(char[] cbuf) 字符输出流...
  • 简单实现了通过字节流与字符流两种方式拷贝文件 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; ...
  • •当创建一个文件对象后,就可以利用它来对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等等; 需要注意的是,File对象并不能直接对文件进行读/操作,只能查看文件的属性; ...
  • IO概述 学习IO流的目的: 实现数据的持久化。 什么是IO: Input:输入 ...字节流:以字节为单位读写数据。 字节输入流:InputStream 所有字节输入流的父类 。 字节输出流:OutputStream 所有...
  • 1.字节数组 输出:ByteArrayOutputStream bos=new ByteArrayOutputStream(); 由于输出有新增方法,所以这里不可以使用多态 输入:ByteArrayInputStream bis=new ByteArrayInputStream(destByte); ...
  • Byte-Based IO Byte Streams 基于字节的I O和字节流 Reading from an InputStream Writing to an OutputStream Opening Closing IO Streams Flushing the OutputStream Implementations of abstract ...
  • 使用字节流和字符流读取文件

    千次阅读 2015-09-13 21:15:41
    使用字节流的方式进行文件的读取并打印至控制台: import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class A { public static void main(String[] args)throws ...
  • JAVA:IO流 之 字节流与字符流(1)

    千次阅读 2017-05-14 17:30:14
    【转载】java学习之IO使用技巧浅谈 首先,通过转载百度经验中的一篇介绍Java使用经验的文章作为开始,来学习和总结Java中的IO...第一步,首先,明确IO中有两个主要的体系,即字节输入(InputStream)、...
  • 一.文件和目录 ...二、字节流 1.生成ZIP压缩文件 2.解压缩zip文件 3.生成Excel文件 4.读取excel文件 5.生成PDF文件 6.读取PDF文件中的内容 7.利用poi读取Word文件中的内容。 三、字符流 1.追加文件内容 2
  • java输入输出--字节流处理

    千次阅读 2018-07-10 01:02:25
    字节流类为处理字节式输入输出提供了丰富的环境。 InputStream/OutputStream InputStream 是一个定义了 Java 字节流输入模式的抽象类。 该类的所有方法在出错条件下都将引发一个 IOException 异常。其声明格式...
  • 字节流与字符流的区别及相互转换

    千次阅读 2017-10-20 08:41:13
    先来看一下流的概念:  在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。...字节流与字符流  在ja
  • Response对象通过字节流输出中文内容

    万次阅读 2016-08-21 10:49:29
    Response对象通过字节流输出中文内容:
  • JAVA IO一、相关概念1、分类:区别和联系 一、相关概念 I/O: Input/Output Stream,文件输入输出...其中输出就是指将程序中的内容输出到文件中的,也就是文件。 根据读写操作的基本单位不同分为:字...
  • --------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!...字节流:InputStream,OutputStream主要是用来操作的是媒体文件,例如:图片,音乐,电影…等。但是也可以操作文件。   如果

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 77,019
精华内容 30,807
关键字:

利用字节流写文本