黑马程序员----IO流(上)

本文深入讲解Java IO流的基础概念、分类、典型应用及异常处理流程。涵盖了字符流、字节流及其缓冲区对象的使用技巧,同时介绍了装饰设计模式的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


IO流

1.什么是IO流?

我们可以想象成一条河流,但是这条河比较特别,它里面流淌的不是水,而是数据。


IO流分类:

1.既然是河流,那么肯定得有方向吧,也就是按照流向分类:输入流,输出流。
2.我们知道数据分很多种对吧,根据流淌的数据类型分类:字节流,字符流。

IO体系基类:

I nputStream字节输入流
OutputStream字节输出流
Reader字符输入流
Writer字符输出流

IO体系子类命名特点:

子类名=功能+父类名,例如子类FileWriter:就是这个子类是操作文件的,且是Writer的一个子类。

举例使用该体系一员:

FileWriter fw=new FileWriter("demo.txt");
fw.write("123");
fw.flush();
fw.close();
我们看到这是一个处理文件的字符输出流,也就是说将数据写到文件中,那么可知我们必须得有一个文件吧,"demo.txt"就是传入那个文件名的。 如果该文件不存在,那么就在指定路径下创建它,如果存在,则覆盖它
fw.write("123") 向流中写入数据,注意还不是写到文件中,而是先写入流中,这就好像我们先把数据扔到河里,但是这些东西还没有随着河水流入目的地。
fw.flush() 将当前流中的数据写入到目的地文件中,就好像对河中数据进行一次集体打捞,捞到的全部拿到目的地存放。
fw.close() 关闭流资源,我们知道流作为一种资源,在使用完毕后是要关闭的,否则会导致内存泄露,在 close方法内部会调用一次flush进行数据打捞

IOException处理流程:

try
{
FileWriter fw = new FileWriter("demo.txt");
fw.write("123");
fw.flush();
}
catch(IOException e)
{
//处理该打开或者写入异常
}
finally
{
if(fw!=null)
try
{
fw.close();
}
catch(IOException e)
{
//处理关闭异常
}
}

文件续写:

