黑马程序员-常见的一些流和编码表

对象的序列化(对象要实现Serializable序列化接口,类似实现comparable )

1.操作对象的流:ObjectOutputStream ObjectInputStream

ObjectOutputStream :

将 Java对象的基本数据类型和图形写入 OutputStream。

通过在流中使用文件可以实现对象的持久存储。

构造函数:ObjectOutputStream(OutputStream
out)//初始化时要有目的

方法:

writeObject(Object
obj);Object对象要实现Serializable接口。该接口无任何方法,被称为标记

ObjectInputStream
:将ObjectOutputStream写入的基本数据和对象进行反序列化。

构造函数:

ObjectInputStream(InputStream in)
;指定源

Object】 readObject() ;读取类,返回对象。

注意:

对象是字节码文件。

读写object的对象必须是同一个对象。序列号相等(序列号可以自定义,

如:static final long serialVersionUID =
42L)。

静态是不能被序列化存储的,因为静态是在方法区,序列化只是将对内存的序列化。

transient关键字,可以保证被修饰的变量只在堆中,不被序列化存储。

  //写

     File fi = new File("2101.txt");

OutputStream os = new FileOutputStream(fi);//对象不是纯文本,是字节码文件

ObjectOutputStream oos = new ObjectOutputStream(os);

oos.writeObject(new person("lisi",20,"cn"));//是new
person()//假设静态cn被改了,方法区静态变量会变吗 会

//读

File fi = new File("2101.txt");

FileInputStream fis = new FileInputStream(fi);

ObjectInputStream ois = new ObjectInputStream(fis);

person p = (person)ois.readObject();

2.管道流:涉及多线程的IO流对象。(四个流对象都有,inputStream,outputStream,reader,writer)

通常读取流和写入流之间是没有关系的,只有存在中转站的情况下,才存在联系。

如:写入流写到数组中,读取流从数组读取。但是管道流可以实现不需要中转站,

将读取流和写入流的管道接在一起,类似一根管道,一端读,一端写。

但是会出问题:先读呢,还是先写?

我们会用两个现场来操作,通常,数据由某个线程写入
PipedOutputStream 对象,并由其他线程从连接的PipedInputStream读取。

不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。因为read方法是堵塞时方法,如果读不到数据,就等待。

与合并流(sequenceInputStream)的区别:合并流只有一个sequenceInputStream,是将多个输入流合并到一起。管道流是将输入流和输出流连接到一起,
多线程的实现:没写数据之前,即使读到也等待,直到读到数据。

构造方法:

PipedOutputStream(PipedInputStream
snk)

创建连接到指定管道输入流的管道输出流。

也可以这样

PipedOutputStream()

创建尚未连接到管道输入流的管道输出流。

用connect(PipedInputStream snk) 连接两个流

将此管道输出流连接到接收者。

ObjectInputStream(InputStream in)
//制定读取的文件

创建从指定 InputStream 读取的
ObjectInputStream。

常用方法:只能读取和写入字节或字节数组。

