黑马程序员——java高新技术——IO其他流对象

点击打开链接 点击打开链接 点击打开链接 android培训、<a">点击打开链接 点击打开链接 java培训、期待与您交流!">点击打开链接 点击打开链接

IO其他对象

PrintStream:字节打印流。为其他输出流添加了功能,提供了打印方法,可以将各种数据类型的数据原样打印。

构造函数可以接受的参数类型:file对象,字符串路径,字节输出流。

方法:println():打印各种基本数据类型。

PrintWrite:字符打印流。构造函数可以接受的参数类型:file对象(File file)、(File file,String csn),字符串路径(String FileName)、(Strring FileName,String csn),字节输出流 OutputStream,字符输出流Writer。(Writer out,boolean autoFlush)(OutputStream out ,boolean b),b为true,则println,printf,format等方法使用时自动刷新。

SequenceInputStream 合并流

两个构造函数(Enumeration<? Extends InputStream> e)Enumeration:Vector的elements()方法会返回Enumeration,所有我们先把需要合并的流装入Vector集合中,然后把集合对象.elements()作为参数传给合并流就可以。

还有一个构造函数(InputStream s1,InputStream s2):把两个流直接传给构造函数。

import java.io.*;
import java.util.*;
class Test42   //合并流练习
{
	public static void main(String[] args) throws IOException
	{
		//首先新建一个Vector集合,把需要合并的流装入集合中
		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,作为参数传递得合并流的构造函数
		Enumeration<FileInputStream> en=v.elements();
		SequenceInputStream si=new SequenceInputStream(en);

		//操作合并流即可读取到三个流的所有文件。
		FileOutputStream fis=new FileOutputStream("4.txt");
		byte[] b=new byte[1024];
		int len;
		while((len=si.read(b))!=-1)
		{
			fis.write(b,0,len);
		}
		fis.close();
		si.close();
	}
}

切割文件:Test43

import java.io.*;
import java.util.*;
class Test43  //切割文件
{
	public static void main(String[] args) throws IOException
	{
		//splitmp3();
		hebingmp3();
	}
	public static void hebingmp3() throws IOException
	{
		ArrayList<FileInputStream> v=new ArrayList<FileInputStream>();
		v.add(new FileInputStream("4.part"));
        v.add(new FileInputStream("4.part"));
        v.add(new FileInputStream("4.part"));

		Iterator<FileInputStream> it=v.iterator();
		Enumeration<FileInputStream> en=new Enumeration()
		{   public boolean hasMoreElements()
		    {
			    return it.hasNext();
		    }
		    public FileInputStream nextElement()
		    {
			    return it.next();
		    }
		};

		SequenceInputStream sit=new SequenceInputStream(en);

		FileOutputStream fis=new FileOutputStream("123.mp3");
		byte[] b=new byte[1024*1024];
		int len=0;
		while((len=sit.read(b))!=-1)
		{
			fis.write(b);
		}
		fis.close();
		sit.close();
	}

	//切割MP3函数
	public static void splitmp3() throws IOException
	{
		FileInputStream fis=new FileInputStream("1.mp3");
		byte[] bys=new byte[1024*1024];
		int len=0;
		int count=4;
		FileOutputStream fos=null;
		while((len=fis.read(bys))!=-1)
		{
           fos=new FileOutputStream((count++)+".part");
		   fos.write(bys);
		   fos.close();
		}
	}
}

操作对象的流:把堆里的对象存储到硬盘,叫对象的序列化。

ObjectInputStream 与ObjectOutputStream

被操作的对象需要实现接口Serializable,里面没有方法,没有方法的接口称为标记接口。

静态不能被序列化,只能序列化堆里面的。

加transient关键字 也不能被序列化。

文件一般被存为.object。

Public static fianl long serialVersionUID

ObjectOutputStream 方法:

writeObject():

ObjectInputStream方法:

readObject():

IO包中的类RandomAccessFile