我们发现,按照上述方式打开文件,写入数据会将原本的内容覆盖掉,那么如果我们是打算接着文件中已有内容续写呢?这时就需要使用FileWriter的另一个构造函数了。
FileWriter fw=new FileWriter("demo.txt",true);
第二个参数表示是否以附加的方式写入数据,我们传入true就不会覆盖掉原本的数据了。
代码:
//文件的续写
package com.helong.filewriterdemo2;
import java.io.*;
class FileWriterDemo2 
{
	public static void main(String[] args) 
	{
		FileWriter fw=null;
		try
		{
			fw=new FileWriter("Demo2.txt",true);//true表示以续写的方式打开文件
			fw.write("\r\n第二行\r\n第三行");
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}



文本拷贝原理:

将源文件数据读取到流中,到目的地创建新文件,将流中数据写入目的地文件中。


拷贝文件练习:

package com.helong.copyfile;
import java.io.*;
class CopyFile 
{
	public static void main(String[] args) throws IOException
	{
		//copy1();

		copy2();
	}
	//这种方法效率太低,每次取出一个字符然后写入,要重复很多次硬盘和内存之间的交互
	private static void copy1()throws IOException
	{
		//每次取出一个字符,写入目的地文件
		FileWriter fw = new FileWriter("Demo(2).txt");
		FileReader fr = new FileReader("Demo.txt");
		
		for(int c=fr.read();c!=-1;c=fr.read())
		{
			fw.write(c);
		}
		fr.close();
		fw.close();
	}
	private static void copy2()
	{
		FileWriter fw=null;
		FileReader fr=null;
		try
		{
			fw=new FileWriter("Demo(3).txt");
			fr=new FileReader("Demo.txt");
			char[] arr=new char[1024];
			for(int count=fr.read(arr);count!=-1;count=fr.read(arr))
			{
				fw.write(arr,0,count);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				if(fw!=null)fw.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			finally
			{
				try
				{
					if(fr!=null)fr.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
}

运行图:

IO流小练习:

//打印一个java文件,输出到控制台
package com.helong.filetest;
import java.io.*;
class FileTest 
{
	public static void main(String[] args) throws IOException
	{
		FileWriter fw=new FileWriter("FileText.java");
		fw.write("class Demo\r\n");
		fw.write("{\r\n");
		fw.write("void show(){.....}");
		fw.write("\r\n}");

		fw.close();

		FileReader fr=new FileReader(args[0]);
		char[] arr=new char[1024];
		for(int count=fr.read(arr);count!=-1;count=fr.read(arr))
		{
			System.out.print(count+":::"+new String(arr,0,count));
		}
		fr.close();
	}
}
运行图:

/*
FileWriter的基本方法(构造函数,write,close,flush)
IOException的基本处理流程
*/
package com.helong.filewriterdemo;
import java.io.*;
class FileWriterDemo 
{
	public static void main(String[] args) 
	{

		FileWriter fw=null;

		try
		{
			fw = new FileWriter("Demo.txt");

			fw.write("使用FileWriter类创建文件并写入这句话!\n\t");
			fw.write("  ..........再写一句把");
		}
		catch (IOException e)
		{
			System.out.println("构造函数或者write方法:"+e.toString());
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();
			}
			catch (IOException e)
			{
				System.out.println("close方法:"+e.toString());
			}
			
		}
		
	}
}
运行图:



//文件读取方式1
package com.helong.filereaderdemo;
import java.io.*;
class FileReaderDemo 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("Demo.txt");

		for(int ch=fr.read();ch!=-1;ch=fr.read())
		{
			System.out.print((char)ch);
		}

		fr.close();
	}
}
运行图:



//文件读取方式2,以数组形式
package com.helong.filereaderdemo2;
import java.io.*;
class FileReaderDemo2 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr =new FileReader("Demo.txt");
		char[] arr=new char[1024];//通常数组大小设置为1024的整数倍
		for(int count=fr.read(arr);count!=-1;count=fr.read(arr))
		{
			System.out.println(count+":::"+new String(arr,0,count));
		}
		fr.close();
	}
}

运行图:



2.字符流缓冲区对象

在没有缓冲区之前,我们总是将数据一个字节一个字节的传入目的地,这样效率非常低,而 缓冲区对象的出现解决了这个问题,它就好像是一个蓄水池,水(数据)不再是直接流入目的地,而是先流到蓄水池中,当蓄水池中水满了,再一次性运到目的地中。这样,就 减少了频繁的硬盘与内存的交互,提高了效率。同时我们知道蓄水池的出现就是为了水服务的,也就是说先有水后有了蓄水池,因此 当我们创建一个蓄水池时,必须传入水流作为参数


缓冲区对象:

BufferedWriter:有了这个类我们可以将一个FileWriter对象作为参数传给该类对象,再操作流时就可以使用该缓冲区对象的方法来提高效率了。
特别方法newLine():我们知道,在不同操作系统下,换行是由不同符号代替的,例如windows下为"\r\n",linux下为"\n",因此我们编写IO程序时,对于这个问题非常麻烦,要判断是哪个操作系统,再决定使用哪一种换行,而缓冲区对象提供了newLine方法,该方法是跨平台的换行,我们使用更加方便。
BufferedReader:对应BufferedWriter的类。
特别方法readLine():读取一行数据,内部是调用FileReader的read方法,读取一行的数据但是不包括回车换行符。

装饰设计模式:

我们发现,其实BufferedWriter相对于FileWriter来说,功能基本一致,无非就是在效率,方便等方面更好了,而且在BufferedWriter方法,内部也大量的使用到了FileWriter的方法,这使得我们很疑惑,BufferedWriter在体系中与FileWriter是平行的,但是它更像是FileWriter的加强版,而不是一个独立的类,其实当我们看到BufferedWriter的构造函数时我们也会有所察觉,这个类是没有空参数构造函数的,创建该类对象,必须传递一个FileWriter对象进来,这是什么做法呢?我们不得不提一种设计模式:装饰设计模式。

当想要对已有的类进行增强时,将已有类的对象传入自定义的类中,并基于已有类方法提供增强版方法。这个新的类就是已有类的装饰类。因为当我们想增强一个类时,不建议修改其源代码,因此一般都会使用装饰类。装饰类一般通过构造函数接收被装饰的对象,基于被装饰对象的方法提供更强功能

特点:

1.包含被装饰类的一个对象。

2.一般无空参数构造函数,那个对象也是通过构造函数传递给该类的。

3.基于对象的方法,提供增强的方法。

装饰与继承的区别:

细心的朋友会发现,这个所谓的增强版的类貌似使用继承也可以啊,我们可以设计一个类,该类继承于FileWriter,复写增强其中我们想要增强的方法,提供更高效率,更方便的方法,这不也能解决问题吗?那我们为什么要多此一举搞个装饰类出来呢?

我们来仔细分析一下:

例如此时有一个类MyReader,其有两个子类MyFileReader,MyTextReader,我们发现这两个子类的读取方法效率不高,想提高它的效率怎么办呢?改源代码是不可能的,以前我们可能会说定义新的类继承这两个子类,然后复写其中需要提高效率的方法就可以了。

这样做也不是不可以,体系如下:

MyReader:

|--MyFileReader

|--MySuperFileReader

|--MyTextReader

|--MySuperTextReader

我们发现,这样的解决方式虽然也能解决问题,但是会使得该体系过于臃肿,如果还有别的子类,那就还要再定义类,而且灵活性不强,扩展性极差我们再来看看使用装饰设计模式来解决这个问题

MyReader

|--MyFileReader

|--MyTextReader

|--MySuperReader

class MySuperReader extends MyReader
{
MySuperReader(MyReader r)//利用多态,可以处理所有MyReader的子类对象
{}
//基于MyReader的方法,提供对应的增强方法。
}

我们发现,这种方式的好处在于,1.扩展性强,2.代码简洁,3.灵活性强,如果有方法不想增强的可以直接使用传入对象的原方法。

缓冲区对象练习:

//使用缓冲区对象来提高FileWriter的效率
//写入99乘法表
import java.io.*;
class BufferedWriterDemo 
{
	public static void main(String[] args) throws IOException
	{
		//使用蓄水池前肯定要有个水流吧
		FileWriter fr=new FileWriter("buff.txt");
		BufferedWriter bw=new BufferedWriter(fr);

		for(int i=1;i<=9;i++)
		{
			for(int j=1;j<=i;j++)
			{
				bw.write(j+"*"+i+"="+(i*j)+"\t");
			}
			bw.newLine();
			bw.flush();//每次都刷新是为了防止程序突然停止后数据没有能写入硬盘中,例如写BLOG时,一般都是每隔10秒就存一次的,这是一个道理
		}
		bw.close();
	}
}
运行图:



//使用BufferedReaderDemo对象提高读取的效率
import java.io.*;
class BufferedReaderDemo 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr=new FileReader("buff.txt");
		BufferedReader br=new BufferedReader(fr);
		for(String line=br.readLine();line!=null;line=br.readLine())
		{
			System.out.println(line);
		}
		br.close();
	}
}
运行图:



