操作基本數(shù)據(jù)類型的流
- 操作基本數(shù)據(jù)類型
- DataInputStream
- DataOutputStream
操作基本數(shù)據(jù)類型的流可以讀寫基本數(shù)據(jù)類型的數(shù)據(jù),我們來寫一個簡單的讀寫例子
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
// 寫
write();
// 讀
read();
}
private static void read() throws IOException {
// DataInputStream(InputStream in)
// 創(chuàng)建數(shù)據(jù)輸入流對象
DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));
// 讀數(shù)據(jù)
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
char c = dis.readChar();
boolean bb = dis.readBoolean(); // 釋放資源
dis.close();
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(c);
System.out.println(bb);
}
private static void write() throws IOException {
// DataOutputStream(OutputStream out)
// 創(chuàng)建數(shù)據(jù)輸出流對象
DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt")); // 寫數(shù)據(jù)
dos.writeByte(10);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000);
dos.writeFloat(12.34F);
dos.writeDouble(12.56);
dos.writeChar('a');
dos.writeBoolean(true);
// 釋放資源
dos.close();
}
}
內(nèi)存操作流
- 操作字節(jié)數(shù)組
- ByteArrayInputStream
- ByteArrayOutputStream
- 操作字符數(shù)組
- CharArrayReader
- CharArrayWrite
- 操作字符串
- StringReader
- StringWriter
內(nèi)存操作流一般用于處理臨時信息,因?yàn)榕R時信息不需要保存既穆,使用后就可以刪除赎懦。
public class ByteArrayStreamDemo {
public static void main(String[] args) throws IOException {
// 寫數(shù)據(jù) --字節(jié)數(shù)組輸出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 寫數(shù)據(jù)
for (int x = 0; x < 10; x++) {
baos.write(("hello" + x).getBytes());
}
// 釋放資源
// 通過查看源碼我們知道這里什么都沒做,所以根本需要close()
// baos.close();
// public byte[] toByteArray()
byte[] bys = baos.toByteArray();
// 讀數(shù)據(jù)
// ByteArrayInputStream(byte[] buf)
ByteArrayInputStream bais = new ByteArrayInputStream(bys);
int by = 0;
while ((by = bais.read()) != -1) {
System.out.print((char) by);
}
// bais.close();
}
}
上面我們寫英文字符數(shù)據(jù)可以運(yùn)用字節(jié)數(shù)組的輸出流ByteArrayOutputStream幻工,如果我們寫入中文數(shù)據(jù)的話就要用操作字符數(shù)組的流CharArrayWrite了励两。那么,剩下的操作字符數(shù)組和操作字符串的例子就不做演示了囊颅,大家可以自己練練当悔。
打印流
- 打印流分為兩類
- 字節(jié)流打印流 PrintStream
- 字符打印流 PrintWriter
打印流的特點(diǎn):
- 只有寫數(shù)據(jù)的傅瞻,沒有讀取數(shù)據(jù)。只能操作目的地盲憎,不能操作數(shù)據(jù)源嗅骄。
- 可以操作任意類型的數(shù)據(jù)。
- 如果啟動了自動刷新饼疙,能夠自動刷新溺森。
- 該流是可以直接操作文本文件的。
我們來回憶一下哪些流對象是可以直接操作文本文件的呢?
- FileInputStream
- FileOutputStream
- FileReader
- FileWriter
- PrintStream
- PrintWriter
- 看API,查流對象的構(gòu)造方法窑眯,如果同時有File類型和String類型的參數(shù)屏积,一般來說就是可以直接操作文件的。
打印流的特點(diǎn)有一條是可以操作任意類型的數(shù)據(jù)磅甩,可是我們看方法炊林,他的write方法不可以寫boolean類型的,所以我們就去看看他的api更胖,看有什么新方法铛铁,當(dāng)然是有的隔显,我們就直接來學(xué)習(xí)他的新方法吧却妨。
可以操作任意類型的數(shù)據(jù)。有兩種方法括眠,他們就什么區(qū)別呢彪标?
- print() 不會換行,不會自動刷新數(shù)據(jù)掷豺。
- println() 不僅僅自動刷新了數(shù)據(jù)捞烟,還實(shí)現(xiàn)了數(shù)據(jù)的換行。
隨機(jī)訪問流
RandomAccessFile
概述:RandomAccessFile類不屬于流当船,是Object類的子類题画。但它融合了InputStream和OutputStream的功能。支持對隨機(jī)訪問文件的讀取和寫入德频。
這個類我以前寫視頻斷點(diǎn)上傳的時候就用到了苍息,很強(qiáng)大的一個類,我們下面來學(xué)習(xí)下壹置。
public RandomAccessFile(String name,String mode):第一個參數(shù)是文件路徑竞思,第二個參數(shù)是操作文件的模式。模式有四種钞护,我們最常用的一種叫”rw”,這種方式表示我既可以寫數(shù)據(jù)盖喷,也可以讀取數(shù)據(jù)下面我們就用這個類來寫一個簡單的讀寫操作的例子
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建隨機(jī)訪問流對象
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
// 寫入數(shù)據(jù)
raf.writeInt(100);
raf.writeChar('a');
raf.writeUTF("中國");
raf.close();
}
}
運(yùn)行程序,然后我們繼續(xù)來寫讀的方法
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建隨機(jī)訪問流對象
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
int i = raf.readInt();
System.out.println(i);
// 該文件指針可以通過 getFilePointer方法讀取难咕,并通過 seek 方法設(shè)置课梳。 System.out.println("當(dāng)前文件的指針位置是:" + raf.getFilePointer());
char ch = raf.readChar();
System.out.println(ch);
System.out.println("當(dāng)前文件的指針位置是:" + raf.getFilePointer()); String s = raf.readUTF();
System.out.println(s);
System.out.println("當(dāng)前文件的指針位置是:" + raf.getFilePointer());
// 我就要讀取a距辆,怎么辦呢?
raf.seek(4);
ch = raf.readChar();
System.out.println(ch);
}
}
合并流
SequenceInputStream
概述:SequenceInputStream類可以將多個輸入流串流在一起,合并為一個輸入流暮刃,因此挑格,該流也被稱為合并流。
- SequenceInputStream的構(gòu)造方法
- SequenceInputStream(InputStream s1, InputStream s2)
- SequenceInputStream(Enumeration < ? extends InputStream> e)
- 把多個文件的內(nèi)容寫入到一個文本文件
以前我們只是將一個文件的內(nèi)容復(fù)制到另外一個文件中沾歪,現(xiàn)在這個合并流可以實(shí)現(xiàn)將兩個及多個文件的內(nèi)容復(fù)制到一個文件中了漂彤,我們來實(shí)現(xiàn)以下吧
// 需求:把ByteArrayStreamDemo.java和DataStreamDemo.java的內(nèi)容復(fù)制到Copy.java中
public class SequenceInputStreamDemo {
public static void main(String[] args) throws IOException {
InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); InputStream s2 = new FileInputStream("DataStreamDemo.java"); SequenceInputStream sis = new SequenceInputStream(s1, s2); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
// 讀寫操作
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
sis.close();
}
}
運(yùn)行程序你會在Copy.java文件中看到ByteArrayStreamDemo.java和DataStreamDemo.java文件的內(nèi)容都復(fù)制到了Copy.java文件中。
那么怎么合并3個或者三個以上的文件操作呢灾搏?
// 需求:把下面的三個文件的內(nèi)容(ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java)復(fù)制到Copy.java中
public class SequenceInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// SequenceInputStream(Enumeration e)
// 通過簡單的回顧我們知道了Enumeration是Vector中的一個方法的返回值類型挫望。
// Enumeration<E> elements()
Vector<InputStream> v = new Vector<InputStream>();
InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); InputStream s2 = new FileInputStream("CopyFileDemo.java"); InputStream s3 = new FileInputStream("DataStreamDemo.java"); v.add(s1);
v.add(s2);
v.add(s3);
Enumeration<InputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
// 如何寫讀寫呢,其實(shí)很簡單狂窑,你就按照以前怎么讀寫媳板,現(xiàn)在還是怎么讀寫 byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
sis.close();
}
}
運(yùn)行程序,我們會在Copy.java文件中看到那三個文件的內(nèi)容泉哈,我們要是想合并四個或者以上的文件蛉幸,只需要繼續(xù)將文件創(chuàng)建輸入流對象然后添加在Vector集合中就可以實(shí)現(xiàn)了。
序列化流
- 序列化流ObjectOutputStream
- 反序列化流ObjectInputStream
序列化流:把對象按照流一樣的方式存入文本文件或者在網(wǎng)絡(luò)中傳輸丛晦。對象 –> 流數(shù)據(jù)(ObjectOutputStream)
反序列化流:把文本文件中的流對象數(shù)據(jù)或者網(wǎng)絡(luò)中的流對象數(shù)據(jù)還原成對象奕纫。流數(shù)據(jù) –>對象(ObjectInputStream)
//我們先寫一個實(shí)體類,并實(shí)現(xiàn)序列化接口
public class Person implements Serializable {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
//寫入數(shù)據(jù)
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException{
// 創(chuàng)建序列化流對象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
// 創(chuàng)建對象
Person p = new Person("阿杜", 25);
// public final void writeObject(Object obj)
oos.writeObject(p);
// 釋放資源
oos.close();
}
}
//讀取數(shù)據(jù)
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException{
// 創(chuàng)建反序列化對象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "oos.txt"));
// 還原對象
Object obj = ois.readObject();
// 釋放資源
ois.close();
// 輸出對象
System.out.println(obj);
}
}
輸出結(jié)果:Person [name=阿杜, age=25]
我們也可以這樣理解
對象序列化是將對象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)倪^程烫沙。一般的格式是與平臺無關(guān)的二進(jìn)制流匹层,可以將這種二進(jìn)制流持久保存在磁盤上,也可以通過網(wǎng)絡(luò)將這種二進(jìn)制流傳輸?shù)搅硪粋€網(wǎng)絡(luò)結(jié)點(diǎn)锌蓄。對象反序列化升筏,是指把這種二進(jìn)制流數(shù)據(jù)還原成對象。