1.该类不是IO体系中的子类,而是直接继承Object。但是它是IO包中的成员,因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置。同时可以通过seek改变指针位置。其实完成读写操作的原理就是内部封装了字节输入流和输出流。

2.RandomAccessFile(File file,String mode)  RandomAccessFile(String name,String mode)  两个构造函数可以看出该类只能操作文件,而且操作文件还有模式。Mode参数用以打开文件的访问方式,其值为:

r  只读,不会创建文件,会去读取一个已存在的文件,如果文件不存在,则会出现异常。

rw 读写  文件不存在,会自动创建,如果存在不会覆盖。

rws  读写,还要求对文件的内容或元数据的每个同步更新都同步写入到底层存储设备。

rwd  读写,还要求对文件的内容的每个更新都同步写入到底层存储设备。

3.RandomAccessFile类的重要方法:

①达到随机读取数据的两种方法:

Void  seek(long pos):设置此文件开头测量到的文件指针偏移量。

Int   skipBytes(int n):尝试跳过n字节。

②读操作,不同数据类型用不同的read方法

readInt()、readerDouble、readChar()等各种基本数据类型的读法。

String readLine():读取一行

String ReadUTF():读取一个字符串。

③写操作,为了避免数据丢失,不同数据类型写入用不同的write方法

writeInt()、writeDouble()与读相对应的各种基本数据类型的写方法。

writeUTF(String str):将一个字符串写入文件,按UTF-8编码。

④获取和设置文件长度

long length():返回此文件的长度。

void  setLength(long newLength):设置此文件的长度.

4.练习

import java.io.*;
class Test46 //RamdomAccessFile的练习
{
	public static void main(String[] args)
	{
		writeFile();
		readFile_1();
        readFile_2();
	}
	public static void writeFile()  //写操作
	{
		RandomAccessFile raf=null;
		try
		{
			raf=new RandomAccessFile("random.txt","rw");
            raf.write("Lily".getBytes());   //不要忘了变成字节
		    raf.writeInt(12);
            raf.write("Jack".getBytes());
		    raf.writeInt(13);
		}
		catch (IOException e)
		{
			System.out.println("写入错误");
		}
		finally
		{
           try
           {
			   if(raf!=null)
		         raf.close();
           }
           catch (IOException e)
           {
			   System.out.println("关闭流发生错误");
           }
		}
	}
	public static void readFile_1()  //读操作
	{
		RandomAccessFile raf=null;
       try
       {
		  raf=new RandomAccessFile("random.txt","r");   //只读,mode选择r就行
          byte[] b=new byte[4];                         //一个字母一字节,存入的名字都是4字母,字节数组长度为4,刚好存入一个名字
		  raf.read(b);
		  System.out.println("name="+new String(b));    //注意不同类型数据读取方式不同
		  int age;
		  age = raf.readInt();
	      System.out.println("age="+age);
       }
       catch (IOException e)
       {
		   System.out.println("读取文件发生错误");
       }
	   finally
	  {
		   try
		   {
			 if ( raf!=null)
			  raf.close();
		   }
		   catch (IOException e)
           {
		     System.out.println("未能关闭");
           }
	  }

	}

public static void readFile_2()  //随机读操作
	{
		RandomAccessFile raf=null;
       try
       {
		  raf=new RandomAccessFile("random.txt","r");
		  raf.seek(8);                              //指针指到下一个名字的地方,读取的是Jack  13
          byte[] b=new byte[4];                      //或者插入raf.skipByes(8),能达到同样效果
		  raf.read(b);
		  System.out.println("name="+new String(b));
		  int age;
		  age = raf.readInt();
	      System.out.println("age="+age);
       }
       catch (IOException e)
       {
		   System.out.println("读取文件发生错误");
       }
	   finally
	  {
		   try
		   {
			 if ( raf!=null)
			  raf.close();
		   }
		   catch (IOException e)
           {
		     System.out.println("未能关闭");
          }
	  }

	}
}

管道流

PipedInputStream和PipedOutputStream