练习装饰设计模式:

//装饰设计模式:自定义一个类,该类中包含被装饰类对象,基于该对象的方法,提供更好更强的方法
class Person
{
	void eat()
	{
		System.out.println("吃白饭");
	}
	void play()
	{
		System.out.println("玩泥巴");
	}
}
class SuperPerson
{
	private Person p;
	SuperPerson(Person p)
	{
		this.p=p;
	}
	void eat()
	{
		p.eat();
		System.out.println("吃牛肉");
		System.out.println("吃鸡肉");
		System.out.println("吃鱼肉");
	}
	void play()
	{
		p.play();
		System.out.println("玩电脑");
		System.out.println("玩手机");
		System.out.println("玩平板");
	}
}
class DecorationDemo 
{
	public static void main(String[] args) 
	{
		SuperPerson sp=new SuperPerson(new Person());
		sp.eat();
		sp.play();
	}
}
运行图:


//使用装饰设计模式
abstract class Animal
{
	abstract void eat();
	abstract void sleep();
	abstract void play();
	abstract void work();
}
class Cat extends Animal
{
	void eat()
	{
		System.out.println("吃鱼");
	}
	void sleep()
	{
		System.out.println("趴着睡");
	}
	void play()
	{
		System.out.println("玩毛线");
	}
	void work()
	{
		System.out.println("抓老鼠");
	}
}
class Dog extends Animal
{
	void eat()
	{
		System.out.println("吃骨头");
	}
	void sleep()
	{
		System.out.println("躺着睡");
	}
	void play()
	{
		System.out.println("玩飞盘");
	}
	void work()
	{
		System.out.println("看门");
	}
}
class SuperAnimal
{
	private Animal a=null;
	SuperAnimal(Animal a)
	{
		this.a=a;
	}
	void eat()
	{
		a.eat();
		System.out.println("还会自己收拾哦");
	}
	void sleep()
	{
		a.sleep();
		System.out.println("而且不打呼噜哦");
	}
	void play()
	{
		a.play();
		System.out.println("和主人一起玩哦");
	}
	void work()
	{
		a.work();
	}
}
class DecorationDemo2 
{
	public static void main(String[] args) 
	{
		SuperAnimal sa=new SuperAnimal(new Cat());
		sa.eat();
		sa.sleep();
		sa.play();
		sa.work();

		sa=new SuperAnimal(new Dog());
		sa.eat();
		sa.sleep();
		sa.play();
		sa.work();
	}
}