class writedemo implements Runnable{

private  PipedInputStream pis;

writedemo(PipedInputStream
pis){//InputStream不可以放在这,否则this.InputStream=PipedInputStream;

this.pis=pis;

}

public void
run(){

byte[] bys = new byte[1024];

int len = 0;

while ((len=pis.read(bys))!=-1)   {
//没有数据,线程等待。pipedoutputStream,写入,若再夺得线程,读取。

Thread.sleep(3000);

String str = new
String(bys,0,len);//获取数组。

System.out.println(str);

}

pis.close();

}

class readdemo implements Runnable{

PipedOutputStream pos;

readdemo(PipedOutputStream pos){

this.pos= pos;

}

public void
run(){

pos.write("管道来2122了".getBytes());

}

}

class  day2102{

public static void main(String[] args) throws Exception {

PipedInputStream pis = new PipedInputStream();

PipedOutputStream pos = new PipedOutputStream();

pis.connect(pos);

writedemo wd = new writedemo(pis);

readdemo rd = new readdemo(pos);

Thread t1 = new Thread(wd);

Thread t2 = new Thread(rd);

t1.start();

t2.start();

}

}

3.随机访问文件 RandomAccessFile 不是IO子类

功能:此类的实例支持对随机访问文件的读取和写入。可以用seek()方法来访问数据,并进行读写了。

这些数据的大小不必相同;但是其大小和位置必须是可知的

但它是IO包中的成员,因为它具备读写功能。部封装了一个byte数组,而且通过指针对数组的元素进行操作。

可以通过getFilePointer获取真正位置,同时可以通过seek改变指针的位置。

原理:内部封装了字节输入流和字节输出流。

构造函数:

RandomAccessFile(File file, String mode)

创建从中读取和向其中写入(可选)的随机访问文件流,也可以指定文件名称。

局限:通过构造函数可以发现,该类只能操作文件。而且操作文件还有模式Mode:r,只读  rw,读写等

注意:

1.如果模式为只读r,不会创建文件,只会去读取一个已经存在的文件,

如果该文件不存在,则会出现异常

2.如果模式为rw,操作的文件不存咋,会自动创建。如果有则【不会覆盖】。

用处:可以通过多线程实现数据的分段写入。类似迅雷。通过分段规律实现多线程输入。

IO中唯一一个。数据分段,有规律。

常见方法:

int
readInt(),readDouble(),readLong().....

writeInt(int
v),write(long)......

特殊方法:

readLine()

void seek(long pos)

设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。

skipBytes(int n) //只能往后走,不能回头

尝试跳过输入的 n
个字节以丢弃跳过的字节。

RandomAccessFile ra1 = new RandomAccessFile("2014.txt","rw");

//ra1.seek(8*2);//跳过8*2个字节

//ra1.write("lisi".getBytes());

//ra1.writeInt(97);//write()存储低八位

//ra1.writeInt(97);//存入4个8位

ra1.skipBytes(8*2);

String s =ra1.readLine();

System.out.println(s);

4.可以操作基本数据类型的流对象:DataOutputStream, DataInputStream 。

数据输出流将基本 Java 数据类型写入输出流中

特点:通常数据类型输出流会按照一定的格式将数据输出,必须按指定好的格式保存才可以用输入流读取进来。

DataOutput 接口、DataInput 接口,这两个接口的操作彼此对应

构造函数:

DataOutputStream(OutputStream out)

writeUTF(String str) //只能以dataInputStream读取。转换流不可以。String :要写入的字符串。

以与机器无关方式使用 UTF-8
修改版编码将一个字符串写入基础输出流。

static 【String】 readUTF()//utf修改版只能由它来读。

DataOutputStream dos = new
DataOutputStream(new FileOutputStream("2104.txt"));

dos.writeBoolean(true);

//    
dos.writeBytes("lisi");

//    
dos.writeChars("zhansan");

dos.writeInt(20);

dos.close();

DataInputStream(InputStream in)

使用指定的底层 InputStream
创建一个 DataInputStream。

boolean readBoolean()

参见 DataInput 的
readBoolean 方法的常规协定。

byte readByte() char readChar() int readInt() double readDouble()

:分别读取8,16,32,64个字节

DataInputStream dis = new
DataInputStream(new FileInputStream("2104.txt"));

Boolean b = dis.readBoolean();

//     byte s 
= dis.readByte();

//数据读反了,乱码。

//     Byte s1 =

//     char  b2
= dis.readChar();

int s = dis.readInt();

dis.close();

System.out.println(b+".."+s);

特有编码

DataOutputStream dos = new DataOutputStream(new
FileOutputStream("21041.txt"));

dos.writeUTF("你好");

DataInputStream dis = new DataInputStream(new FileInputStream("21041.txt"));

String str = dis.readUTF();//返回值

//     System.out.println(str);

dos.close();

(一) ByteArrayInputStream

操作字节数组:该流没有调用底层资 源,流关闭无效,不产生IOExcetion

字节数组(基本流的数组?)--->字节数组(字节数组流)--->

构造方法:ByteArrayInputStream(byte[] buf)