输入输出可以直接进行连接,通过结合线程使用。连接的两种方法。

①PipedInputStream(PipedOutputStream pos)构造函数

②方法connect()

可以操作基本数据类型的数据的流对象。

DateInputStream  DateOutputStream

①DateInputStream(InputStream in)使用指定的底层InputStream创建一个DateInputStream。

各种读方法

readBoolean\readByte\readChar\readUTF

②DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入到指定基础输出流。

各种写方法。

③练习Test47

ort java.io.*;
class Test47
{
	public static void main(String[] args)  throws IOException
	{
		writeDate();
		readDate();
	}
	public static void writeDate() throws IOException
	{
		DataOutputStream dp=new DataOutputStream(new FileOutputStream("date.txt"));
		dp.writeBytes("输出流练习");   //将一个字符串写入输出流。字符串 s 中的每一个字符被依次写入输出流,每个字符用一个字节表示。
		dp.writeBoolean(true);
		dp.writeInt(123);
		dp.writeDouble(1254.256);
		dp.close();
	}

	public static void readDate() throws IOException
	{
        DataInputStream di=new DataInputStream(new FileInputStream("date.txt"));
		byte[] bys=new byte[5];
		di.read(bys);
		boolean  b=di.readBoolean();
		int i=di.readInt();
		Double d=di.readDouble();
		System.out.println(new String(bys));
		System.out.println("b="+b);
        System.out.println("i="+i);
        System.out.println("d="+d);

		di.close();
	}
}

结果如图所示:

一个汉字对应两个字节,但经过多次查找发现写入5个汉字只有5个字节,怀疑是writeBytes出来问题,查找帮助文档发现此方法详细描述为:将一个字符串写入输出流。字符串 s 中的每一个字符被依次写入输出流,每个字符用一个字节表示。所以把汉字存入损失了一部分数据,导致错误。

把汉字写入可以用writeUTF(String str) 方法。读的时候用对应的readUTF().

2.操作字节数组

①ByteArrayInputStream :在构造的时候,需要接收数据源,而且数据源是一个字节数组。两种构造函数ByteArrayInputStream(byte[] buf);ByteArrayInputStream(byte[] buf,int offset,int length);

重要方法:

Int  | available


方法摘要


int


available()

返回可从此输入流读取(或跳过)的剩余字节数。


void


close()

关闭 ByteArrayInputStream 无效。


int


read()

从此输入流中读取下一个数据字节。


int


read(byte[] b, int off, int len)

将最多 len 个数据字节从此输入流读入 byte 数组。


void


reset()

将缓冲区的位置重置为标记位置。


long


skip(long n)

从此输入流中跳过 n 个输入字节。

②ByteArrayOutptuStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。源和目的都是内存,用流的读写思想来操作数组。


方法摘要


void


close() 关闭 ByteArrayOutputStream 无效。


void


reset()

将此 byte 数组输出流的 count 字段重置为零,从而丢弃输出流中目前已累积的所有输出。


int


size() 返回缓冲区的当前大小。


byte[]


toByteArray()

创建一个新分配的 byte 数组。


String


toString()

使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。


String


toString(String charsetName)

使用指定的 charsetName,通过解码字节将缓冲区内容转换为字符串。


void


write(byte[] b, int off, int len)

将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte 数组输出流。


void


write(int b)  将指定的字节写入此 byte 数组输出流。


void


writeTo(OutputStream out)

将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用 out.write(buf, 0, count) 调用该输出流的 write 方法效果一样。

练习

import java.io.*;
class Test48
{
	public static void main(String[] args) throws IOException
	{
		ByteArrayInputStream bis=new ByteArrayInputStream("ABCDGF".getBytes());
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		int by=0;
		while((by=bis.read())!=-1)
		{
			bos.write(by);
		}
		System.out.println(bos.toString());
		bos.writeTo(new FileOutputStream("array.txt"));  //writeTo方法会抛IO异常。
	}
}

另外还有:

操作字符数组