运行图:



IO异常的一种处理方式:

/*
将异常信息存放到特定的文件中
*/
import java.io.*;
import java.util.*;
import java.text.*;
class ExceptionInfoHandle
{
	public static void rememberExceptionInfo(String info)throws IOException
	{
		Date d=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		String date=sdf.format(d);
		/*//方法1*/
		BufferedWriter bw=new BufferedWriter(new FileWriter("ExceptionInfo.txt",true));
		bw.write(date);
		bw.newLine();
		bw.write(info);
		bw.newLine();
		bw.newLine();
		bw.flush();
		

		/*//方法2
		
		System.setOut(new PrintStream(new FileOutputStream("ExceptionInfo.txt",true)));
		System.out.println(date);
		System.out.println(info);
		System.out.println();*/
	}
}
class ExceptionInfo 
{
	public static void main(String[] args) throws IOException
	{
		try
		{
			int a=12/0;
		}
		catch (Exception e)
		{
			ExceptionInfoHandle.rememberExceptionInfo(e.toString());
		}

		try
		{
			int[] arr=new int[2];
			System.out.println(arr[3]);
		}
		catch (Exception e)
		{
			ExceptionInfoHandle.rememberExceptionInfo(e.toString());
		}
	}
}
运行图:


手写实现BufferedReader的readLine和close方法:

//自己实现BufferedReader的readLine和close功能
//思路:其实BufferedReader内部的readLine方法也是在调用FileReader的read读取一个字符的方法
import java.io.*;
class MyBufferedReader
{
	private FileReader fr=null;
	MyBufferedReader(FileReader fr)
	{
		this.fr=fr;
	}
	public String myReadLine()throws IOException
	{
		//定义一个临时存储数据的容器
		//BufferedReader中使用数组,我们此处使用StringBuilder
		StringBuilder sb=new StringBuilder();
		for(int ch=fr.read(),temp;ch!=-1;ch=fr.read())
		{
			//如果文件中有单独的\r或者\n,那么将被跳过
			//if(ch=='\r')continue;
			//if(ch=='\n')return sb.toString();//'\n'表示读到了一行的结尾处,因此返回字符串
			if(ch=='\r')
			{
				if((temp=fr.read())=='\n')//连续的'\t''\n'表示这是个换行符
					return sb.toString();
				else//单独的'\t',不是换行符的一部分,也应该存入容器中
				{
					sb.append(ch);
					sb.append(temp);
				}
			}
			else
				sb.append((char)ch);
		}
		if(sb.length()!=0)return sb.toString();
		return null;
	}
	public void myClose()throws IOException
	{
		fr.close();
	}

}
class MyBufferedReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr=new FileReader("buff.txt");
		MyBufferedReader mbr=new MyBufferedReader(fr);
		for(String line=mbr.myReadLine();line!=null;line=mbr.myReadLine())
		{
			System.out.println(line);
		}
	}
}
运行图:



