Java基础——IO流
来源:互联网 发布:指南针软件好用吗 编辑:程序博客网 时间:2024/05/16 10:28
1、IO流
IO流:输入、输出流(针对的是内存和外围设备(硬盘)的数据交换)
外围设备到内存:输入(读)
内存到外围设备:输出(写)
字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先指定的编码表,获取对应的文字
再对这个文字进行操作。简单的说:字节流+编码表。
字节流的两个顶层父类:
1、InputStream
2、OutputStream
字符流的两个顶层父类:
1、Reader
2、Writer
如果要操作文字数据,优先考虑字符流,将数据从内存写到硬盘上,要使用字符流中的输出流:Writer
字符流缓冲区:
BufferWriter
newLine():加入换行符
BufferReader
readLine():读取文本的一行
2、字符流的操作代码示例
2.1字符流读写操作
读操作
package cn.itcast.p2.io.filewriter;//读文件的第一种方式import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub// 1、创建读取字符数据的流对象 /* * 在创建读取流对象时,必须要明确被读取的文件,一定要确定该文件是存在的 * 用一个读取流关联一个已存在文件 * * * */ FileReader fr=new FileReader("demo.txt"); int ch;// 用Reader中的read方法读取字符// int ch=fr.read();//每次只读取一个字符,而且是二进制(因为存在磁盘上的都是二进制格式的,由于前面int限制,所以返回的十进制数)// System.out.println(ch);//结果:97,读完之后返回的是-1 while((ch=fr.read())!=-1) { System.out.println((char)ch); } }}
package cn.itcast.p2.io.filewriter;//读文件的第二种方式import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderDemo2 { public static void main(String[] args) throws IOException { FileReader fr=new FileReader("demo.txt"); /*使用read(char[])读取文本文件数据 * 先创建字符数组 * * */ /*char[]buf=new char[6]; int num=fr.read(buf);//返回读取到字符数,并把字符存储到buf数组中 System.out.println(num+":"+new String(buf));//结果:6:abcd(后面有两空格) int num1=fr.read(buf); System.out.println(num1+":"+new String(buf));//结果:6:adfalx(会把之前的覆盖掉) int num2=fr.read(buf); System.out.println(num1+":"+new String(buf));//6:ixixlx int num3=fr.read(buf); System.out.println(num3+":"+new String(buf));//-1:ixixlx(当读到-1直接返回)*/ char[]buf=new char[1024];//一般设置1024的整数倍,以免反复执行下面的语句,提高效率 int len; while((len=fr.read(buf))!=-1) { System.out.println(new String(buf,0,len)); } }}
写操作
package cn.itcast.p2.io.filewriter;//写文字到硬盘import java.io.FileWriter;import java.io.IOException;public class FileWriterDemo { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //创建一个可以往文件中写入字符数据的字符输出流对象 /* * 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地) * 如果文件不存在,则会自动创建 * 如果文件存在,则会被覆盖 * * */// FileWriter fw=new FileWriter("demo.txt");// 如果构造函数中加入true,可以实现对文件进行续写 FileWriter fw=new FileWriter("demo.txt",true); /* * 调用Writer对象中的write(string)方法,写入数据 * 其实数据写入到临时存储缓冲区中 * */// fw.write("abcde"); fw.write("abcd"+LINE_SEPARATOR+"adfal");//加入换行符 fw.write("xixix");//续写入文件 /* * 进行刷新,将数据直接写到目的地中 * */ fw.flush(); /* * 关闭流,关闭资源,在关闭流的时候会先调用flush刷新缓冲区中的数据到目的地 * */ fw.close(); }}
2.1.1 读写实例代码
package cn.itcast.p2.io.filewriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextTest { /* * 将C盘中的一个文件复制到D盘 * 思路: * 1、需要读取源 * 2、将读到的原数据写入到目的地 * 3、既然是操作文本数据,使用字符流 * */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //1、读取一个已有的文本文件,使用字符读取流和文件相关联 FileReader fr=new FileReader("笔记.txt"); //2、创建一个目的地,用于存储读到数据 FileWriter fw=new FileWriter("copytext_1.txt"); //3、频繁的读写操作 int ch=0; while((ch=fr.read())!=-1) { System.out.println(ch); fw.write(ch); } //4、关闭流资源 fw.close(); fr.close(); }}
读写异常捕捉
package cn.itcast.p2.io.filewriter;//异常处理import java.io.FileWriter;import java.io.IOException;public class IOExceptionDemo { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); public static void main(String[] args) { // TODO Auto-generated method stub FileWriter fw=null;//在外面声明 try { fw = new FileWriter("demo.txt");//在里面初始化 位置1 fw.write("abcd" + LINE_SEPARATOR + "adfal");//加入换行符 位置2 } catch (IOException e) { // TODO: handle exception System.out.println(e.toString()); }finally { if(fw!=null)//需要判断它是否为空才能进行下面的fw.close()操作,因为位置1抛出异常时(路径不存在),fw就不存在,为此它也会抛异常 //当有限制时,就可以很明确的捕捉到是否是位置2发生写入异常 try { fw.close();//如果不再外面声明,此处就会报错,fw变量没被定义 } catch (IOException e) { // TODO Auto-generated catch block throw new RuntimeException("关闭失败"); }// } }}
package cn.itcast.p2.io.filewriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextTest_2 { private static final int BUFFER_SIZE = 1024; public static void main(String[] args) { // TODO Auto-generated method stub FileReader fr=null; FileWriter fw=null; try { fr=new FileReader("笔记.txt"); fw=new FileWriter("copytest_2.txt"); //创建一个临时容器,用于缓存读取到的字符 char[] buf=new char[BUFFER_SIZE]; //定义一个变量记录读取到的字符数(其实就是往数组里装的字符个数) int len=0; while((len=fr.read(buf))!=-1) { fw.write(buf, 0, len); } } catch(Exception e) { throw new RuntimeException("读写失败"); }finally { if(fw!=null) try { fw.close(); }catch(IOException e) { } if(fr!=null) try { fr.close(); }catch(IOException e){ } } }}
获取文本的行号
package cn.itcast.p2.io.wrapper;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;public class LineNumberReaderDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub FileReader fr=new FileReader("笔记.txt"); LineNumberReader lnr=new LineNumberReader(fr); String line=null;// lnr.setLineNumber(100);//设置文本开始行 while((line=lnr.readLine())!=null) { System.out.println(lnr.getLineNumber()+":"+line);//获取文本的行号 } lnr.close(); }}
2.2字符流缓冲区读写操作
package cn.itcast.p2.io.charstream.test;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextByBufTest { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub FileReader fr=new FileReader("buf.txt"); BufferedReader bufr=new BufferedReader(fr); FileWriter fw=new FileWriter("buf_copy2.txt"); BufferedWriter bufw=new BufferedWriter(fw); String line=null; //按行读写 while((line=bufr.readLine())!=null) { bufw.write(line); bufw.newLine(); bufw.flush(); } /*int ch=0; while((ch=bufr.read())!=-1) { bufw.write(ch); }*/ bufw.close(); bufr.close(); }}
package cn.itcast.p2.io.charstream.test;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;public class BufferWriterDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub FileWriter fw=new FileWriter("buf.txt"); //为了提高写入的效率,使用了字符流的缓冲区 //创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联 BufferedWriter bufw=new BufferedWriter(fw); //使用缓冲区的写入方法将数据先写入到缓冲区中 bufw.write("abcd"); bufw.newLine();//写入换行符(只是缓冲区对象有),封装的是System.getProperty("line.separator") bufw.write("afhsdnajkl"); //使用缓冲区的刷新方法将数据刷到目的地中 bufw.flush(); //关闭缓冲区的(其实关闭的就是被缓冲的流对象) bufw.close(); }}
package cn.itcast.p2.io.charstream.test;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class BufferedReaderDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub demo(); FileReader fr=new FileReader("buf.txt"); BufferedReader bufr=new BufferedReader(fr); String line=null; while((line=bufr.readLine())!=null) { System.out.println(line);//读取文本的一行 } bufr.close(); } private static void demo() throws IOException { // TODO Auto-generated method stub FileReader fr=new FileReader("buf.txt"); char[]buf=new char[1024]; int len=0; while((len=fr.read(buf))!=-1) { System.out.println(new String(buf,0,len)); } fr.close(); }}
2.2.1自定义缓冲区
自定义类
package cn.itcast.p2.io.charstream.mybuffer;import java.io.FileReader;import java.io.IOException;/* * 自定义的读取缓冲区,其实就是模拟一个BufferedReader * 分析: * 缓冲区中无非就是封装了数组 * 并对外提供了更多的方法对数组进行访问 * 其实这些方法最终操作的都是数组的角标 * * 缓冲的原理: * 其实就是从源中获取一批数据装进缓冲区中 * 再从缓冲区中不断的取出一个一个数据 * * 在此次取完后,再从源中继续取一批数据进缓冲区 * 当源中的数据取光时,用-1作为结束标记 * */public class MyBufferReader { private FileReader r; //定义一个数组作为缓冲区 private char[]buf=new char[1024]; //定义一个指针用于操作这个数组中的元素,当操作到最后一个元素后,指针归零 private int pos=0; //定义一个计数器用于记录缓冲区中的数据个数,当该数据减到0,就从源中继续获取数据到缓冲区中 private int count=0; MyBufferReader(FileReader r) { this.r=r; } /* * 该方法从缓冲区中一次取一个字符 * * */ public int myRead() throws IOException { if(count==0) { count=r.read(buf); } if(count<0) return -1; char ch=buf[pos++]; count--; return ch; /*//1、从源中获取一批数据到缓冲区中,需先做判断,只有计数器为0时,才需要从源中获取数据 if(count==0) { count=r.read(buf); if(count<-1) return -1; //每次获取数据到缓冲区后,角标归零. pos=0; char ch=buf[pos]; pos++; count--; return ch; }else if(count>0) { char ch=buf[pos]; pos++; count--; return ch; }*/ } public String myReadLine() throws IOException { StringBuilder sb=new StringBuilder(); int ch=0; while((ch=myRead())!=-1) { if(ch=='\r') continue; if(ch=='\n') return sb.toString(); sb.append((char)ch); } if(sb.length()!=0)//没有这个的话,如果最后一行后面没有回车则最后一行打印不出来 return sb.toString(); return null; } public void myClose() throws IOException { r.close(); }}
自定义缓冲区应用
package cn.itcast.p2.io.charstream.mybuffer;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class MyBufferedReaderDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub// demo(); FileReader fr=new FileReader("buf.txt"); MyBufferReader bufr=new MyBufferReader(fr); String line=null; while((line=bufr.myReadLine())!=null) { System.out.println(line);//读取文本的一行 } bufr.myClose(); } private static void demo() throws IOException { // TODO Auto-generated method stub FileReader fr=new FileReader("buf.txt"); char[]buf=new char[1024]; int len=0; while((len=fr.read(buf))!=-1) { System.out.println(new String(buf,0,len)); } fr.close(); }}
3、字节流读写操作
3.1 字节流读写示例
package cn.itcast.p2.io.bytestream.demo;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub demo_write(); demo_read(); } private static void demo_read() throws IOException { // TODO Auto-generated method stub //创建一个读取流对象和指定文件关联 FileInputStream fis=new FileInputStream("bytesdemo.txt"); byte[]buf=new byte[fis.available()];//文件长度,少用,万一文件16个G,导致内存溢出 fis.read(buf); System.out.println(new String(buf)); //一次读取一个数组长度,建议使用这种 /*byte[] buf=new byte[1024]; int len=0; while((len=fis.read(buf))!=-1) { System.out.println(new String(buf,0,len)); }*/ /*//一次读取一个字节 int ch=0; while((ch=fis.read())!=-1) { System.out.println((char)ch); }*/ fis.close(); } private static void demo_write() throws IOException { // TODO Auto-generated method stub// 1、创建字节输出流对象,用于操作文件 FileOutputStream fos=new FileOutputStream("bytesdemo.txt");// 2、写数据,直接写入到了目的地中 fos.write("abcddasf".getBytes()); fos.close();//关闭资源动作 }}
3.2 字节流缓冲区读写示例
package cn.itcast.p2.io.bytestream.demo;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class CopyMp3Test { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub copy_1(); copy_2(); }//使用缓冲区复制音频文件 private static void copy_2() throws IOException { // TODO Auto-generated method stub FileInputStream fis=new FileInputStream("0.mp3"); BufferedInputStream bufis=new BufferedInputStream(fis); FileOutputStream fos=new FileOutputStream("2.mp3"); BufferedOutputStream bufos=new BufferedOutputStream(fos); int ch=0; while((ch=bufis.read())!=-1) { fos.write(ch); } bufis.close(); bufos.close(); } private static void copy_1() throws IOException { // TODO Auto-generated method stub FileInputStream fis=new FileInputStream("0.mp3"); FileOutputStream fos=new FileOutputStream("1.mp3"); byte[]buf=new byte[1024]; int len=0; while((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); fis.close(); }}
4 装饰设计模式
装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的增强
装饰和继承都能事项一样的特点:进行功能的拓展。有什么区别呢?
首先有一个继承体系。
writer
|—TextWriter:用于操作文本
|—MediaWriter:用于操作媒体
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展
效率提高需要加入缓冲技术
Writer
|—TextWriter:用于操作文本
|—BufferTextWriter:加入了缓冲技术的操作文本对象
|—MediaWriter:用于操作媒体
|—BufferMediaWriter:
如果这个体系进行功能扩展,有多个流对象
那么这个流要提高效率,是不是也要产生子类呢?这时就会发现只为提高功能进行的扩展
导致继承体系越来越臃肿,不够灵活
既然加入的都是同一种技术—缓冲
前一种是让缓冲和具体的对象相结合
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将那个对象和缓冲关联
class Buffer{
Buffer(TextWriter w)
{}
Buffer(MediaWriter w)
{}
}
装饰类:
class BufferWriter extends Writer{
BufferWriter(Writer w)
{
}
}
Writer
|—TextWriter:用于操作文本
|—MediaWriter:用于操作媒体
|—BufferWriter:用于提高效率
装饰比继承灵活
特点:装饰类和被装饰类都必须所属同一个接口或者父类
举例
package cn.itcast.p2.io.wrapper;public class PersonDemo { public static void main(String[] args) { // TODO Auto-generated method stub Person p=new Person();// p.chifan(); NewPerson p1=new NewPerson(p); p1.chifan(); NewPerson2 p2=new NewPerson2(); p2.chifan(); }}class Person{ void chifan() { System.out.println("吃饭"); }}//这个类的出现是为了增强Person而出现的class NewPerson{ private Person p; NewPerson(Person p){ this.p=p; } public void chifan() { System.out.println("开胃酒"); p.chifan(); System.out.println("甜点"); }}//继承实现Person的增强class NewPerson2 extends Person{ public void chifan() { System.out.println("开胃酒"); super.chifan(); System.out.println("甜点"); }}
5、转换流操作
5.1 字节流和字符流之间的转换(没有使用转换流)
package cn.itcast.p1.transstream.demo;import java.io.IOException;import java.io.InputStream;/* * 读取一个键盘录入的数据,并打印在控制台上 * 键盘本身就是一个标准的输入设备 * 对于Java而言,对于这种输入设备都有对应的对象 * * */public class TransStreamDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub// readKey(); readKey2(); } private static void readKey2() throws IOException { // TODO Auto-generated method stub /* * 获取用户键盘录入的数据 * 并将数据变成大写显示在控制台上 * 如果用户输入的是over,结束键盘录入 * * 思路: * 1、因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串 * 2、那就需要一个容器,StringBuilder * 3、在用户回车之前将录入的数据变成字符串判断即可 * * */// 1、创建容器 StringBuilder sb=new StringBuilder();// 2、获取键盘读取流 InputStream in=System.in;// 3、定义变量记录读取到的字节,并循环获取 int ch=0; while((ch=in.read())!=-1) {// 在存储之前需要判断是否是换行标记,因为换行标记不存储 if(ch=='\r') continue; if(ch=='\n') { String temp=sb.toString(); if("over".equals(temp)) break; System.out.println(temp.toUpperCase()); sb.delete(0, sb.length()); } else// 将读取到的字节存储到StringBuilder中 sb.append((char)ch); } System.out.println(sb); } private static void readKey() throws IOException { // TODO Auto-generated method stub InputStream in=System.in; int ch=in.read();//阻塞式方法,没有数据就一直等 System.out.println(ch);// in.close();//默认的输入设备和输出设备都不需要关闭,一旦关闭则整个// InputStream in=System.in;int ch=in.read();就会报错,这个流就不存在了,它是随着系统的关闭而消失的,系统运行而存在的(除非系统关了重启) }}
5.2 转换流
转换流:
InputStreamReader:字节到字符的桥梁。解码
OutputStreamWriter:字符到字节的桥梁。编码
流的操作规律:
之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。
想要知道开发时用到哪些对象,只要通过四个明确即可。
1、明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2、明确数据是否是纯文本数据
源:是纯文本:Reader
否:InputStream
目的:是纯文本:Writer
否:OutputStream
到这里,就可以明确需求中具体要使用哪个体系
3、明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组(缓冲区)
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4、是否需要其他额外功能
1、是否需要高效(缓冲区);
是,就加上buffer;
例如:
需求1:复制一个文本文件
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体设备
源:
硬盘:File
目的:
硬盘:File
FileReader fr=new FileReader(“a.txt”)
FileWriter fw=new FileWriter(“b.txt”)
4、需要额外功能吗?
需要,需要高效
BufferedReader bufr=new BufferedReader(new FileReader(“a.txt”));
BufferedWriter bufw=new BufferedWriter(new FileWriter(“b.txt”));
需求2:将键盘输入数据存储到硬盘
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体设备
源:
键盘 System.in
目的地:
硬盘 File
InputStream in=System.in
FileWriter fw=new FileWriter(“a.txt”);
这样做可以完成,但是麻烦,将读取的字节数据转成字符串,再由字符流操作
4、需要额外功能吗?
需要。转换将字节流转成字符流。因为明确源是Reader,这样操作文本数据更加便捷
所以要将已有的字节流转成字符流,使用字节—》字符。InputStreamReader
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fw=new FileWriter(“b.txt”);
还需要功能吗?
需要高效!
BufferReader bufr=new BufferReader(new InputStreamReader(System.in));
BufferWriter bufw=new BufferWriter(FileWriter(“b.txt”));
需求3:将一个文本文件数据显示在控制台上
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体的设备
源:
硬盘 File
目的:
控制台 System.out
FileReader fr=new FileReader("b.txt");OutputStream out=System.out;4、是否需要额外功能 需要转换.因为一个汉字是两个字节,输出是一个一个字节的输出转换成字符操作更加便捷 FileReader fr=new FileReader("a.txt"); OutputStreamWriter osw=new OutputStreamWriter(System.out); 需要高效 BufferedReader bfr=new BufferedReader(new FileReader("a.txt")); BufferedReader bfw=new BufferedWriter(new OutputStreamWriter(System.out));
需求4:读取键盘录入数据,显示在控制台上
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer
3、明确设备 源: 键盘 System.in 目的地: 控制台 System.out4、是否需要额外功能? 需要转换,因为都是字节流,但是操作的确实文本数据 所以使用字符流操作起来更为便捷 InputStreamReader isr=new InputStreamReader(System.in); OutputStreamWriter osw=new OutputStreamWriter(System.out); 为了将其高效 BufferReader bufr=new BufferReader(new InputStreamReader(System.in)); BufferWriter bufw=new BufferWriter(new OutputStreamWriter(System.out));5、将一个中文字符串数据按照指定的编码表写入到一个文本文件中 1、目的 OutputStream writer 2、是纯文本 Writer 3、设备:硬盘 File FileWriter fw=new FileWriter("a.txt") fw.write("你好"); 注意:既然需求已经明确了指定编码表的动作 那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地编码表 只能使用其父类 OutputStreamWriter OutputStreamWriter接收一个字节输出流对象,既然是操作文本文件,那么该对象应该是FileOutputStream OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("a.txt"),编码名字); 需要高效吗? BufferWriter bufw=new BufferWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),编码名字));
什么时候使用转换流呢?
1、源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁
提高对文本操作的便捷
2、一旦操作文本涉及到具体的指定编码表时,必须使用转换流
5.2.1 字节流转成字符流
package cn.itcast.p1.transstream.demo;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class TransStreamDemo_2 { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub// 字节流 InputStream in=System.in;// 将字节转成字符的桥梁,转换流 InputStreamReader isr=new InputStreamReader(in);// 字符流 BufferedReader bufr=new BufferedReader(isr); String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; System.out.println(line.toUpperCase()); } }}
缓冲区+转换流
package cn.itcast.p1.transstream.demo;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;public class TransStreamDemo_3 { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out)); String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } }}
编码问题
package cn.itcast.p1.transstream.demo;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;public class TransStreamDemo_5 { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub writeText(); writeText_1(); writeText_2(); readText(); readText_1(); } private static void readText_1() throws IOException { // TODO Auto-generated method stub// 用什么编码就用什么解码 InputStreamReader isr=new InputStreamReader(new FileInputStream("gbk_2.txt"),"gbk"); char[] buf=new char[10]; int len=isr.read(buf); String str=new String(buf,0,len); System.out.println(str); isr.close(); } private static void readText() throws IOException { // TODO Auto-generated method stub FileReader fr=new FileReader("gbk_2.txt");//因为编码是gbk,而默认编码是utf-8所以解码的时候乱码 char[] buf=new char[10]; int len=fr.read(buf); String str=new String(buf,0,len); System.out.println(str); fr.close(); } private static void writeText_2() throws IOException { // TODO Auto-generated method stub// 用utf-8进行编码其中的文本 OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"utf-8"); osw.write("你好"); osw.close(); } private static void writeText_1() throws IOException { // TODO Auto-generated method stub OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("gbk_2.txt"),"GBK"); /* * FileWriter fw=new FileWriter("gbk_1.txt"); * 这句代码和上面的功能是一样的 * FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件 * 简单说:操作文件的字节流+本机默认的编码表(utf-8) * 如果操作文本文件需要明确具体的编码。FileWriter就行不通了,它不能改变编码,只能使用转换流了 * * */ osw.write("你好"); osw.close(); } private static void writeText() throws IOException { // TODO Auto-generated method stub FileWriter fw=new FileWriter("gbk_1.txt"); fw.write("你好"); fw.close(); }}
6、文件操作
6.1 封装成文件对象
package cn.itcast.p2.File.demo;import java.io.File;public class FileDemo { public static void main(String[] args) { // TODO Auto-generated method stub constructorDemo(); } private static void constructorDemo() { // TODO Auto-generated method stub// 可以将一个已存在的或者不存在的文件或者目录封装成File文件对象 File file=new File("a.txt");// 以下两种方法和上面一样,只不过下面的将路径和文件名分开了,上面的可以使用绝对路径 /*File f2=new File("c:\\","a.txt"); File f=new File("c:\\"); File f3=new File(f,"a.txt");*/// File.separator表示路径分割符:window下是:\\ Linux下是:\ File f4=new File("c:"+File.separator+"abc"+File.separator+"a.txt"); System.out.println(f4); }}
6.2 文件的基本操作
package cn.itcast.p2.File.demo;import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.util.Date;public class FileMethodDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /* * File对象的常见方法 * 1、获取 * 1.1获取文件名称 * 1.2获取文件路径 * 1.3获取文件大小 * 1.4获取文件修改时间 * 2、创建与删除 * boolean * 3、判断 * 4、重命名 * * */// getDemo();// createAndDeleteDemo();// isDemo();// renameToDemo(); listRootDemo(); } private static void listRootDemo() { // TODO Auto-generated method stub File file=new File("d:\\"); System.out.println("getFreeSpace:"+file.getFreeSpace());//打印空闲空间 System.out.println("getTotalSpace:"+file.getFreeSpace());//打印总共空间 System.out.println("getUsableSpace:"+file.getFreeSpace());//打印可用空间// File[]files=File.listRoots();// for(File file:files)// System.out.println(file);//打印根目录,即C:\ D:\ E:\ F:\ } private static void renameToDemo() { // TODO Auto-generated method stub File f1=new File("a.txt"); File f2=new File("aa.txt"); boolean b=f1.renameTo(f2);//将a.txt重命名为aa.txt,如果是aa.txt和a.txt是不同的盘,则变成了剪切并重命名,a.txt不存在了,变成了其他盘的aa.txt System.out.println("b="+b); } private static void isDemo() { // TODO Auto-generated method stub File f=new File("a.txt");// boolean b=f.exists();//判断文件是否存在// System.out.println(b); System.out.println(f.isDirectory());//判断是否是目录 System.out.println(f.isFile());//判断是否是文件,一般先判断是否存在再判断文件与否,假如不存在,则会返回false } private static void createAndDeleteDemo() throws IOException { // TODO Auto-generated method stub File file=new File("file.txt"); /* * 和输出流不一样,如果文件不存在则创建,存在则不创建 * */// boolean b=file.createNewFile();//创建新文件// System.out.println("b="+b); //创建目录 /*File dir=new File("abc"); * File dir1=new File("abc\\d\\d\cc"); boolean b=dir1.mkdirs();//创建多级目录 dir.mkdir();//创建单级目录 System.out.println("b="+b); System.out.println(dir.delete());//删除目录,里面如果有文件则删不掉,删除多级目录时只删除了最里面的那个目录 */ boolean b=file.delete();//删除文件 } private static void getDemo() { // TODO Auto-generated method stub File file=new File("a.txt"); String name=file.getName();//获取文件名称 String absPath=file.getAbsolutePath();//获取文件绝对路径 String path=file.getPath();//获取相对路径 long len=file.length();//获取文件大小 long time=file.lastModified();//获取最近一次修改时间 Date date=new Date(time); DateFormat dateFormat=DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); String str_time=dateFormat.format(date); System.out.println("parent path:"+file.getParent());//获取文件的父目录 System.out.println(name); System.out.println(absPath); System.out.println(path); System.out.println(len); System.out.println(time); System.out.println(str_time); }}
6.3 过滤文件
过滤器
隐藏文件的过滤器
package cn.itcast.p2.filter;import java.io.File;import java.io.FileFilter;import java.nio.file.Path;public class FilterByHadden implements FileFilter { @Override public boolean accept(File pathname) { // TODO Auto-generated method stub return !pathname.isHidden(); }}
后缀名的过滤器(.java)
package cn.itcast.p2.filter;import java.io.File;import java.io.FilenameFilter;public class filterByName implements FilenameFilter { @Override public boolean accept(File dir, String name) { // TODO Auto-generated method stub return name.endsWith(".java"); }}
后缀名的通用过滤器
package cn.itcast.p2.filter;import java.io.File;import java.io.FilenameFilter;public class ShufflxFilter implements FilenameFilter { private String suffix; @Override public boolean accept(File dir, String name) { // TODO Auto-generated method stub return name.endsWith(suffix); } public ShufflxFilter( String suffix) { super(); this.suffix=suffix; // TODO Auto-generated constructor stub }}
过滤文件的代码示例
package cn.itcast.p2.File.demo;import java.io.File;import cn.itcast.p2.filter.FilterByHadden;import cn.itcast.p2.filter.ShufflxFilter;public class FileListDemo { public static void main(String[] args) { // TODO Auto-generated method stub// listDemo();// listDemo_2(); listDemo_3(); } private static void listDemo_3() { // TODO Auto-generated method stub File dir=new File("c:\\"); File[]files=dir.listFiles(new FilterByHadden()); for(File file:files) { System.out.println(file); } } private static void listDemo_2() { // TODO Auto-generated method stub File dir=new File("c:\\");// String[]names=dir.list(new filterByName());//过滤器 String[]names=dir.list(new ShufflxFilter(".java"));//根据自定义后缀名过滤文件 for(String name:names) { System.out.println(name); } } private static void listDemo() { // TODO Auto-generated method stub File file=new File("c:\\"); /* * 获取当前目录的文件以及文件夹名称,包含隐藏文件 * 调用list方法的File对象中封装的必须是目录 * 否则会发生NullPointerException异常 * 如果访问的是系统级目录也会发生指针异常 * 如果目录存在但是没有内容,会返回一个数组,但是长度为0 * * */ String[]names=file.list();//获取当前目录的文件以及文件夹名称,包含隐藏文件 for(String name:names) { System.out.println(name); } }}
获取目录下的文件
package cn.itcast.p2.File.test;import java.io.File;/* * 需求:对指定目录进行所有内容的列出(包含子目录中的内容) * 也可以理解为深度遍历 * * */public class FileTest { public static void main(String[] args) { // TODO Auto-generated method stub File dir=new File("I:\\"); listAll(dir,0); } private static void listAll(File dir,int level) { // TODO Auto-generated method stub// 获取指定目录下当前的所有文件夹或者文件对象 File[]files=dir.listFiles(); for(int x=0;x<files.length;x++) { if(files[x].isDirectory()) { listAll(files[x],level); } else System.out.println(getSpace(level)+files[x].getName()); } } private static String getSpace(int level) { // TODO Auto-generated method stub StringBuilder sb=new StringBuilder(); for(int x=0;x<level;x++) { sb.append("|--"); } return sb.toString(); }}
删除目录下的文件
package cn.itcast.p2.File.test;import java.io.File;/* * 删除一个带有内容的目录 * 原理:必须从最里面往外删 * * * */public class RemoveDirTest { public static void main(String[] args) { // TODO Auto-generated method stub File dir=new File("");// dir.delete(); removeDir(dir); } private static void removeDir(File dir) { // TODO Auto-generated method stub File[]files=dir.listFiles(); for(File file:files) { if(file.isDirectory()) { removeDir(file); }else { System.out.println(file+":"+file.delete()); } } System.out.println(dir+":"+dir.delete()); }}
7 Properties
7.1 Properties基本操作
package cn.itcast.p2.properties;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;import java.util.Set;public class PropertiesDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /* * Map * |--Hashtable * |--Properties: * * Properties集合: * 特点: * 1、该集合中的键和值都是字符串类型 * 2、集合中的数据保存到流中,或者从流获取(字节流、字符流都行) * * 通常该集合用于操作以键值对形式存在的配置文件 * * * * */// propertiesDemo();// methodDemo();// methodDemo_2();// methodDemo_3(); methodDemo_4(); } private static void methodDemo_4() throws IOException { // TODO Auto-generated method stub// 对已有的配置文件中的信息进行修改 /* * 读取这个文件 * 并将这个文件中的键值数据存储到集合中 * 再通过集合对数据进行修改 * 再通过流将修改后的数据存储到文件中 * */ File file=new File("info.txt"); if(!file.exists()) { file.createNewFile(); } FileReader fr=new FileReader(file);// FileWriter fw=new FileWriter(file);//放到这个位置里面将只有wangwu=16这一条信息// 创建集合存储配置信息 Properties prop=new Properties();// 将流中信息存储到集合中 prop.load(fr); prop.setProperty("wangwu", "16");// 创建输出流 FileWriter fw=new FileWriter(file);//因为这个file也就是info.txt是新建的(覆盖了之前的info.txt),将集合中的所有信息输出到里头// 将集合中的信息存储到输出流中 prop.store(fw, "modify wangwu"); fw.close(); fr.close(); } private static void methodDemo_3() throws IOException { // TODO Auto-generated method stub Properties prop=new Properties();// 集合中的数据来自于一个文件// 注意:必须保证该文件中的数据是键值对// 需要使用到读取流 FileInputStream fis=new FileInputStream("info.txt");// 使用load方法 prop.load(fis); prop.list(System.out); } private static void methodDemo_2() throws IOException { // TODO Auto-generated method stub Properties prop=new Properties();// 存储元素 prop.setProperty("zhangsan", "30"); prop.setProperty("lisi", "31"); prop.setProperty("wangwu", "26"); prop.setProperty("zhaoliu", "20");// 想要将这些集合中的字符串键值信息持久化存储到文件中// 需要关联输出流 FileOutputStream fos=new FileOutputStream("info.txt");// 将集合中数据存储到文件中,使用Store方法 prop.store(fos, "name+age"); fos.close(); } private static void methodDemo() { // TODO Auto-generated method stub// 演示Properties集合和流对象相结合的功能 Properties prop=new Properties();// 存储元素 prop.setProperty("zhangsan", "30"); prop.setProperty("lisi", "31"); prop.setProperty("wangwu", "26"); prop.setProperty("zhaoliu", "20"); prop.list(System.out);//将存储的元素打印输出到控制台 } /* * Properties集合的存和取 * * * */ private static void propertiesDemo() { // TODO Auto-generated method stub// 创建一个Properties集合 Properties prop=new Properties();// 存储元素 prop.setProperty("zhangsan", "30"); prop.setProperty("lisi", "31"); prop.setProperty("wangwu", "26"); prop.setProperty("zhaoliu", "20");// 修改元素 prop.setProperty("wangwu", "36");// 取出所有元素 Set<String>names=prop.stringPropertyNames(); for(String name:names) { String value=prop.getProperty(name); System.out.println(name+":"+value); } }}
7.2 Properties案例示例
package cn.itcast.p2.properties;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.FilenameFilter;import java.io.IOException;import java.util.ArrayList;import java.util.List;/* * 获取指定目录下,指定扩展名的文件(包含子目录中的) * 这些文件的绝对路径写入到一个文本文件中 * * 简单的说,就是建立一个指定扩展名的文件的列表 * * 思路: * 1、必须进行深度遍历 * 2、要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中 * 3、对容器中的内容进行遍历并将绝对路径写入到文件中 * * * */public class Test { public static void main(String[] args) { // TODO Auto-generated method stub File dir=new File("J:\\协同中心"); FilenameFilter filter=new FilenameFilter() { @Override public boolean accept(File dir, String name) { // TODO Auto-generated method stub return name.endsWith(".xlsx"); } }; List<File>list=new ArrayList<File>(); getFiles(dir,filter,list); File destfile=new File(dir,"javalist.txt"); writerToFile(list,destfile); } private static void getFiles(File dir,FilenameFilter filter,List<File>list) { // TODO Auto-generated method stub File[]files=dir.listFiles(); for(File file:files) { if(file.isDirectory()) { getFiles(file,filter,list); }else {// 对过滤器进行过滤,将符合条件的对象存储到集合中 if(filter.accept(dir, file.getName())) { list.add(file); } } } } public static void writerToFile(List<File>list,File destFile) { BufferedWriter bufw=null; try { bufw=new BufferedWriter(new FileWriter(destFile)); for(File file:list) { bufw.write(file.getAbsolutePath()); bufw.newLine(); bufw.flush(); } } catch (IOException e) { // TODO Auto-generated catch block throw new RuntimeException("写入失败"); }finally { if(bufw!=null) try { bufw.close(); }catch(IOException e){ throw new RuntimeException("关闭失败"); } } }}
package cn.itcast.p2.properties;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;/* * 定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示,并终止程序的运行 * 思路: * 1、应该有计数器 * 每次程序启动都需要计数一次,并且是在原有的次数上进行计数 * 2、计数器就是一个变量,程序启动时进行计数,计数器必须存在于内存并进行运算 * 可是程序一结束,计数器就消失了,那么再次启动该程序,计数器又被重新初始化了 * 而我们需要多次启动同一个应用程序,使用的是同一个计数器 * 这就需要计数器的生命周期变长,从内存存储到硬盘文件中 * 3、如何使用计数器呢? * 首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件,获取上一次计数器次数 * 其次,对该次数进行自增,并将自增后的次数重新存储到配置文件中。 * 4、文件中的信息该如何进行存储并体现? * 直接存储次数值可以,但是不明确该数据的含义。所以起名字变得很重要 * 这就有了名字和值的对应,所以可以使用键值对 * 映射关系可以使用map集合搞定,由于又需要读取硬盘上的数据,所以用map+io=properties搞定 * * */public class PropertiesTest { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub getAppCount(); } private static void getAppCount() throws IOException { // TODO Auto-generated method stub// 将配置文件封装成File对象 File confile=new File("count.properties"); if(!confile.exists()) { confile.createNewFile(); } FileInputStream fis=new FileInputStream(confile); Properties prop=new Properties(); prop.load(fis);// 从集合中通过键获取次数 String value=prop.getProperty("time");// 定义计数器,记录获取到的次数 int count=0; if(value!=null) { count=Integer.parseInt(value); if(count>=5) { System.out.println("使用次数已到,请注册"); throw new RuntimeException(); } } count++;// 将改变后的次数重新存储到集合中 prop.setProperty("time", count+""); FileOutputStream fos=new FileOutputStream(confile); prop.store(fos, ""); fos.close(); fis.close(); }}
8 其他流
8.1 打印流
package cn.itcast.p2.print.demo;import java.io.FileNotFoundException;import java.io.PrintStream;public class PrintDemo { public static void main(String[] args) throws FileNotFoundException { // TODO Auto-generated method stub /* * PrintStream: * 1、提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式 * 2、它不抛IOException * * 构造函数,接收三种类型的值: * 1、字符串路径 * 2、File对象 * 3、字节输出流 * * */ PrintStream out=new PrintStream("print.txt");// out.write(97);//只将低8为转成字符写入进去 out.print(97);//将97先变成字符保持原样将数据打印到目的地 out.close(); }}
package cn.itcast.p2.print.demo;import java.io.BufferedReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;public class PrintWriterDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /* * PrintWriter:字符打印流 * 构造函数参数: * 1、字符串路径 * 2、File对象 * 3、字节输出流 * 4、字符输出流 * * */ BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));// PrintWriter out=new PrintWriter(System.out,true);//加了true可以自动刷新(相当于位置1的功能) PrintWriter out=new PrintWriter(new FileWriter("out.txt"),true);//写入到文件中 String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line.toUpperCase());// out.flush();//位置1 } out.close(); bufr.close(); }}
8.2 序列流
package cn.itcast.p2.print.demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Enumeration;public class SequenceInputStreamDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /* * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中 * * */ /*Vector<FileInputStream>v=new Vector<FileInputStream>(); v.add(new FileInputStream("1.txt")); v.add(new FileInputStream("2.txt")); v.add(new FileInputStream("3.txt")); Enumeration<FileInputStream>en=v.elements();*/// 上面方法也可,建议用下面的 ArrayList<FileInputStream>al=new ArrayList<FileInputStream>(); for(int x=1;x<=3;x++) { al.add(new FileInputStream(x+".txt")); } Enumeration<FileInputStream>en=Collections.enumeration(al);//将列表转成枚举 SequenceInputStream sis=new SequenceInputStream(en);//序列流需传一个枚举 FileOutputStream fos=new FileOutputStream("4.txt"); byte[]buf=new byte[1024]; int len=0; while((len=sis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); sis.close(); }}
8.2.1 序列流案例示例
文件切割
package cn.itcast.io.p1.splitfile;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;public class SplitFileDemo { private static final int SIZE = 1024*1024; public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //切割文件 File file=new File("J:\\01.mp3");// splitFile(file);// 文件切割+配置文件 splitFile_2(file); } private static void splitFile_2(File file) throws IOException{ // TODO Auto-generated method stub// 用读取流关联源文件 FileInputStream fis=new FileInputStream(file);// 定义一个1M的缓冲区 byte[]buf=new byte[SIZE];// 创建目的 FileOutputStream fos=null; int len=0; int count=1; /* * 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数,以方便于合并。 * 这个信息为了进行描述,使用键值对的方式。用到了properties对象 * * */ Properties prop=new Properties(); File dir=new File("J:\\partfiles"); if(!dir.exists()) dir.mkdirs(); while((len=fis.read(buf))!=-1) { fos=new FileOutputStream(new File(dir,(count++)+".part")); fos.write(buf,0,len); fos.close(); }// 将被切割文件的信息保存到prop集合中 prop.setProperty("partcount", count+""); prop.setProperty("filename", file.getName()); fos=new FileOutputStream(new File(dir,count+".properties"));// 将prop集合中的数据存储到文件中 prop.store(fos, "save file info"); fos.close(); fis.close(); } private static void splitFile(File file) throws IOException { // TODO Auto-generated method stub// 用读取流关联源文件 FileInputStream fis=new FileInputStream(file);// 定义一个1M的缓冲区 byte[]buf=new byte[SIZE];// 创建目的 FileOutputStream fos=null; int len=0; int count=1; File dir=new File("J:\\partfiles"); if(!dir.exists()) dir.mkdirs(); while((len=fis.read(buf))!=-1) { fos=new FileOutputStream(new File(dir,(count++)+".part")); fos.write(buf,0,len); } fos.close(); fis.close(); }}
文件合并
过滤器
package cn.itcast.io.p1.splitfile;import java.io.File;import java.io.FilenameFilter;public class SuffixFilter implements FilenameFilter { private String suffix; @Override public boolean accept(File dir, String name) { // TODO Auto-generated method stub return name.endsWith(suffix); } public SuffixFilter(String suffix) { super(); this.suffix = suffix; }}
合并
package cn.itcast.io.p1.splitfile;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Collections;import java.util.Enumeration;import java.util.Properties;public class MergeFileDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //合并文件 File dir=new File("J:\\partfiles");// mergeFile(dir); mergeFile_2(dir); } private static void mergeFile_2(File dir) throws IOException { // TODO Auto-generated method stub// 获取指定目录下的配置文件对象 File[]files=dir.listFiles(new SuffixFilter(".properties")); if(files.length!=1) throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");// 记录配置文件对象 File confile=files[0];// 获取该文件中的信息 Properties prop=new Properties(); FileInputStream fis=new FileInputStream(confile); prop.load(fis); String filename=prop.getProperty("filename"); int count=Integer.parseInt(prop.getProperty("partcount"));// 获取该目录下的所有碎片文件 File[]partFiles=dir.listFiles(new SuffixFilter(".part")); if(partFiles.length!=(count-1)) { throw new RuntimeException("碎片文件不符合要求,个数不对!应该"+count+"个"); }// 将碎片文件和流对象关联并存储到集合中 ArrayList<FileInputStream>al=new ArrayList<FileInputStream>(); for(int x=1;x<partFiles.length;x++) { al.add(new FileInputStream(partFiles[x])); }// 将多个流合并成一个序列流 Enumeration<FileInputStream>en=Collections.enumeration(al); SequenceInputStream sis=new SequenceInputStream(en); FileOutputStream fos=new FileOutputStream(new File(dir,filename)); byte[] buf=new byte[1024]; int len=0; while((len=sis.read(buf))!=-1) { fos.write(buf, 0, len); } fos.close(); sis.close(); } private static void mergeFile(File dir) throws IOException { // TODO Auto-generated method stub ArrayList<FileInputStream>al=new ArrayList<FileInputStream>(); for(int x=1;x<8;x++) { al.add(new FileInputStream(new File(dir,x+".part"))); } Enumeration<FileInputStream>en=Collections.enumeration(al); SequenceInputStream sis=new SequenceInputStream(en); FileOutputStream fos=new FileOutputStream(new File(dir,"02.mp3")); byte[] buf=new byte[1024]; int len=0; while((len=sis.read(buf))!=-1) { fos.write(buf, 0, len); } fos.close(); sis.close(); }}
8.2.2 对象序列化和反序列化
Person类实现Serializable接口
package cn.itcast.io.p2.bean;import java.io.Serializable;/* * Serializable用于给序列化的类加入ID号 * 用于判断类和对象是否是同一个版本 * transient:非静态数据不想被序列化可以使用这个关键字修饰 * * * */public class Person implements Serializable/*标记接口*/{ private static final long serialVersionUID=95271;//如果不自定义这个ID的话,系统会根据类型等自动算出一个ID,但这个根据编译器版本算出有所差异,所以 //可能导致,在不同编译器下序列化的文件,在另一个版本编译器下不能被反序列化(序列化和反序列化的时候它需要校正这个ID) //为此,如果你将某个对象序列化后,然后将这个类中的private String name;改成public String name它也不能被反序列化,ID号变了 private String name;// private transient String name;//不会被序列化// private static int age;//静态数据的值不会被序列化,比如这个反序列化回来就是0(它在静态去,对象在堆区) private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String name, int age) { super(); this.name = name; this.age = age; }}
对象序列化和反序列化
package cn.itcast.io.p1.splitfile;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import cn.itcast.io.p2.bean.Person;public class objectStreamDemo { public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { // TODO Auto-generated method stub writeObject(); readObject(); } private static void readObject() throws FileNotFoundException, IOException, ClassNotFoundException { // TODO Auto-generated method stub ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.object"));// 对象的反序列化 Person p=(Person)ois.readObject(); System.out.println(p.getName()+":"+p.getAge()); ois.close(); } private static void writeObject() throws FileNotFoundException, IOException { // TODO Auto-generated method stub ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.object"));// 对象序列化,被序列化的对象必须实现Serializable接口 oos.writeObject(new Person("小强",30)); oos.close(); }}
9 其他流的读写
9.1 文件随机读写
package cn.itcast.io.p1.splitfile;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;public class RandomAccessFileDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub /* * RandomAccessFile不是io体系中的子类 * 特点: * 1、该对象既能读又能写 * 2、该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素 * 3、可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置 * 4、其实该对象就是将字节输入流和输出流进行了封装 * 5、该对象的源和目的只能是文件(文本文件、媒体文件都可) * * */ writeFile(); readFile(); randomWrite(); }private static void randomWrite() throws IOException { // TODO Auto-generated method stub RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");// raf.write("赵六".getBytes());//这样的话就覆盖了之前数组里的张三和102(因为文件存在,它不会重新创建,也就是该数组存在,只会覆盖)// raf.writeInt(102);// 往指定位置写入数据 raf.seek(5*8);//定位指针位置 raf.write("哈哈".getBytes()); raf.writeInt(108); raf.close(); }private static void readFile() throws IOException { // TODO Auto-generated method stub RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");// 通过seek设置指针的位置// raf.seek(1*8);//将指针移到第8个字节的位置 byte[]buf=new byte[6];//因为系统编码是utf-8,所以一个汉字是三个字节存储的,为此这里是6,如果变成4,则后面那个字是乱码 raf.read(buf); String name=new String(buf); int age=raf.readInt(); System.out.println("name="+name); System.out.println("age="+age); System.out.println("pos:"+raf.getFilePointer());//获取指针当前位置 raf.close(); }// 使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄 private static void writeFile() throws IOException { // TODO Auto-generated method stub //如果文件不存在,则创建,如果文件存在,不创建 RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw"); raf.write("张三".getBytes());//写入的是字节// raf.write(97);//只写低8位 raf.writeInt(908);//都写入 raf.close(); }}
9.2 基本数据类型的读写
package cn.itcast.io.p3.dataStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class DataStreamDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub// 操作基本数据类型的流 writeData(); readData(); } private static void readData() throws IOException { // TODO Auto-generated method stub DataInputStream r=new DataInputStream(new FileInputStream("data.txt")); System.out.println(r.readUTF()); r.close(); } private static void writeData() throws IOException { // TODO Auto-generated method stub DataOutputStream dis =new DataOutputStream(new FileOutputStream("data.txt")); dis.writeUTF("你好");//修改版的utf-8,前面有一个标识符 dis.close(); }}
9.3 字节数组读写
package cn.itcast.io.p3.byteStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;public class byteStreamDemo { public static void main(String[] args) { // TODO Auto-generated method stub ByteArrayInputStream bis=new ByteArrayInputStream("abcd".getBytes()); ByteArrayOutputStream bos=new ByteArrayOutputStream(); int len=0; while((len=bis.read())!=-1) { bos.write(len); } System.out.println(bos.toString()); }}
9.4 管道流读写
package cn.itcast.io.p1.piped;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;public class pipedDemo { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub PipedInputStream input=new PipedInputStream(); PipedOutputStream output=new PipedOutputStream(); input.connect(output);//输入流连接输出流 new Thread(new Input(input)).start(); new Thread(new Output(output)).start(); }}class Input implements Runnable{ private PipedInputStream in; Input(PipedInputStream in){ this.in=in; } public void run() { try { byte[]buf=new byte[1024]; int len=in.read(buf); String s=new String(buf,0,len); System.out.println("s="+s); in.close(); }catch(Exception e) { } }}class Output implements Runnable{ private PipedOutputStream out; Output(PipedOutputStream out){ this.out=out; } public void run() { try { out.write("hi,管道来了".getBytes()); }catch(Exception e) { } }}
10. 编码解码
10.1 编码解码解析
package cn.itcast.io.p4.encode;import java.io.UnsupportedEncodingException;public class EncodeDemo { public static void main(String[] args) throws UnsupportedEncodingException { // TODO Auto-generated method stub /* * 字符串--->字节数组:编码 * 字节数组--->字符串:解码 * * */ String str="你好";// 编码 byte[]buf=str.getBytes();// byte[]buf=str.getBytes("GBK");//指定为GBK编码// printBytes(buf);// 解码 String s1=new String(buf);//默认方式解码// String s1=new String(buf,"utf-8");//指定码表解码 System.out.println("s1="+s1); errorEncode(); } private static void errorEncode() throws UnsupportedEncodingException { // TODO Auto-generated method stub /* * 如果编码编错了,解不出来 * 如果编码对了,解错了,有可能有救 * */ String str="你好"; byte[]buf=str.getBytes(); String s1=new String(buf,"iso8859-1");//编码是utf-8,用iso8859-1解码 System.out.println("s1="+s1);//结果:s1=ä½ å¥½ byte[]buf2=s1.getBytes("iso8859-1");//获取源字节 String s2=new String(buf2,"utf-8"); System.out.println("s2="+s2); } private static void printBytes(byte[] buf) { // TODO Auto-generated method stub for(byte b:buf) { System.out.println(b); } }}
10.2 编码解码案例
package cn.itcast.io.p4.encode;import java.io.UnsupportedEncodingException;public class Test { public static void main(String[] args) throws UnsupportedEncodingException { // TODO Auto-generated method stub /* * 在java中,字符串"abcd"与字符串"ab你好"的长度是一样,都是四个字节。 * 但对应的字节数不同,一个汉字占两个字节 * 定义一个方法,按照最大的字节数来取字串 * 如:对于"ab你好",如果取三个字节,那么子串就是ab与"你"字的半个 * 那么半个就要舍弃,如果取四个字节就是"ab你",取五个字节还是"ab你" * * */ String str="ab你好cd谢谢"; int len=str.getBytes("GBK").length; for(int x=0;x<len;x++) { System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByte(str,x+1)); } } private static String cutStringByte(String str,int len) throws UnsupportedEncodingException { // TODO Auto-generated method stub byte[]buf=str.getBytes("GBK"); int count=0; for(int x=len-1;x>=0;x--) { if(buf[x]<0) count++;//计算汉字的字节码数 else break; } if(count%2==0) return new String(buf,0,len,"gbk");//将buf里的从0到len长度的字节码按GBK解码 else return new String(buf,0,len-1,"gbk"); }}
- Java基础—IO流
- java基础—-IO流
- java基础—IO流
- java基础—IO流
- java基础—IO
- Java基础——IO(流)
- Java基础(十二)——IO流
- java基础——IO流
- Java基础——IO流
- java基础——IO流
- JAVA基础——IO流
- java基础——IO流
- java基础——IO流
- JAVA基础——IO流
- 【java基础】——IO流(上)
- 【Java基础】——IO流(中)
- 【Java基础】——IO流(下)
- Java基础——IO流(上)
- 进程同步--临界区保护(1)_轮转法
- 深入理解Java虚拟机 ch8 虚拟机字节码执行引擎 读书笔记
- 关于pip源的问题转载
- 雇员管理系统-SSH版(一)
- Clipboard.js 使用说明
- Java基础——IO流
- 仿Windows记事本简要分析 (Java)
- java 消息机制 ActiveMQ实例
- 洛谷3678:简单的数学题(画柿子+杜教筛)
- python连接mysql数据库
- HttpServletResponse
- 用最少的字介绍最常用的机器学习分类算法
- 哈尔滨理工大学第七届程序设计竞赛初赛(高年级组)F 苦逼的单身狗【DP】
- Spring深入浅出IOC详解