CharArrayReader与CharArrayWriter

操作字符串

StringReader与StringWriter

其用法与操作字节数组差不多

字符编码

编码:字符串变成字节数组

解码:字节数组变成字符串

String  |  byte[]:getBytes()  getBytes(String charaetName)

byte[] | String:new String(byte[])  new String(byte[],charsetName)  Arrays.toString()

charsetName值“GBK” ”UFT-8”

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-12 20:43:14

黑马程序员——java高新技术——IO其他流对象的相关文章

黑马程序员——java基础---IO(input output)流字符流

黑马程序员——java基础---IO(input output)流字符流 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- io(input output)流特点: 1,io流用来处理数据之间的传输 2,java对数据的操作是通过流的方式: 3,java用于操作流的对象都在io包中: 4,流按操作数据分为两种:字节流和字符流: 5,流按流向分为:输入流和输出流. 注意:流只能操作数据,而不能操作文件. 3.IO流的常用基类: 1)字节流的抽象

黑马程序员——Java基础---IO(下)

黑马程序员——Java基础---IO(下) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正

黑马程序员——Java基础---io(上)

黑马程序员——Java基础---io(上) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java I/O系统负责处理程序的输入和输出,I/O类库位于java.io包中,它对各种常见的输入流和输出流进行了抽象.如果数据流中最小的数据单元是字节,那么称这种流为字节流:如果数据流

黑马程序员——Java高新技术代理

代理 普通代理 很多时候,我们使用别人代码往往会发现别人代码的功能并不是十分符合我们的需求,调用别人的方法的时候,总是先new一个对象,然后我们的前处理做完,然后调用别人代码的方法,再加入后处理,这样做往往十分麻烦.代理就为其他类提供了一种控制其对象的方法.代理类和委托类必须实现同一个接口,这样代理类才能在需要的时候代替委托类对象,执行委托类的方法. interface Solution{ public void doSomething(); } //委托类Demo实现了接口 class Dem

黑马程序员——Java基础--IO流(一)---字符流和字节流

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.IO流的介绍及体系 IO流用来处理设备之间的数据传输.java对数据的操作是通过流的方式.java用于操作流的对象都在IO包中. 输入流和输出流相对于内存设备而言:将外设中的数据读取到内存中:输入.将内存中的数据写出到外设中:输出. 流按照操作数据分为两种:字节流和字符流. 字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作

黑马程序员——Java基础---IO(二)---IO字节流、流操作规律

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! -------   字节流 一.概述 1.字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件. 2.由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作. 3.读写字节流:Inpu

黑马程序员——Java基础--IO流(一)---File类以及其他流对象

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.File类 File类是将文件系统中的文件和文件夹封装成了对象.提供了更多的属性和行为可以对这些文件和文件夹进行操作.这些是流对象办不到的,因为流只操作数据.File对象可以作为参数传递给流对象的构造函数.File 类的实例是不可变的:也就是说,一旦创建,File 对象表示的抽象路径名将永不改变. 1.File类中的方法 (1).File类的构造方法以及字段 1 new File(Stri

黑马程序员——Java基础——IO流(二)——File类、Properties类、打印流、序列流

第一件 File类 一.File类 a.用于将文件或者文件夹封装成对象 b.方便对文件与文件夹的属性信息进行操作 c.File对象可以作为参数传递给流的构造函数 d.了解File类中的常用方法 二.File对象的创建 a.File f=new File("a:\\a.txt"): b.File f2=new File("C:\\abc","a.txt");//分开的好处是后一个参数能够使用其他对象如string c.File d=new File

黑马程序员——Java基础---IO(三)--File类、Properties类、打印流、序列流(合并流)

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- File类 一.概述 1.File类:文件和目录路径名的抽象表现形式 2.特点: 1)用来将文件或文件夹封装成对象 2)方便于对文件与文件夹的属性信息进行操作,因此是对流操作的一种补充 3)File类的实例是不可变的:也就是说,一旦创建,