3.字节流

使用字节流写入数据是不需要刷新的当然也是需要关闭资源的),这是因为字节流是一个字节一个字节的操作数据,因此不会放到流中,而是直接放到目的地,而字符流不同,由于一个字符是两个字节,因此它要先把一个字节放到流中,等下一个字节来时,凑成一个字符再写入目的地
字节流体系:
InputStream:读
|--FileInputStream
|--BufferedInputStream
OutputStream:写
|--FileOutputStream
|--BufferedOutputStream


常用子类:

FileOutputStream:写入单个字节或者字节数组。将其他要写的数据转换成字节数组,例如"helong".getBytes()
FileInputStream:available()方法返回剩下的可操作的估计字节数。使用该方法返回值定义数组大小。
问题:如果文件过大,那么使用该方法返回值创建数组时会内存溢出。
两个装饰类:BufferedOutputStream,BufferedInputStream。

两个方法的特点:

int read(),write(int)特点:我们使用read来读取数据时,每次虽然只读取一个字节,但是却返回一个int变量,这是为什么呢
原因:由于使用字节流对象可能读取到任何数据(文字,图片,音乐等) ,例如1111-1111,因为像这样的一个字节的值换成十进制为-1,如果直接就返回这个字节,那么在外面判断时就会误以为已经读完了数据。这是不对的,因此java的做法是将一个byte提升为int,但是如果直接提升的话,那结果就变成了1111-1111 1111-1111 1111-1111 1111-1111这样,可是我们发现这个结果还是-1,因此我们的目的是保留后八位的同时,将前面全部补0,因此我们将这个结果&255,来保留后八位
而对于write来说,虽然参数是一个int,但是我们都知道在这个int中,只有后八位是我们需要的,而前八位是补的0,因此write是做了强转动作来只取后八位的。

转换流:

InputStreamReader:传入一个字节流对象,得到一个字符流对象,这样就可以使用字符流缓冲区对象的方法了,例如BufferedReader.readLine()
OutputStreamWriter:传入一个字节流输出对象(例如:System.out),得到一个字符流输出写对象
出现转换流的原因:我们知道FileReader处理纯文本文件的读取操作,而FileReader是InputStreamReader的子类,这其实表示用InputStreamReader也能处理纯文本文件的读取,只是需要指定流和编码方式比较麻烦,而FileReader则不需要指定流,且默认采用GBK编码表,但是这也是它的局限性,不能处理UTF-8编码的文件

转换流特有功能:转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符


键盘录入(最简写法):

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

键盘录入练习:

//键盘录入
import java.io.*;
class ReadIn 
{
	public static void main(String[] args) throws IOException
	{
		InputStream in=System.in;
		while(true)
		{
			StringBuffer sb=new StringBuffer();
			for(int ch=in.read();ch!='\r'&&ch!='\n';ch=in.read())
			{
				sb.append((char)ch);
			}
			in.read();
			if(sb.toString().equals("over"))
				break;
			else
				System.out.println(sb.toString().toUpperCase());
		}
	}
}
运行图:

控制台输出:

BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

字节流练习:

