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

打印流

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();
		}
		
	}

}
Java IO流--IO包中的其他类_第1张图片

序列流

SequenceInputStream:对多个流进行合并,该流只能接收Enumeration类型
import java.util.*;
import java.io.*;
class Demo2Sequence {

	public static void main(String[] args) {

		Vector v = new Vector ();  //所以只有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 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 block
					e.printStackTrace();
				}
				
			}
			if(fos != null){
				
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.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 al = new ArrayList();  //创建一个ArrayList集合

		for(int x=1; x<=3; x++)
		{
			al.add(new FileInputStream("D:\\splitfiles\\"+x+".part"));  //把切割成3份的文件存入
		}
           
//       把对象存入ArrayList,然后通过枚举取出的方法,通过匿名内部类覆盖两个方法并且返回值
		final Iterator it = al.iterator();  //因为是访问匿名内部类,所以前面要加上fianl修饰
             
		Enumeration en = new Enumeration()
		{
			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()不能写入静态字段。所以结果会显示为null

		oos.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连接到out

		Read r = new Read(in);
		Write w = new Write(out);
		new Thread(r).start();    //管道流与多线程关联
		new Thread(w).start();


	}
}

Java IO流--IO包中的其他类_第2张图片

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"));   此方法抛异常,并且可以把内存中的数据写入到硬盘

	}
}
Java IO流--IO包中的其他类_第3张图片
在流操作规律:
源设备,
键盘 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默认的编码表是GBK
		System.out.println(Arrays.toString(b1));  //[-60,-29,-70,-61]
		
		String s1 = new String(b1,"GBK");   //转换成字符串,解码。默认的也是GBK
		System.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编码规则
Java IO流--IO包中的其他类_第4张图片








 

你可能感兴趣的:(Java IO流--IO包中的其他类)