Java IO流--IO包中的其他类

来源:互联网 发布:中国大学生软件杯 编辑:程序博客网 时间:2024/05/01 04:20

打印流

PrintWriter与PrintStream:可以直接操作输入流和文件
PrintStream(字节打印流)
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
PrintStream永远不会抛出IOException,PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。并且提供了打印方法可以对多种数据类型值进行打印,并保持数据的表现形式。
import java.io.*;class TestWork {public static void main(String[] args) throws IOException {PrintStream out = new PrintStream("print.txt");out.write(97);  //输出a,只输出最低8位的字节out.print(97);  //输出97,将97变成字符串保持原样将数据打印到目的地out.close();}}
PrintWriter(字符打印流)
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
4,字符输出流,Writer。
import java.io.*;class Demo1PrintDemo {public static void main(String[] args) {BufferedReader bufr = null;PrintWriter out = null;try {bufr = new BufferedReader(new InputStreamReader(System.in));out = new PrintWriter(System.out,true);  //PrintWriter()可以接受字节对象,true表示默认换行,自动刷新String line = null;while((line = bufr.readLine()) != null) {if("over".equals(line))  //输入over则结束break;out.println(line.toUpperCase());  //转换大写字母}}catch(IOException e) {}finally {if(bufr != null) {try {bufr.close();}catch(IOException e) {}}if(out != null) out.close();}}}

序列流

SequenceInputStream:对多个流进行合并,该流只能接收Enumeration类型
import java.util.*;import java.io.*;class Demo2Sequence {public static void main(String[] args) {Vector<FileInputStream> v = new Vector<FileInputStream> ();  //所以只有Vector里面有SequenceInputStream sis = null;FileOutputStream fos = null;try {v.add(new FileInputStream("1.txt"));v.add(new FileInputStream("2.txt"));v.add(new FileInputStream("3.txt"));Enumeration<FileInputStream> en = v.elements();   调用Vector里面的elements方法,创建Enumeration对象 sis = new SequenceInputStream(en);   //传入对象 fos = new FileOutputStream("4.txt");byte[] buf = new byte[1024];   int len = 0;while((len = sis.read(buf)) != -1) {fos.write(buf,0,len);}} catch (IOException e) {e.printStackTrace();}finally {if(sis != null){try {sis.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(fos != null){try {fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}

文件切割
import java.io.*;import java.util.*;class SplitFile {public static void main(String[] args) throws IOException{//splitFile();merge();}public static void merge()throws IOException{ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();  //创建一个ArrayList集合for(int x=1; x<=3; x++){al.add(new FileInputStream("D:\\splitfiles\\"+x+".part"));  //把切割成3份的文件存入}           //       把对象存入ArrayList,然后通过枚举取出的方法,通过匿名内部类覆盖两个方法并且返回值final Iterator<FileInputStream> it = al.iterator();  //因为是访问匿名内部类,所以前面要加上fianl修饰             Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){public boolean hasMoreElements(){return it.hasNext();}public FileInputStream nextElement(){return it.next();}};SequenceInputStream sis = new SequenceInputStream(en);  //将枚举传入FileOutputStream fos = new FileOutputStream("D:\\splitfiles\\0.bmp");byte[] buf = new byte[1024];int len = 0;while((len=sis.read(buf))!=-1){fos.write(buf,0,len);  //写入文件}fos.close();sis.close();}public static void splitFile()throws IOException{FileInputStream fis =  new FileInputStream("D:\\1.bmp");FileOutputStream fos = null;byte[] buf = new byte[1024*1024];  //定义一个原文件小的数组,以便达到切割的目的int len = 0;int count = 1;    //这个变量是为了方便去文件名while((len=fis.read(buf))!=-1){fos = new FileOutputStream("D:\\splitfiles\\"+(count++)+".part");fos.write(buf,0,len);fos.close();}fis.close();}}

操作对象

ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable
类通过实现java.io.Serializable接口以启用序列化功能,Serializable只是一个标记接口,子类实现后不用覆盖方法
import java.io.*;class ObjectStreamDemo {public static void main(String[] args) throws Exception{//writeObj();readObj();}public static void readObj()throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));//创建一个操作对象流的实例化对象,并传入相关联的对象Person p = (Person)ois.readObject();   //因为ois是Obj所以要向下转型,System.out.println(p);ois.close();}public static void writeObj()throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));oos.writeObject(new Person("lisi0",399,"kr"));  //往文件里面写入对象,但writeObject()不能写入静态字段。所以结果会显示为nulloos.close();}}
import java.io.*;class Person implements Serializable  //自定义一个类并实现Serializable接口,给被序列化的类加ID号{public static final long serialVersionUID = 42L;  //声明serialVersionUID则序列号不会变动,private String name;   //如果把private改为了public则会出现异常,因为默认的ID号变动了transient int age;static String country = "cn";Person(String name,int age,String country){this.name = name;this.age = age;this.country = country;}public String toString(){return name+":"+age+":"+country;}}

管道流

 PipedInputStream和PipedOutputStream:输入输出可以直接进行连接,通过结合线程使用
import java.io.*;class Read implements Runnable{private PipedInputStream in;Read(PipedInputStream in){this.in = in;}public void run(){try{byte[] buf = new byte[1024];System.out.println("读取前。。没有数据阻塞");int len = in.read(buf);   //read没有读取到数据时,则会一直等待,当数据读到时,则继续往下执行System.out.println("读到数据。。阻塞结束");String s= new String(buf,0,len);System.out.println(s);in.close();}catch (IOException e){throw new RuntimeException("管道读取流失败");}}}class Write implements Runnable{private PipedOutputStream out;Write(PipedOutputStream out){this.out = out;}public void run(){try{System.out.println("开始写入数据,等待6秒后。");Thread.sleep(6000);out.write("piped lai la".getBytes());  //六秒后数据写入out.close();}catch (Exception e){throw new RuntimeException("管道输出流失败");}}}class  PipedStreamDemo{public static void main(String[] args) throws IOException{PipedInputStream in = new PipedInputStream();PipedOutputStream out = new PipedOutputStream();in.connect(out);    //让in连接到outRead r = new Read(in);Write w = new Write(out);new Thread(r).start();    //管道流与多线程关联new Thread(w).start();}}


RandomAccessFile

随机访问文件,自身具备读写的方法, 通过skipBytes(int x),seek(int x)等方法来达到随机访问。
特点
1. 该对象即能读,又能写
2. 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
3. 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
4. 其实该对象就是将字节输入流和输出流进行了封装
5. 该对象的源或者目的只能是文件。通过构造函数就可以看出操作文件还有模式:只读r,,读写rw等。
    如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
    如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
注意:
该类不是算是IO体系中子类,而是直接继承自Object,但是它是IO包中成员,因为它具备读和写功能。
import java.io.*class RandomAccessFileDemo {public static void main(String[] args) throws IOException{//writeFile_2();//readFile();}public static void readFile()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","r");  //只读模式,如果文件不存在则抱异常//调整对象中指针。//raf.seek(8*1);//跳过指定的字节数raf.skipBytes(8);byte[] buf = new byte[4];raf.read(buf);String name = new String(buf);int age = raf.readInt();System.out.println("name="+name);System.out.println("age="+age);raf.close();}public static void writeFile_2()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.seek(8*0);  //seek设置指针 的位置raf.write("周期".getBytes());raf.writeInt(103);raf.close();}public static void writeFile()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");  //读写模式,如果文件不存在则 创建文件raf.write("李四".getBytes());raf.writeInt(97);    //使用 writeInt方法写入 的是int类型的4个字节raf.write("王五".getBytes());raf.writeInt(99);raf.close();}}

操作基本数据类型

 DataInputStream和DataOutputStream
凡是操作基本数据类型使用此类
import java.io.*;class DataStreamDemo {public static void main(String[] args) throws IOException{//writeData();//readData();//writeUTFDemo();//readUTFDemo();}public static void readUTFDemo()throws IOException{DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));String s = dis.readUTF();  //读取UTF修改版值能用这种方法,否则会出现异常System.out.println(s);dis.close();}public static void writeUTFDemo()throws IOException{DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));dos.writeUTF("你好");  //按照UTF-8修改版,编码,与修改之前版本字节,不一样,所以读取修改版也只能用这种方法,否则会出现异常dos.close();}public static void readData()throws IOException{DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));          //读取数据int num = dis.readInt();boolean b = dis.readBoolean();double d = dis.readDouble();System.out.println("num="+num);System.out.println("b="+b);System.out.println("d="+d);dis.close();}public static void writeData()throws IOException{DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));dos.writeInt(234);  //输入int型4个字节dos.writeBoolean(true);  //输入boolean型一个字节dos.writeDouble(9887.543);  //输入double型8个字节dos.close();}}

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream
ByteArrayInputStream :
在构造的时候,需要接收数据源,。而且数据源是一个字节数组
ByteArrayOutputStream:
在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。
注意:
两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭
import java.io.*;class ByteArrayStream {public static void main(String[] args) {ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());   //数据源ByteArrayOutputStream bos = new ByteArrayOutputStream();   //数据目的,ByteArrayOutputStream内部封装好了一个可变长度的数组。int by = 0;while((by=bis.read())!=-1){bos.write(by);}System.out.println(bos.size());System.out.println(bos.toString());//bos.writeTo(new FileOutputStream("a.txt"));   此方法抛异常,并且可以把内存中的数据写入到硬盘}}
在流操作规律:
源设备,
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。
用流的读写思想来操作数据。此外还有CharArrayReader、CharArrayWriter以及StringReader、StringWriter

编码表

常见的编码表

ASCII:美国标准信息交换码,用一个字节的7位可以表示
ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字符号
Unicode:国际标准码,融合了多种文字
    所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符
编码:字符串变成字节数组。
解码:字节数组变成字符串。
转换流可以根据指定的编码表进行编码、解码
import java.io.*;class EncodeStream {public static void main(String[] args) throws IOException {//writeText();readText();}public static void readText()throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"gbk");  //按照GBK进行解码,由于编码是按utf-8进行的,所以按照gbk解码的时候输出的结果是你好两个 字符char[] buf = new char[10];int len = isr.read(buf);String str = new String(buf,0,len);System.out.println(str);isr.close();}public static void writeText()throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");  //按照UTF-8进行编码osw.write("你好");osw.close();}}
字符串、字节的例子
import java.util.*;class Demo4Encode {public static void main(String[] args) throws IOException{String s = "你好";byte[] b1 = s.getBytes("GBK");   //转换成字节数组,编码。getBytes默认的编码表是GBKSystem.out.println(Arrays.toString(b1));  //[-60,-29,-70,-61]String s1 = new String(b1,"GBK");   //转换成字符串,解码。默认的也是GBKSystem.out.println(s1);  //你好}public static void iso() throws IOException {String s = "你好";byte[] b1 = s.getBytes();   String s1 = new String(b1,"iso8859-1");  //如果用GBK进行编码,解码的时候用iso8859-1,会产生乱码,这时的解决办法是System.out.println(s1);byte[] b2 = s1.getBytes("iso8859-1");   //再用iso859-1进行编码,转换成字节数组,因为它的字节没变。再通过GBK解码即可String s2 = new String(b2,"GBK");System.out.println(s2);}}
当在windows自带的记事本里面输入联通的时候,再次打开会出现乱码
原因:
输入联通两字符时,记事本默认GBK编码:11000001、10101010、11001101、10101000。正好符合UTF-8的编码规则,再次打开时,记事本就按照了UTF-8进行解码,故出现了乱码现象。
UTF-8编码规则









 
0 0
原创粉丝点击