//测试FileOutputStream和FileInputStream使用
import java.io.*;
class FileStream 
{
	public static void main(String[] args) throws IOException
	{
		input_3();
	}
	private static void input_1()throws IOException
	{
		FileInputStream fis=new FileInputStream("FileStream.txt");
		for(int ch=fis.read();ch!=-1;ch=fis.read())//一个字节一个字节的读数据
		{
			System.out.print((char)ch);
		}
		fis.close();
	}
	private static void input_2()throws IOException
	{
		FileInputStream fis=new FileInputStream("FileStream.txt");
		byte[] buf=new byte[1024];
		for(int len=fis.read(buf);len!=-1;len=fis.read(buf))//一次性读多个字节,然后一起操作
		{
			System.out.println(new String(buf,0,len));
		}
		fis.close();
	}
	private static void input_3()throws IOException
	{
		FileInputStream fis=new FileInputStream("FileStream.txt");
		byte[] buf=new byte[fis.available()];
		fis.read(buf);
		System.out.println(new String(buf));
		fis.close();
	}
	private static void output_1()throws IOException
	{
		FileOutputStream fos=new FileOutputStream("FileStream.txt");
		fos.write("helong is so handsome!\r\nmuhhhhh".getBytes());
		fos.close();//即便没有刷新,也会将数据写入目的地,这是因为字节流操作的是字节这种最小单元,因此不需要有中间处理,直接就存到了目的地。
	}
}
运行图:


//转换流练习
import java.io.*;
class TranslateStream 
{
	public static void main(String[] args) throws IOException
	{
		
		//数据源
		//BufferedReader br=new BufferedReader(new InputStreamReader(System.in/*数据源是标准输入,也就是键盘*/));
		BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("trans.txt")/*数据源是标准输入,也就是键盘*/));

		//目的地
		BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out/*目的地是控制台*/));
		//BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("trans.txt")/*目的地一个文件夹*/));

		for(String line=br.readLine();line!=null;line=br.readLine())
		{
			if(line.equals("over"))break;
			bw.write(line.toUpperCase());
			bw.newLine();
			bw.flush();
		}
		br.close();
		bw.close();
	}
}
运行图:

复制图片:
//复制一张图片
/*
思路:
1.以字节形式读取该图片FileInputStream
2.创建一个对应格式的图片文件到目的地FileOutputStream
3.循环读写
4.关闭资源
*/
import java.io.*;
class CopyPic 
{
	public static void main(String[] args)
	{
		FileInputStream fis=null;
		FileOutputStream fos=null;
		try
		{
			fis=new FileInputStream("使用缓冲区对象读取数据.png");
			fos=new FileOutputStream("使用缓冲区对象读取数据(2).png");
			byte[] buf=new byte[1024];
			for(int len=fis.read(buf);len!=-1;len=fis.read(buf))
			{
				fos.write(buf,0,len);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("复制图片失败");
		}
		finally
		{
			try
			{
				if(fis!=null)fis.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取流关闭失败");
			}
			try
			{
				if(fos!=null)fos.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入流关闭失败");
			}
		}
	}
}

运行图:



4.流操作基本流程

1.找到源流对象,进行包装----InputStream,Reader
2.找到目的流对象,进行包装----OutputStream,Writer
3.操作的数据是否为纯文本----决定使用字符流还是字节流
4.通过设备确定使用的具体对象(源设备:内存,硬盘,键盘。目的设备:内存,硬盘,控制台)
5.是否需要提高效率,是就使用包装类
使用流操作流程解决问题:
//将文本文件打印到控制台上,使用三个明确的流程
import java.io.*;
class TranslateStreamTest 
{
	public static void main(String[] args) throws IOException
	{
		/*
		明确源:
		1.源:文本文件
		2.纯文本:Reader
		3.设备:硬盘--FileReader
		*/
		BufferedReader br=new BufferedReader(new FileReader("根据步骤分析流操作.txt"));

		/*
		明确目的:
		1.目的:控制台
		2.纯文本:Writer,字符流对象
		3.设备:控制台,System.out字节流对象(需要转换,将字节流对象转为字符流对象,需要转换流)
		*/
		BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

		for(String line=br.readLine();line!=null;line=br.readLine())
		{
			bw.write(line);
			bw.newLine();
		}
		bw.close();
		br.close();
	}
}




------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值