操作对象
ObjectInputStream与ObjectOutputStream
可直接操作对象的流。
对象本身存在于堆内存中,当程序运行完时,内存被释放,对象也不存在了。
可以使用流将对象存于硬盘上。
import java.io.*;
class Person implements Serializable
{
public static final long serialVersionUID = 36L;
//给定id,定义固定标识,使区别化方便。
private String name;
transient int age; //加上关键字transient成员同样不能被序列化,而保证
//成员的值在堆内存中存在而不在文本中存在
static String country = "cn";//静态是不能被序列化的。所以打印的还是cn
Person(String name,int age,String country)
{
this.name = name;
this.age = age;
this.country = country;
}
public String toString()
{
return name+"::"+age+"::"+country;
}
}
import java.io.*;
/*
使Person继承Serializable,使其序列化。ObjectStreamDemo中的Person类对象的序列号是Java根
据Person中的成员获取而来的。若将Person类中的成员改变,对应的对象的序列号会改变继而发生异常。
但如果自己定义一个id,既可避免。*/
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();
//编译时抛出ClassNotFoundException异常,将跑出IOE改为E
System.out.println(p);
ois.close();
}
public static void writeObj() throws IOException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
//讲一个对象写入文件中
//对象new Person("lisi",23);应存在于内存中,而现在直接写到硬盘上了。
oos.writeObject(new Person("lisi02",43,"UK"));//lisi,43,cn
//类Person中country是static,静态不能被序列化。
oos.close();
}
}
/*
管道流
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);
//此处读到上面PipedInputStream in中的数据
System.out.println(s);
in.close();
}
catch(IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
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 is coming".getBytes());
//此处数据写到上面Read—>Read的PipedInputStream in中
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包中的成员,因它具备读和写的功能。
其内部也封装了一个数组,而且通过只针对数组的元素进行操作。
可以通过getFilePoint获取指针位置,
同时可以通过seek改变指针位置。
其实完成读写的原理是其内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读 r;读写 rw等
如果模式为只读 r,不会创建文件,会去读取一个已存在的文件,若文件不存在,则会出现异常。
如果模式为rw,而且该对象的构造函数要操作的文件不存在,会自动创建文件,若存在也不会覆盖。
*/
ort java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile();
//readFile();
writeFile_2();
}
public static void readFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//文件中的数据在数组中,可以通过调整指针来取出数据。
//调整对象中的指针
//raf.seek(8*0);//指向李四
//raf.seek(8*1); //指向王五
//跳过指定字节数,但不能往回跳
raf.skipBytes(8);
byte[] buf = new byte[4];//用于装人名,人名4个字节
raf.read(buf);//将ran.txt读到buf中
String name = new String(buf);
int age =raf.readInt(); //readInt();从文件读取一个有符号的32位整数
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");//不会覆盖文件
//getBytes(); 使用平台默认的字符集将String编码为byte序列并存到一个新的byte[]中
raf.write("李四".getBytes());
//只写出int类型最低的8位(二进制).
//当数据达到一定时会发生数据丢失,256——1 00000000。
//一个int型对应4个字节,一个字节对应8位
raf.writeInt(97);//按四个字节将 int 写入该文件,先写高字节
raf.write("王五".getBytes());
raf.writeInt(100);
raf.close();
}
public static void writeFile_2() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
//不会覆盖文件ran.txt
raf.seek(8*3);//会在王五后面留一个位置.若是8*0,会将李四替换
raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();
}
}
IO包中的其他类
操作基本数据类型
DataInputStream和DataOutputStream
操作字节数组
ByteArrayInputStream和ByteArrayOutputStream
可直接操作字节数组中数据的流对象
操作字符数组
CharArrayReader和CharArrayWrite
操作字符串
StringReader和StringWriter
/*
DataInputStream和DataOutputStream
可以用于操作基本数据类型的数据的流对象。
*/
import java.io.*;
class DataStreamDemo
{
public static void main(String[] args) throws IOException
{
//writeData();
//readData();
//writeUTFDemo();
readUTFDemo();
}
public static void writeUTFDemo() throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
dos.writeUTF("你好");
dos.close();
OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8");
osw1.write("你好");
osw1.close();
OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
osw2.write("你好");
osw2.close();
}
public static void readUTFDemo() throws IOException //只能用对应的方法(表)读取
{
DataInputStream dis = new DataInputStream(new FileInputStream("utfdate.txt"));
String s = dis.readUTF();
sop(s);
dis.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();
sop("num:"+num);
sop("b:"+b);
sop("d:"+d);
dis.close();
}
public static void writeData() throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
//FileOutputStream 流
dos.writeInt(234);//4个字节
dos.writeBoolean(true);//1个字节
dos.writeDouble(9887.5432);//8个字节
dos.close();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
字符编码
字符流的出现是为了方便操作字符数据,原因是字符流内部加入了编码表。
更重要的是加入了编码转换。
字节和字符之间的转换需要通过两个对象——InputStream、OutputStream。这
两个的对象中是加入了编码表的流对象。
还有PrintStream和printWriter可以加入编码表。但只能打印不能读取。
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("GBK2.txt"),"GBK");
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf,0,len);
sop(str);
isr.close();
}
public static void writeText() throws IOException
{
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("GBK2.txt"));
osw.write("你好");
osw.close();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
import java.util.*;
/*
编码:字符串变成字节数组
String -->byte[]; str.getBytes(CharsetName); 按指定字符集
解码:字节数组变成字符串
byte[] -->String; new String(byte[],CharsetName);
*/
class EncodeDemo
{
public static void main(String[] args) throws Exception
{
//method_1();
method_2();
}
public static void method_1() throws Exception
{
String s = "你好";
//byte[] b1 = s.getBytes();//[-60,-29,-70,-61]
byte[] b1 = s.getBytes("GBK");// 会抛出不支持编码异常
//[-60,-29,-70,-61] 默认编码即GBK
String s1 = new String(b1);
System.out.println("s1="+s1);
System.out.println("b1:"+Arrays.toString(b1));
}
public static void method_2() throws Exception
{
/*
你好——(编码)GBK——[-60,-29,-70,-61]——(解码)ISO8859-1——????-
-(编码)ISO8859-1——[-60,-29,-70,-61]——(解码)GBK——你好
*/
String s = "你好";
byte[] b1 = s.getBytes("GBK");//编码
sop("b1:"+Arrays.toString(b1));
String s1 = new String(b1,"ISO8859-1");//解码
sop("s1:"+s1);
byte[] b2 = s1.getBytes("ISO8859-1");
sop("b2:"+Arrays.toString(b2));
String s2 = new String(b2,"GBK");
sop("s2:"+s2);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
//加入编码表后是会报异常的
class EncodeDemo2
{
public static void main(String[] args) throws Exception
{
String s = "联通";
byte[] by = s.getBytes("gbk");
for(byte b:by)
{
System.out.println(Integer.toBinaryString(b&255));
}
}
}
小结
最新推荐文章于 2023-03-22 22:10:16 发布