打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印。字节打印流:
PrintStream
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
字符打印流:
PrintWriter
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
4,字符输出流,Writer。
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);
//PrintWriter out = new PrintWriter(System.out,true);
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
bufr.close();
}
}
序列流:
SequenceInputStream
表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
可以将多个流对象合并成一个流对象。
构造方法:
SequenceInputStream(InputStream s1, InputStream s2) ;通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
SequenceInputStream(Enumeration<? extends InputStream> e) ;通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
将1.txt,2.txt,3.txt合并成4.txt。
import java.util.*;
import java.io.*;
class Test
{
public static void main(String[] args) throws IOException
{
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> e=v.elements();
SequenceInputStream sis=new SequenceInputStream(e);
FileOutputStream fos=new FileOutputStream("4.txt");
byte[] b=new byte[1024];
int len;
while((len=sis.read(b))!=-1)
{
fos.write(b,0,len);
}
sis.close();
fos.close();
}
}
切割文件
一个输入流对应多个输出流:
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比Vector效率高
for(int x=1; x<=3; x++)
{
al.add(new FileInputStream("c:\\splitfiles\\"+x+".part"));
}
final Iterator<FileInputStream> it = al.iterator();
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("c:\\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("c:\\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("c:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
操作对象:
ObjectInputStream 与 ObjectOutputStream
被操作的对象需要实现Serializable(标记接口);
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。
import java.util.*;
import java.io.*;
class Test
{
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();
System.out.println(p);
ois.close();
}
public static void writeObj()throws IOException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
oos.writeObject(new Person("lisi",39,"dy"));
oos.close();
}
}
class Person implements Serializable
{
public static final long serialVersionUID = 42L;//给类固定一个标识
private String name;
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
输入输出可以直接连接,通过结合线程使用
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 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);
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);
Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
RandomAccessFile
该类不是算是IO体系中子类。而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。应用在多线程中。
完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,读写rw等。
如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
Java API:此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
方法:
skipBytes();//跳过指定的字节数,只能往后跳。等
import java.io.*;
class Test
{
public static void main(String[] args) throws Exception
{
writeFile();
writeFile_2();
readFile();
}
public static void readFile()throws IOException //读取打印信息
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
for(int i=0;i<11;i++)
{
raf.seek(8*i);
byte[] b=new byte[4];
raf.read(b);
String name=new String(b);
int age=raf.readInt();
System.out.println("name="+name+",age="+age);
}
raf.close();
}
public static void writeFile_2()throws IOException //写入信息2
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*10);//可以随便写位置,随便覆盖位置上的内容。
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);
raf.write("王五".getBytes());
raf.writeInt(258);
raf.close();
}
}
DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象。
oid writeUTF(String str) 以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。
import java.io.*;
class Test
{
public static void main(String[] args) throws Exception
{
writeFile();
read();
Demo();
}
public static void Demo()throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("UTFdemo.txt"));
dos.writeUTF("发货个人规划的分割肉哥哥的非农赶紧的搜狗奇偶");
dos.close();
DataInputStream dis=new DataInputStream(new FileInputStream("UTFdemo.txt"));
System.out.println(dis.readUTF());
dis.close();
}
public static void read()throws IOException
{
DataInputStream dis=new DataInputStream(new FileInputStream("DataOutputStream.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 writeFile()throws IOException //写入信息
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("DataOutputStream.txt"));
dos.writeInt(2134);
dos.writeBoolean(true);
dos.writeDouble(3253.453);
dos.close();
}
}
操作字节数组
ByteArrayInputStream :在构造的时候,需要接收数据源,而且数据源是一个字节数组。ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪
read
方法要提供的下一个字节。关闭
ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何
IOException。
ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了 可变长度的字节数组。这就是数据目的地。此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用
toByteArray()
和
toString()
获取数据。关闭
ByteArrayOutputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何
IOException。
因为这两个流对象都操作的数组,并没有使用系统资源。所以,不用进行close关闭。
在流操作规律讲解时:
源设备,
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。
用流的读写思想来操作数据。
import java.io.*;
class Test
{
public static void main(String[] args) throws Exception
{
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());
ByteArrayOutputStream bos = new 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"));
}
}