   在构造的时候,需要接受数据源,而且数据源是字节数组。

ByteArrayInputStream:
包含一个内部缓冲区,该缓冲区包含从流中读取的字节

2.ByteArrayOutputStream:该输出流中,数据被写入一个缓冲区数组,该数组随数据的写入自动增加。

构造方法:ByteArrayOutputStream()  创建一个新的 byte 数组输出流。

在构造的时候,不用定义目的,内部数组就是目的。

输出流特有方法:

int size()

返回缓冲区的当前大小。

byte[] toByteArray()

创建一个新分配的 byte 数组。

String toString()

使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。

String toString(String charsetName)

使用指定的
charsetName,通过解码字节将缓冲区内容转换为字符串。

void writeTo(OutputStream out):将数组流中的全部内容写到字节输出流中(文件等)

例如:bos.writeTo(new
FileOutputStream("2104.txt"))//此方法涉及异常。

特点:没有调用底层资源(windows?),不用关闭流,也不会产生IOException

内部封装了数组,它是由字节流到字节流,始终都在内存中操作。

作用:将一个文件读到内存中,先用数组存放起来。而且长度是可变的。

源设备:

键盘(System.in),硬盘(FileStream),内存(ArrayStream)

目的设备:

控制台(System.out),硬盘(FileStream),内存(ArrayStream)

用处:将一个文件,读到内存,并放在数组先存取来。而且,数组长度可变, ArrayStream很方便。

对数组元素的操作:只有设置(设置值,改变)和获取。对应于流中就是写和读。

这就是用流读写的思想操作数组,以后遇到数组,可以封装的该流中。

(二)字符数组流和字符串流。CharArrayReader

CharArrayReader,CharArrayWriter 实现一个可用作字符输入流的字符缓冲区

CharArrayReader(char[] buf)

根据指定的 char 数组创建一个
CharArrayReader。

ByteArrayOutputStream()

创建一个新的 byte 数组输出流。

StringReader,

构造方法:StringReader(String s) 创建一个新字符串
reader。

StringWriter()

使用默认初始字符串缓冲区大小创建一个新字符串
writer。

import java.io.*;

class day2105 {

public static void
arraydemo(){

//数据源

byte[] bys = "adfdfdffa".getBytes()
;

ByteArrayInputStream bis = new ByteArrayInputStream(bys);

//数据目的

ByteArrayOutputStream bos = new ByteArrayOutputStream();

//输入流:读取数据,读入流中,已经在流中的缓冲区,输入输出在管道的两头。

int len =0;

//本身具备数组,可以一个一个接受,read()方法一个一个读取,返回的是读取的字符。·

while ((len =bis.read())!=-1){

bos.write(len);//表示将这个字符写入缓冲区中。

}

//     bis.close();
不用关闭,不用抛

System.out.println(bos.toString());

System.out.println(bos.size());

}

public static void main(String[]
args){

arraydemo();

}

}

/*必须懂

InputStreamReader,OutputStream转换流中加入了编码

PrintStream,printWriter也有,但是只能用于打印。

ASCII;美国标准信息交换吗 ,用一个字节7位

iso-8859-1:欧洲码表,用一个字节8位

GB2312:中国的中文编码

GBK:中文编码表升级版。2个字节 两个高位是1

Unicode:国际标准码,所有文字用两个字节。java语言使用的就是Unicode

UTF-8:最多用三个字节表示一个字节,一个字节可以表示,两个字节也可以

表示,三个也可以。

字符编码:以转换流为主

*
printStream和PrintWriter也涉及编码表,但是只用于打印。

* "你好"以gbk的编码表的存储。存的是字节。例如:你
查表对应"-45 -56",好 查表"-48 -89".存储的形式-45 -56  -48 -89

*  读取的时候:读的是数字:-45 -56 
-48 -89在GBK表中对应的是"你好"。但是如果使用的UTF-8读取时,-45 -56  -48一组,对应的是

*  ?,而-48对应的也是?,都是未知字符。

* 编码:变成字节数字  字符串变成字节数组

* 解码: 变成字符串。 字节数组变成字符串

* String-->byte[] 
.getBytes()

* byte[]-->String  
new String(buf)

/**UTF-8修改版标示头。UTF-8怎么决定使用一个字节,两个字节,三个字节。

* 单个字节:头位:0

* 两个字节表示:第一个字节头位:1 1 0

*
               
   第二个字节头位:1 0

* 第三个字节表示:第一个字节头位:1 1 1 0

*
                      
第二个字节头位:1 1 0

*
                      
第三个字节:      1 0

//联通使用Gbk编码,但是其二进制形式是U8表的表现形式。就去查U8的表。

//[-63, -86, -51, -88]

//     11000001

//     10101010

//     11001101

//     10101000

//看表现形式可以发现,它符合两个字节表示的情况,而在u8中,汉字是以三个字节表示。所以出错。

练习:

* 有五个学生,每个学生有3门功课的成绩,

从键盘输入以上数据(包括姓名,三门成绩)

输入格式:如:zhangsan,50,54,54,计算出总成绩。

并把学生的信息和计算出的总分数按高低顺序存放在

磁盘文件“stud.txt”中。

黑马程序员-常见的一些流和编码表

时间: 2024-10-28 19:27:22

黑马程序员-常见的一些流和编码表的相关文章

黑马程序员——Java I/O流基础知识点(File类)

File工具 File类就是用俩将文件或者文件夹封装对象,弥补流对象的不足--流只能操作数据,不能操作文件夹的 封装的是路径!!! 构造方法演示 1.可以将已有的未出现的文件或者文件夹封装成对象. File f1=new File("c:\\abc\\a.txt"): File f2=new File("d:\\abc","ab.txt"打印,会打印路径.:目录分隔符,为了更好地跨平台File. File类常见功能 1,创建 createNewF

黑马程序员——Java基础--IO流(一)---字符流和字节流

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.IO流的介绍及体系 IO流用来处理设备之间的数据传输.java对数据的操作是通过流的方式.java用于操作流的对象都在IO包中. 输入流和输出流相对于内存设备而言:将外设中的数据读取到内存中:输入.将内存中的数据写出到外设中:输出. 流按照操作数据分为两种:字节流和字符流. 字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作

黑马程序员——Java基础--IO流(一)---File类以及其他流对象

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.File类 File类是将文件系统中的文件和文件夹封装成了对象.提供了更多的属性和行为可以对这些文件和文件夹进行操作.这些是流对象办不到的,因为流只操作数据.File对象可以作为参数传递给流对象的构造函数.File 类的实例是不可变的:也就是说,一旦创建,File 对象表示的抽象路径名将永不改变. 1.File类中的方法 (1).File类的构造方法以及字段 1 new File(Stri

黑马程序员——java基础IO流——字符流缓冲区和字节流

字符流的缓冲区 l  缓冲区的出现提高了对数据的读写效率. l  对应类 ?    BufferedWriter ?    BufferedReader l  缓冲区要结合流才可以使用. l  在流的基础上对流的功能进行了增强. 1, BufferedWriter 每次可以写入一行,缓冲区的出现是为了提高流的操作效率而出现的.所以在创建缓冲区之前,必须要先有流对象.该缓冲区中提供了一个跨平台的换行符,newLine(); /* 缓冲区的出现是为了提高流的操作效率而出现的. 所以在创建缓冲区之前,

黑马程序员------Java中IO流学习总结

Java培训.Android培训.iOS培训..Net培训.期待您的交流 一.概念 流:流就是字节序列的抽象概念,能被连续读取数据的数据源和能被连续写入数据的接收端就是流 IO流:用于处理设备上的数据 常用设备:硬盘.内存.键盘录入等 IO流的分类: 1.根据处理的数据类型不同,可分为字节流和字符流. 字符流的由来:因为文件编码的不同,而有了对字符高效操作的字符流对象,原理是基于字节流读取字节时,去查了相关码表. 字符流和字节流的区别: **字节流读取时,读到一个字节就返回一个字节:而字符流是字

黑马程序员——Java基础——IO流

第一讲 IO概述 1概述:IO流:输入(Input与Output流) 2特点: a.IO流用于数据传输: b.按操作分为字节流与字符流 c.按流向分:输入流和输出流 3.常用IO流的基类 1)字节流的基类:InputStream和OutpuStream 2)字符流的基类:Reader和Writer 第二讲 字符流 一.简述 1.字符流的对象融合了编码表.使用的是默认的编码 2.字符流只能用于文字处理,而字节流可以处理其他: 3.下列把FileWriter和FileReader一起讲 1 pack

黑马程序员——Java基础——IO流(二)——File类、Properties类、打印流、序列流

第一件 File类 一.File类 a.用于将文件或者文件夹封装成对象 b.方便对文件与文件夹的属性信息进行操作 c.File对象可以作为参数传递给流的构造函数 d.了解File类中的常用方法 二.File对象的创建 a.File f=new File("a:\\a.txt"): b.File f2=new File("C:\\abc","a.txt");//分开的好处是后一个参数能够使用其他对象如string c.File d=new File

黑马程序员——25,打印流,合并流,对象序列化,管道流,RandomAccessFile

------<ahref="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- /* IO流的打印流:专门用于打印的流 字节打印流PrintStream PrintStream的构造函数可以接收file对象,String型字符串路径,字节输出流 字符打印流PrintWriter PrintWriter的构造函数可以接收

黑马程序员——常见一些类的使用

------ <a href="http://www.itheima.com" target="blank">android培训</a>.<a href="http://www.itheima.comtarget="blank"> java培训</a>.期待与您交流! --------- Runtime对象,该类并没有提供构造函数,说明不可以new对象, 该类中的方法包括静态与非静态的 该