IO流
1.IO流用来处理设备之间的数据传输
2.Java对数据的操作都是通过流的方式
字节流
字节流的抽象基类:InputStream,OutputStream
字节读取流 常用子类:FileInputStream
常用读取方法:
1.定义大小刚好的缓冲区
byte[] buf=new byte[fis.available()];//available()返回流中的字节数
//定义一个刚刚好的缓冲区,不用再循环了
2.读取–标准方式
public static void readFile_2() throws IOException//字符串读取--标准方式
{
FileInputStream fis=new FileInputStream("fos.txt");
byte[] buf=new byte[1024];
int ch=0;
while((ch=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,ch));
}
fis.close();
}
字节写入流 常用子类:FileOutputStream
OutputStream:不需要刷新,进一个字节,写入一个字节,但是需要关闭资源。
写入方法:
public static void writeFile() throws IOException
{
FileOutputStream fos=new FileOutputStream("fos.txt");//写入
fos.write("abcde".getBytes());//字符串转成字节数组
fos.close();
}
字节流缓冲区+案例
写入流缓冲区:BufferedOutputStream
读取流缓冲区:BufferedIntputStream
字节流缓冲区复制MP3的例子
import java.io.*;
/*
演示MP3的赋值,通过缓冲区
BufferedOutputStream
BufferedIntputStream
*/
public class CopyMp3 {
public static void main(String[] args)throws IOException
{
copy_1();
}
public static void copy_1()throws IOException
{
BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("Demo.mp3"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("Demo2.mp3"));
int len;
while((len=bufis.read())!=-1)
{
bufos.write(len);
}
bufis.close();
bufos.close();
}
}
自定义字节数组复制图片的例子
package 黑马IO流;
/*
复制一个图片
思路:
1.用字节读取流对象和图片关联。
2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
3.通过循环读写,完成数据的存储。
4.关闭资源
*/
import java.io.*;
public class Copypic {
public static void main(String[] args) {
FileOutputStream fos=null;//写入流
FileInputStream fis=null;//读取流
try
{
fis=new FileInputStream("Demo.jpg");
fos=new FileOutputStream("imageDemo.jpg");
byte[] buf=new byte[1024];//缓冲区
int len;
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
try
{
fis.close();
}
catch(IOException e)
{
throw new RuntimeException("关闭读取流失败");
}
try
{
fos.close();
}
catch(IOException e)
{
throw new RuntimeException("关闭写入流失败");
}
}
}
}
字符流
字符流的抽象基类:Reader,Writer
字符读取流 常用子类:FileReader
文本文件读取方式一:
//创建一个文件读取流对象,和指定名称的文件相关联
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
FileReader fr=new FileReader("Demo.txt");
//调用读取流对象的read方法,返回int类型
//read():一次读一个字符,而且会自动往下读,直到-1
int ch=0;
while((ch=fr.read())!=-1) {
System.out.print((char)ch);
}
文本文件读取方式二:read(cahr[])
FileReader fr=new FileReader("Demo.txt");
//定义一个字符数组,用于存储到字符
//该read(char[])返回的是读到字符的个数
char[] buf=new char[1024];
int num=0;
while((num=fr.read(buf))!=-1) {
System.out.println(new String(buf,0,num));
}
字符写入流 常用子类:FileWriter
写入操作:需要刷新流
//创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件
//而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖
//其实该布就是在明确数据要存放的目的地。
FileWriter fw=new FileWriter("Demo.txt");
//调用write方法,将字符串写入流缓冲中
fw.write("abcde");
//刷新流对象中的缓冲中的数据
//将数据刷到目的地中。
fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中数据
//将数据刷到目的地中。
//和flush的区别:flush刷新后,流可以继续使用
2.演示对已有文件的续写:
传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾进行数据编写
fw=new FileWriter("demo.txt",true);
字符流缓冲区+案例
缓冲区的出现是为了提高流的操作效率而出现的,
所以在创建缓冲区之前,必须要先有流对象。
关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();
1.字符写入流缓冲区:
BufferedWriter bufw=new BufferedWriter(fw);
该缓冲区中提供了一个跨平台的换行符。
newLine();
2.字符读取流缓冲区
BufferedReader bufr=new BufferedReader(fr);
该缓冲区中提供了一个一次读一行的方法:
readLine();//当返回null的时候。表示读到文件末尾
//readLine()方法返回的时候只返回回车符之前的数据内容,并不返回回车符
3. BufferedReader的子类LineNumberReader
特殊方法:可以设置行号:Inr.setLineNumber(0);//设置起始行号1
获取行号:Inr.getLineNumber()
通过缓冲区复制一个.java文件案例
package 黑马IO流;
import java.io.*;
//通过缓冲区复制一个.java文件
public class CopyTextByBuf {
public static void main(String[] args) {
BufferedReader bufr=null;
BufferedWriter bufw=null;
try
{
bufr=new BufferedReader(new FileReader("D:\\\\JAVA学习\\\\src\\\\黑马\\\\RunTimeDemo.java"));
bufw=new BufferedWriter(new FileWriter("RunTimeDemo_copy.txt"));
String line=null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch(IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e)
{
throw new RuntimeException("读取流关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch(IOException e)
{
throw new RuntimeException("写入流关闭失败");
}
}
}
}
LineNumberReader案例
package 黑马IO流;
//BufferedReader的子类LineNumberReader
import java.io.*;
public class LineNumberReaderDemo {
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("buf.txt");
LineNumberReader Inr=new LineNumberReader(fr);
String line=null;
Inr.setLineNumber(0);//设置起始行号1
while((line=Inr.readLine())!=null)
{
System.out.println(Inr.getLineNumber()+":"+line);
}
Inr.close();
}
}
运行结果
流操作的基本规律+读取转换流
1.明确源和目的
源 :输入流。InputStream Reader
目的:输出流。OutputStream Writer
2.操作的数据是否是纯文本
是:字符流。
不是:字节流。
3.当体系明确后,在明确要使用哪个具体的对象。
通过设备来区分:
源设备:内存,硬盘,键盘,
目的设备:内存,硬盘,控制台。
—读取键盘录入
System.out:对应的是标准输出设备,控制台。
System.in: 对应的是标准输入设备,键盘。
— 改变标准输入输出设备
System.setIn(InputStream in);
System.setOut(PrintStream out)
–读取转换流:
读取转换流 InputStreamReader
1.键盘录入(读取)最常见写法
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
写入转换流 OutputStreamWriter
2.写入文件,常见写法
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“trans.txt”)));
学生信息录入硬盘小程序
package 黑马IO流;
/*
有五个学生,每个学生有三门课的成绩
从键盘输入以上数据,输入格式:zhangsan,30,40,60计算出总成绩
并把学生的信息和计算出的总分数按高低顺序存放在磁盘文件"studentinfo.txt"中
1.描述学生对象
2.定义一个可操作学生对象的工具类(读取,写入)
思想:
1.通过获取键盘录入一行数据,并将改行中的信息取出封装成学生对象。
2.因为学生有很多,那么就需要存储,使用到集合,
因为要对学生的总分排序,所以可以使用TreeSet.
3.将集合的信息写入到一个文件中。
*/
import java.io.*;
import java.util.*;
public class StudentInfoTest {
public static void main(String[] args) throws IOException
{
Comparator<Student> cmp=Collections.reverseOrder();//强行逆转比较器
Set<Student> stus=StudentInfoTool.getStudent(cmp);
StudentInfoTool.writeToFile(stus);
}
}
class Student implements Comparable<Student>
{
private String name;
private int ma,cn,en;
private int sum;
public int compareTo(Student s)
{
int num=new Integer(this.sum).compareTo(new Integer(s.sum));//比较大小。进行排序
if(num==0)
return this.name.compareTo(s.name);
return num; //实现的是自然顺序
}
Student(String name,int ma,int cn,int en)
{
this.name=name;
this.ma=ma;
this.cn=cn;
this.en=en;
sum=ma+cn+en;
}
public String getName()
{
return name;
}
public int getSum()
{
return sum;
}
public int hashCode()//如果存入的hash集合中就需要复写hashCode()和equals()
{
return name.hashCode()+sum*38;//当姓名和年龄一样时进行equals比较
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s=(Student)obj;
return this.name.equals(s.name) && this.sum==s.sum;
}
public String toString()
{
return "student["+name+","+ma+","+cn+","+en+"]";
}
}
class StudentInfoTool
{
public static Set<Student> getStudent()throws IOException
{
return getStudent(null);//获取自然排序的集合的方法
}
public static Set<Student> getStudent(Comparator<Student> cmp)throws IOException
{//获取含比较器的集合的方法
BufferedReader bufr=
new BufferedReader(new InputStreamReader(System.in));//输入流
String line=null;
Set<Student> stus=null;
if(cmp==null)
stus=new TreeSet<Student>();
else
stus=new TreeSet<Student>(cmp);
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
String[] arr=line.split(",");
Student stu=new Student(arr[0],Integer.parseInt(arr[1]),
Integer.parseInt(arr[2]),
Integer.parseInt(arr[3]));
stus.add(stu);
}
bufr.close();
return stus;
}
public static void writeToFile(Set<Student> stus)throws IOException
{
//输出流
BufferedWriter bufw=new BufferedWriter(new FileWriter("StudentInfo.txt"));
for(Student stu:stus)
{
bufw.write(stu.toString()+"\t");
bufw.write(stu.getSum()+"");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}