PrintWriter与PrintStream:可以直接操作输入流和文件。
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
与其他输出流不同,PrintStream永远不会抛出IOException。
PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。
在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。
字节打印流
PrintStream
构造函数可以接受的函数类型
1、file对象
2、字符串路径 String
3、字节输出流 OutputStream
字符打印流
PrintWriter
构造函数可以接受的函数类型
1、file对象
2、字符串路径 String
3、字节输出流 OutputStream
4、字符输出流 Writer
示例
import java.io.*;
public class H_15PrintDemo {
public static void main(String[] args) throws IOException
{
BufferedReader bufr=new BufferedReader(newInputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
//PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("a.txt")),true);
//直接传入true 可以自刷新 不能刷新到文件 将文件封装成流对象
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toLowerCase());
out.flush();//不刷新会再关闭后一起打印
}
out.close();
bufr.close();
}
}
2. 合并流SequenceInputStream
import java.util.*;
import java.io.*;
public class H_16SequenceInputStream {
public static void main(String[] args) throws IOException {
Vector<FileInputStream> v=new Vector<FileInputStream>();//创建一个集合,添加文件
v.add(new FileInputStream("info.txt"));
v.add(new FileInputStream("java.txt"));
v.add(new FileInputStream("buf.txt"));
Enumeration<FileInputStream> en=v.elements();
SequenceInputStream sis=new SequenceInputStream(en);//传入一个枚举对象
FileOutputStream fos=new FileOutputStream("seq.txt");//合并的文件
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
3. 切割函数与高效合并
public static void splitFile() throws IOException
{
FileInputStream fis=new FileInputStream("TBBT_copy2.png");
FileOutputStream fos=null;
byte[] buf=new byte[1024*1024];//设置文件大小
int len=0;
int count=1;
while((len=fis.read(buf))!=-1)
{
fos=new FileOutputStream((count++)+".part");//按大小切割文件
fos.write(buf, 0, len);
fos.close();
}
fis.close();
}
public static void merge() throws IOException
{
ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
for(int x=1;x<=3;x++)
{
al.add(new FileInputStream(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();
}
};
//Enumeration<FileInputStream> en = Collections.enumeration(al);
//也可以使用Collections的方法
SequenceInputStream sis=new SequenceInputStream(en);
BufferedOutputStream bos=new BufferedOutputStream(newFileOutputStream("copy.png"));
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
bos.write(buf, 0, len);
bos.flush();
}
bos.close();
sis.close();
}
}
4. 序列化流 ObjectOutputStream
1、序列化 即存储起来 不会因为程序消亡而消亡
2、成员必须实现序列化类Serializable才可以进行序列化
静态成员是不能被序列化的
非静态成员不想被序列化的话,加上transient int age//临时的 中转的意思
通常保存成 类名.类型名
3、如果第一次序列化后,
如果改变Person 成员属性 uid 会改变
再次读取原编译文件会报错,因为uid不同。
4、自定义uid
static final long serialVersionUID=42L
那么序列号都相同,修改后也不会报错。
import java.io.*;
public class H_01ObjectOutputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
writeObj();//序列化后的文件是看不懂的
readObj();
}
public static void readObj() throws IOException, ClassNotFoundException
{
ObjectInputStream ois=new ObjectInputStream(newFileInputStream("obj.txt"));
//通常命名为obj.object,此处做演示打开看看
Object obj=ois.readObject();
System.out.print(obj);
ois.close();
}
public static void writeObj() throws IOException
{
ObjectOutputStream oos=new ObjectOutputStream(newFileOutputStream("obj.txt"));
oos.writeObject(new Person("lisi",39));
oos.close();
}
}
class Person implements Serializable //可序列化的 ,该接口没有方法 仅仅是标记
{
String name;
int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String toString()
{
return name+" "+age;
}
}
5. 管道流
集合涉及多线程:Properties
流对象涉及多线程:管道流
创建需要多线程的读方法和写方法。
read中构造函数传入读取管道流
write中构造函数传入写入管道流
分别重写run方法及读取方法和写入方法。
主函数
new 管道读取流和管道写入流对象
需要建立关联 in.connect(out);
分别传入read和write构造函数
新建线程对象,传入read和write对象
import java.io.*;
public class H_02PipeInputStream {
public static void main(String[] args) throws IOException
{
PipedInputStream in=new PipedInputStream();
PipedOutputStream out=new PipedOutputStream();
in.connect(out);//关联
Read read=new Read(in);//传入对象
Write write=new Write(out);
new Thread(read).start();//启动线程
new Thread(write).start();
}
}
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public void run()
{
try {
byte[] buf=new byte[1024];
int len=in.read(buf);
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 {
Thread.sleep(3000);
out.write("piped ce shi ".getBytes());
out.close();
} catch (Exception e)
{
throw new RuntimeException("管道流写入失败");
}
}
}
6. 随机访问文件
1、 RandomAccessFile
该类不算是IO体系中的子类,而是直接继承自Object。但是它是IO体系的成员,具备读写功能。
内部封装了一个数组,通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置
同时可以通过seek改变指针的位置
读写的原理是内部封装了字节输入流和输出流
2、 通过构造函数可以看出:该类只能操作文件
而且后面有四种模式 r rw rws rwd 输错会报参数错误异常
如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常
如果模式rw,操作的文件不存在,会自动创建,如果存在,则不会覆盖。
3、 raf.write(259);//只能写入最低八位,会导致数据丢失
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
//调整对象上的指针
raf.seek(10);//按字节数来获取 从第十个直接开始
//跳过指定的字节数
raf.skipBytes(4);//跳过四个字节 但是不能往前跳
作用: 实现数据的分段写入
将数据分段:用不同的线程负责不同段的写入
应用:程序的分段下载
4、 重点特点:
有模式限制
seek设置读取位置
可以直接操作基本数据类型
import java.io.*;
public class H_03RandomAccessFile {
public static void main(String[] args) throws IOException {
//writeFile();
writeFile_2();
readFile();
}
public static void readFile() throws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
//调整对象上的指针
//raf.seek(10);//按字节数来获取 从第十个直接开始
//跳过指定的字节数
raf.skipBytes(4);//跳过四个字节 但是不能往前跳
byte[] buf=new byte[4];
raf.read(buf);
String s=new String(buf);
System.out.println(s);
int age=raf.readInt();
System.out.println(age);
raf.close();
}
public static void writeFile_2() throws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
raf.write("lisi".getBytes());
raf.writeInt(97);
raf.seek(8*4);//跳过四个8位写入
raf.write("zhangsan".getBytes());
raf.close();
}
public static void writeFile() throws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
raf.write("lisi".getBytes());
raf.write(7);//只能写入最低八位,会导致数据丢失
raf.writeInt(3);//写入四位,前面是空格
raf.write("haha".getBytes());
raf.close();
}
}
7. 数据流DataInputStream DataOutputStream
可以用于操作基本数据类型
直接读或者取整数、小数、布尔值等等。
特殊方法 writeUTF readUTF
修改版的utf编码
写入两个汉字是 8字节
utf正常是6字节
gbk是4字节
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class H_04DataStreamDemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//writeData();
//readData();
writeUTFDemo();
readUTFDemo();
OutputStreamWriter osw=new OutputStreamWriter(newFileOutputStream("GBK.txt"));
osw.write("你好");
osw.close();
}
public static void readUTFDemo() throws IOException
{
DataInputStream dis=new DataInputStream(newFileInputStream("utfdata.txt"));
String s=dis.readUTF();
System.out.println(s);
}
public static void writeUTFDemo() throws IOException
{
DataOutputStream dos=new DataOutputStream(newFileOutputStream("utfdata.txt"));
dos.writeUTF("你好");
dos.close();
}
public static void readData() throws IOException
{
DataInputStream dis=new DataInputStream(newFileInputStream("Data.txt"));
//必须按照写入的顺序读取
int num=dis.readInt();
double dou=dis.readDouble();
boolean bool=dis.readBoolean();
System.out.println(num);
System.out.println(dou);
System.out.println(bool);
}
public static void writeData() throws IOException
{
DataOutputStream dos=new DataOutputStream(newFileOutputStream("data.txt"));
dos.writeInt(333);
dos.writeDouble(988989.34343);
dos.writeBoolean(true);
dos.close();
}
}
8. 操作字节数组流
ByteArrayInputStream与ByteArrayOutputStream
ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组
因为这两个流对象都操作字节数组,并没有使用系统资源,所以不用close关闭,也不会报IO异常
import java.io.*;
public class H_05ByteArrayStream {
public static void main(String[] args) throws IOException{
//数据源
ByteArrayInputStream bis=newByteArrayInputStream("abcedef".getBytes()); //数据目的
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int ch=0;
while((ch=bis.read())!=-1)
{
bos.write((char)ch);
}
System.out.println(bos.size());//7
System.out.println(bos.toString().toUpperCase());//ABCEDEF
bos.writeTo(new FileOutputStream("byte.txt"));//写入文件
}
}