点击打开链接 点击打开链接 点击打开链接 点击打开链接 点击打开链接
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 v=new Vector();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("3.txt"));
//得到集合的Enumeration,作为参数传递得合并流的构造函数
Enumeration 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 v=new ArrayList();
v.add(new FileInputStream("4.part"));
v.add(new FileInputStream("4.part"));
v.add(new FileInputStream("4.part"));
Iterator it=v.iterator();
Enumeration 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() |
int |
read() |
int |
read(byte[] b, int off, int len) |
void |
reset() |
long |
skip(long n) |
②ByteArrayOutptuStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。源和目的都是内存,用流的读写思想来操作数组。
方法摘要 |
|
void |
close() 关闭 ByteArrayOutputStream 无效。 |
void |
reset() |
int |
size() 返回缓冲区的当前大小。 |
byte[] |
toByteArray() |
String |
toString() |
String |
toString(String charsetName) |
void |
write(byte[] b, int off, int len) |
void |
write(int b) 将指定的字节写入此 byte 数组输出流。 |
void |
writeTo(OutputStream out) |
练习
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”