javaIO包

Java IO流: 
流是一组有序的有头有尾的字节集合,是数据传输总称或抽象。 
IO流是用来处理设备之间的数据传输 
Java对数据的操作是通过流的方式 
Java用于操作流的对象都在IO包中 
流按操作数据分为两种:字节流与字符流 
流按流分为:输入流(input),输出流(output)(相对于内存来说的) 

根据处理的数据不同:分为:字节流和字符流。 

**所有的数据都是以字节体现的,后期产生了字符流,因为字符数据涉及到了编码问题,所以在字符流对象中加入了编码机制。如果处理的数据都是字符数据,只是可以使用字符流对象来完成。 

IO流常用基类: 
  字节流的抽象基类: 
  InputStream,OutputStrean 
   
  字符流的抽象基类: 
  Reader,Writer 
   
  **由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。 
  如:InputStream的子类FileInputStream 
  如:Reader的子类FileReader 

IO程序的书写 
1,导入IO包中的类 
2,进行IO异常处理 
3,在finally中对流进行关闭 

FileWriter类: 

FileWriter fw = new FileWriter(“Demo.txt”);
//FileWriter:用来操作文件的字符串输出流对象 
/* 
创建该对象做的事情: 
1,在堆内存中产生了一个实体 
2,调用了系统底层资源,其实是调用了windows的功能,在指定位置创建了一个文件,建立数据存储的目的地。用于存放即将写入的数据。 
3,因为目的地可能因为路径错误,而导致失败,所以抛出了IOException,需要对其处理。 

**如果创建的文件已经存在,那么会覆盖原文件。 
*/ 

//既然有了流对象,指定具体数据,使用fw对象的write方法将数据写成,fw对象的write 
//方法,将数据写入到了流中,其实就是内存中。 
Fw.write(“abcdefg”); 

//刷洗缓冲区,将流中的数据刷到目的地中。 
Fw.flush(); 

Fw.write(“kkkkkk”); 

Fw.flush(); 

Fw.write(“qqqqqq”); 

/* 
Close方法: 
1,先刷新缓冲区的数据到目的地,其实就是调用了一次flush。 
2,关闭了调用底层的资源。将资源释放。 
*/ 
Fw.close(); 


Flush()和close()的不同: 
Flush():只会刷新缓冲区,流依然存在,并可以继续使用 
Close():也会刷新缓冲区,但是刷新后,立刻关闭流资源,流不可以在继续使用。 


FileReader类:【 


  /* 
  创建一个读取流对象,并关联要读取的文件。 
  将要读取的文件作为构造函数的参数传递,对象一初始化就必须有一个已经存在的数据。 
  */ 
  FileReader fr = new FileReader(“Demo.txt”); 
   
  /* 
  //调用了读取流对象的read方法,一次读一个字符。 
  Int ch = fr.read(); 
  */ 
   
  Int ch = 0; 
  While((ch = fr.read())!=-1){//当为-1的时候就不读了 
  System.out.println((char)ch); 
  } 
   
  System.out.println((char)ch); 
   
  Fr.close(); 
   
  或者:(这种方法比较好,循环次数较少) 
   
  FileReader fr = new FileReader(“Demo.txt”); 
   
  Char[] buf = new char[1024]; 
   
  Int len = 0; 
  While((len=fr.read(buf))!=-1){ 
  System.out.println(new String(buf,0,len)); 
  } 

】 


BufferedWriter类:(带缓冲技术的字符输出流) 
  FileWriter fw = new FileWriter(“bufdemo.txt”); 
  BufferedWriter bufw = new BufferedWriter(fw); 

  Bufw.write(“haha”); 
  Bufw.newLine();//依据不同的平台,进行换行的操作 
  Bufw.write(“hehe”); 
  bufw.newLine(); 
  Bufw.flush();//养车一个习惯,只要用到了缓冲区,就记着一定要刷新 
  Bufw.close();不用关闭fw了,因为缓冲区是提高流的操作效率而存在,只是内部提供了 数组,对数据进行缓冲,最终的写入还是流完成的,所以关闭缓冲区,其实就是在关闭 流,也就是bufw.close其实内部调用的就是fw.close(); 


BufferedReader类: 
  FileReader fr = new FileReader(“bufdemo.txt”); 
  BufferedReader bufr = new BufferedReader(fr); 
  String line = null; 
  While((line=bufr.readLine())!=null){ 
  System.out.println(line); 
  } 
  Bufr.close(); 


复制的原理: 
  对源文件进行读取。 
  并将读取的数据存储到目的文件中。 
   
  1,(不同缓冲区) 
  FileReader fr = null; 
  FileWriter fw = null; 
  Try{ 
  Fr = new FileReader(“Demo.txt”); 
  Fw = new FileWriter(“copyDemo.txt”); 
  Char[] buf = new char[1024]; 
  Int len = 0; 
  While((len=fr.read(buf))!=-1){ 
  Fw.write(buf,0,len); 
  } 
  }catch(IOException e){ 
  Throw new RuntimeException(“读写失败”): 
  }finally{ 
  Try{ 
  If(fw!=null) 
  Fw.close(); 
  }catch(IOException e){ 
  Throw new RuntimeException(“写入关闭失败”): 
  } 
  Try{ 
  If(fr!=null) 
  Fr.close(); 
  }catch(IOException e){ 
  Throw new RuntimeException(“读取关闭失败”); 
  } 
  } 
   
  2,(使用缓冲区) 
  import java.io.*; 
   
  class TestBuffer { 
   public static void main(String[] args){ 
   FileReader fr = null; 
   FileWriter fw = null; 
   BufferedReader br = null; 
   BufferedWriter bw = null; 
   try 
   { 
   fr = new FileReader("E:\\ITcast\\day24\\copyText.java"); 
   fw = new FileWriter("E:\\ITcast\\day24\\Copy.txt"); 
   br = new BufferedReader(fr); 
   bw = new BufferedWriter(fw); 
   String str = null; 
   while ((str=br.readLine())!=null) 
   { 
   bw.write(str); 
   bw.newLine(); 
   bw.flush(); 
   } 
   } 
   catch (IOException e) 
   { 
   throw new RuntimeException("复制不成功"); 
   }finally{ 
   try 
   { 
   if(br!=null) 
   br.close(); 
   } 
   catch (IOException e) 
   { 
   throw new RuntimeException("关闭输入失败"); 
   } 
   
   try 
   { 
   if(bw!=null) 
   bw.close(); 
   } 
   catch (IOException e) 
   { 
   throw new RuntimeException("关闭输出失败"); 
   } 
   } 
   } 
  } 




字符流的缓冲区,是为了提高效率而存在的。 
BufferedWriter 
  NewLine(); 
BufferedReader 
  readLine();调用基础流对象的read方法,一次读一个字符,并吧该字符进行了临时存储。直到读到回车换行符为止,将存储的数据作为字符串返回。 
缓冲区的出现提供了比以前流对象功能更前的函数。 


异常处理方式: 

Import java.io.*; 
Class FileWriterDemo2{ 
  Public static void main(String[] args){ 
  FileWirter fw = null 
  Try{ 
  Fw = new FileWriter(“d:\\Demo.txt”); 
  Fw.write(“abcdef”); 
  }catch(IOException e){ 
  System.out.println(e.toString()); 
  Throw new RuntimeException(“写入失败”); 
  }finally{ 
  Try{ 
  If(fw != null) 
  Fw.close(); 
  }catch(IOException e){ 
  System.out.println(e.toString()); 
  Throw new RuntimeException(“关闭失败”); 
  } 
  } 
  } 


这样写的好处,就是写入的时候发生了错误,finally中的代码也会继续执行,也就是说可以执行到close方法,将流关闭,将FileWriter写在try catch的外面,是为了让finally中的变量也try中的变量指向同一个流。


如何对已有的文件进行数据的续写? 
使用FileWriter对象的另一个构造函数,带一个boolean类型的参数的构造函数。只要boolean类型值为true,就可以完成续写。 
**如果写入回车换行符,在windows中需要\r\n来完成。 

FileReader 
FileWriter 
BufferedWriter 
BufferedReader 
凡是直接操作数据的流对象,或者操作文件的流对象,都是最常用的流对象。 
因为文件就是数据体现形式。 
而操作流就需要提高效率,所以带缓冲的流对象,也是常用对象。 

inputStream类: 
  FileInputStream fis = new FileInputStream(“fos.txt”); 
  Byte[] buf = new byte[1024]; 
  Int len = 0; 
  While((len=fis.read(buf)) != -1){ 
  System.out.println(new String(buf,0,len)); 
  }
  Fis.close(); 


outputStream类: 
  FileOutputStream fos = new FileOutputStream(“fos.txt”); 
  Byte[] buf = “abcde”.getBytes(); 
  Fos.write(buf);//字节流的写入方法,直接将数据写到了目的地,因为对象中不存在缓冲区 
  Fos.close();//关闭资源 


复制图片:(复制的几种方式) 
1, 
  FileInputStream fis = new FileInputStream(“c:\\0.bmp”); 
  FileOutputStream fos = new FileOutputStream(“c:\\1.bmp”); 
  Byte[] byf = new byte[1024]; 
  Int len = 0; 
  While((len=fis.read(buf))!=-1){ 
  Fos.write(buf,0,len); 
  } 
  Fos.close(); 
  Fis.close(); 

2, 
  FileInputStream fis = new FileInputStream(“c:\\1.mp3”); 
  BufferedInputStream bufis = new BufferedInputStream(fis); 
  FileOutputStream fos = new FileOutputStream(“c:\\3.mp3”); 
  BufferedOutputStream bufos = new BufferedOutputStream(fos); 
   
  Int by = 0; 
  While((by = byfis.read())!=-1){ 
  Byfos.write(by); 
  } 
  Bufos.close(); 
  Bufis.close(); 



不能通过字符流复制图片,因为读取图片数据时,字符流会查默认的编码表。如果在编码表中没有查到具体的数据,就会用其他数据替代。这时,元数据错乱,导致生成的图片无法观看。所占字节也不同。 
**只要操作数据是文本,建议使用字符流,因为它可以进行指定编码的转换,除此之外,都用字节流。 


键盘的录入:(将输入的字符转成大写,如果是over就结束) 
  Int ch = 0; 
  InputStream in = System.in; 
  StringBuilder sb = new StringBuilder(); 
  While(true){ 
  Ch = in.read(); 
  If(ch == -1){ //通过控制台的ctrl+c可以强制结束录入,其实就是给流定义了结束标记 
  System.out.println(“------”); 
  Break; 
  } 
  If(ch == ‘\r’) 
  Countinue; 
  If(ch == ‘\n’){ 
  String s = sb.toString(); 
  If(s.equals(“over”)) 
  Break; 
  System.out.println(s.toUpperCase()); 
  Sb.delete(0,sb.length()); //清空缓冲区 
  }else 
  Sb.append((char)ch); 
   
  } 
转换流:(字符流) 
InputStreamReader字节通向字符流的桥梁 
OutputStreamWriter字符通向字节的桥梁 


InputStream in = System.in;//获取键盘录入读取流对象。//这个是字节流对象 

//流转换,将字节流转成字符流 
InputStreamReader isr = new InputStreamReader(in); 

对字符流进行读取效率的提高,意思操作一行数据 
BufferedReader bufr = new BufferedReader(isr);//这个是字符流对象 

OutputStream out = System.out; 
OutputStreamWriter osw = new OutputStreamWriter(out); 
BufferedWriter bufw = new BufferedWriter(osw); 

String line = null; 
While((line = bufr.readLine())!=null){ 
  If(“over”.equals(line)) 
  Break; 
  Bufw.write(line.toUpperCase()); 
  bufw.newLine(); 
  Bufw.flush(); 


Bufw.close(); 
Bufr.close(); 



**//一次读键盘一行 
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in))); 
BufferedWriter bufw = new BufferedWriter(new OutStreamWriter(System.out))); 

流的操作规律? 
因为io包中的对象很多,最重要的是要知道完成数据处理时,要使用哪个对象最合适。 
如何判断要使用那些对象? 
  通过几个明确来判断对象的使用。 
  1,明确数据源,和数据目的(数据汇) 
  数据源:InputStream Reader 
  数据目的:OutputStream Writer 
  2,明确数据的内容是否是纯文本。 
  数据源:是:Reader 
  数据目的:是:Writer 
  如果不是:就使用InputStream或者OutputStream 
   
  如果数据不能明确,只有使用字节流。 
  这样就可以将四个基类,进行确定,要使用哪个。 
  3,明确具体设备。 
  数据源:键盘(System.in),内存(数组),硬盘(File开头的流对象)。 
  数据目的:控制台(System.out),内存(数组),硬盘(File开头的流对象)。 
  4,明确是否需要提高效率? 
  是:使用带Buffer对象 
   

Writer 
  |--OutputStreamWriter 
  |--FileWriter 
Reader 
  |--InputStreamReader 
  |--FileReader 
转换流其实就是将字节流和编码表相结合,将字节流中的字节数据去查了具体的编码表。 
所以转换流才可以获取一个中文字符。 
那么转换流的子类用于操作文件的对象FileReader就直接使用父类的具体有转换功能的read方法,就可以一次读一个字符。 

FileReader fr = new FileReader(“a.txt”);//该对象中已经内置了本机默认的字符编码表 
  //对于简体中文版的机器默认编码表示gbk 
//通过字节读取流读取a.txt中中文数据,按照gbk编码表的来读取中文字符。 
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),”gbk”); 

InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),”gbk”); 
FileReader fr = new FileReader(“a.txt”); 
这两句代码的功能是一样的。 

区别: 
第一句可以指定编码表 
第二句,固定本机默认编码表 

如果操作中文数据,仅使用本机默认码表,那么第二句简单 
如果操作中文数据,使用指定码表,必须使用第一句,而且要将指定码表作为字符串传递到构造函数中。 

File类: 
数据存放的形式最常见的就是文件。 
文件的属性较多,如文件名称,路径,大小等属性。 
为了方便与操作java就将其视为对象。 
通过File类对其描述。 
提供了多个属性和行为。便于对文件进行操作。 

而流对象只能用于操作文件中的数据。 
对于文件的属性,都是通过File对象来完成。 

File类可以是文件,也可以是路径。 
将制定文件封装成File对象。 
File f = new File(“c:\\a.txt”); 

File f1 = new File(“c:\\”,”a.txt”); 

File dir = new File(“c:\\”); 
File f2 = new File(dir,”a.txt”); 

File f3 = new File(“c:”+File.separator+”a.txt”); 
File.separator是跨平台性的目录分隔符 

File常见的方法: 
1,创建文件 
  Boolean createNewFile();//如果f这个文件不存在,该方法会对其创建 
  //如果f已经存在,该方法不会创建 
  //而输出流创建文件,如果该文件存在,会覆盖,但是,如果输出流 
  //的构造函数传入参数为true,不覆盖文件,可以完成续写。 
  创建文件夹 
  Boolean mkdir();//创建单级目录,如果已经存在不创建 
  Boolean mkdirs();//创建多级目录(就是目录下还有子目录),可以在已存在的目录下继 //续创建 
2,删除 
  Boolean delete();//java中的删除不走回收站 
  //删除目录时,如果目录中有内容,应该先将内部内容删除,再删该目录 
  //windows的删除就是从里往外删 
  Void deleteOnExit();//程序退出时,把该文件删除。 
3,判断(想要判断file对象封装的是文件还是目录,必须要确定内容是存在的) 
  Boolean isFile()//是不是文件 
  Boolean isDirectory()//是不是目录 
  Boolean isAbsolute()//是不是据对路径 
  Boolean exists()//判断封装的对象是否存在 
  Boolean canExecute()//判断文件是否可以执行 
  Boolean isHidden()//判断文件是否是隐藏文件 
4,获取 
  String getAbsolutePath();//获取绝对路径(完整路径) 
  String getPath();//获取相对路径(file内封装的路径内容) 
  String getName();//获取文件名 
  String getParent();//获取父目录 
  Long length();//获取文件的长度(文件的字节数,该方法只针对于与文件而言) 
  Long lastModified();//文件最后一次修改的时间 
5,重命名 
  Boolean renameTo(file);//将文件名修改,可以进行文件的移动(剪切+重命名) 
6,文件列表 
  Static File[] listRoots();//列出系统的根 
  String[] list();//获取当前目录下的文件夹和和文件的名称,如果file中封装的是一个文件,那么返回数组为null,所以最好做一个安全的判断 
  File[] listFiles();//获取的是当前目录下文件或者文件夹对应的对系那个。 
   
  (如果仅获取文件名称,就用list方法。如果还用获取文件的其他信息,最好用listFiles,因为它可以获取到文件对象,这样就可以通过文件对象方法,获取其他内容) 



IO包中的其他类: 
PrintWriter与PrintStream 
可直接操作输入流和文件。 

PrintStream:字节流中的打印流,可以直接操作设备的流对象。 
  构造函数的参数特点: 
  1,字符串路径。 
  2,File对象。 
  3,字节输出流。 
   
PrintWriter:字符流中的打印流。 
  构造函数的参数特点: 
  1,字符串路径 
  2,File对象 
  3,字节输出流 
  4,字符输出流 
   
打印流可以直接操作文件,算是较为常用的流对象。 
可以打印任意数据类型。 


管道流: 
  PipedInputStream和PipedOutputStream 
  输入输出可以直接进行连接,通过线程使用。 
  读取流和写入流可以进行连接。 
  但是需要被多线程操作。 
  因为read方法是阻塞式方法。容易引发死锁。 



RandomAccessFile: 
随机访问文件,自身具备读写的方法。 
通过skipBytes(int x),seek(int x)来达到随机访问。 
特点: 
  1,既可以读又可以写。 
  2,内部封装了一个大的byte类型的数组,这就说明该对象操作的数据是字节数据,说明其中封装了字节的读取流和写入流。而且可以使用内部的指针对这个数组进行数据的操作 
  3,提供了getFilePointer方法获取指针的位置,还提供了seek方法设置指针的位置。 
  4,通过该对象的构造函数可以得知,该对象只能操作文件。 
  也就是说源和目的都是一个文件。 
  并通过构造函数的另一个参数来确定,访问方式。该变量只能接收四个值。 
  R:只读,rw:读写。Rws,rwd 
  5,该对象中的方法可以操作基本数据类型。 
  6,注意被操作的文件数据,希望有规律。这样可以通过数据的整数倍来控制指针的偏移。 
   对数据进行操作,达到,随机访问的效果。 

  可以应用于多线程对大数据的写入。同时写入,只要给每一个线程分配 
  起始索引位,就可以完成多线程随机写入。 
  提高了写入效率。 
   
   
  使用的前提: 
  1,必须是文件。 
  2,数据有规律。比如等长数据。 

*/ 

class RandomAccessFileDemo 

public static void main(String[] args) throws IOException 

writeDemo3(); 
// readDemo2(); 



//对已有数据进行修改。 
public static void writeDemo3()throws IOException 

RandomAccessFile raf = new RandomAccessFile("info.txt","rw"); 

raf.seek(8*3);//从指针索引位8开始进行写入。 
raf.write("赵六".getBytes()); 
raf.writeInt(72); 

raf.close(); 


/* 
既然能写,那么读也应该没有问题。 
通过指针的操作,完成读取的随机效果。 
*/ 
public static void readDemo2()throws IOException 

RandomAccessFile raf = new RandomAccessFile("info.txt","r"); 

raf.seek(8*1); 


byte[] buf = new byte[4]; 

int len = raf.read(buf); 
String s= new String(buf,0,len); 

System.out.println("name="+s); 
int age = raf.readInt();//一次读四个字节并转成int数值。 
System.out.println("age="+age); 
raf.close(); 




//通过seek方法指定指针的位置,进行数据写入。 
/* 
发现RandomAccessFile操作的文件如果已经存在,不会再次创建,直接操作已有文件。。 

发现通过seek的指针定位,就可以完成数据的随机写入。 

它可以完成已有数据的修改。 
*/ 
public static void writeDemo2()throws IOException 

RandomAccessFile raf = new RandomAccessFile("info.txt","rw"); 

raf.seek(8*2);//从指针索引位8开始进行写入。 
// raf.write("李四".getBytes()); 
// raf.writeInt(67); 
raf.write("王武".getBytes()); 
raf.writeInt(68); 

raf.close(); 


/* 
通过该对象写点数据。 
数据: 人员信息: 姓名,年龄 
*/ 
public static void writeDemo()throws IOException 

RandomAccessFile raf = new RandomAccessFile("info.txt","rw"); 

raf.write("张三".getBytes()); 
//raf.writeBytes("张三");//解析出了问题。 
//raf.writeChars("张三");//解析出了问题。 
//raf.write(65);//write:只将一个int整数的最低字节写出。 


raf.writeInt(65); 

raf.close(); 



public static void readDemo()throws IOException 

RandomAccessFile raf = new RandomAccessFile("info.txt","r"); 

byte[] buf = new byte[4]; 

int len = raf.read(buf); 
String s= new String(buf,0,len); 

System.out.println("name="+s); 
int age = raf.readInt();//一次读四个字节并转成int数值。 
System.out.println("age="+age); 
raf.close(); 







序列流: 
SequenceInputStream 
对多个流进行合并。 

操作对象: 
ObjectInputSteam与ObjectOutputStream 
被操作的对象需要实现 


ProPerties类: 
Map 
  |--Hashtable 
  |--Properties 
Properties:该集合中存储的键和值都是字符串类型的数据,通常同于配置文件的定义。 
Properties类表示了一个持久的属性集,Properties可以保存在流中或从流中加载,属性列表中每个键及其对应都是一个字符串。 
1,添加元素: 
  Properties prop = new Properties(); 
prop.setProperty("xiaowang","12"); 
prop.setProperty("xiaozhang","13"); 
prop.setProperty("xiaoli","14"); 
  System.out.println(prop); 

2,列表方法: 
  Properties prop = new Properties(); 
prop.setProperty("xiaowang","12"); 
prop.setProperty("xiaozhang","13"); 
prop.setProperty("xiaoli","14"); 
  prop.list(System.out);//打印到控制台,只要让参数是System.out 
  ------------------------------------------------------------------ 
Properties prop = System.getProperties(); 
  Prop.list(new PrintStream(“sys.txt”));//将系统信息写入到sys.txt文件中去 

3, 
Properties prop = new Properties(); 
System.out.println(prop); 
FileReader fr = new FileReader("prop.txt"); 
prop.load(fr); 
//使用集合的特有方法load 
System.out.println(prop); 
4, 
//将硬盘中的键值对加载到Properties集合中。 
Properties prop = new Properties(); 
System.out.println(prop); 
FileInputStream fis = new FileInputStream("info.txt"); 
//使用集合的特有方法load,将流的特定规则信息存储到集合中,注意:流中的信息必须有规则是键值对。用=分隔 
prop.load(fis); 
System.out.println(prop); 
fis.close(); 
5, 
//模拟一个load方法。 
/* 
其实load方法很简单,就是通过流对象,读取文本中一行数据 。 
在将该行数据通过=进行切割。左边作为键,右边作为值。 
存入到Properties集合中。 
*/ 
Properties prop = new Properties(); 
BufferedReader bufr = 
new BufferedReader(new FileReader("info.txt")); 
String line = null; 
while((line=bufr.readLine())!=null) 

String[] arr = line.split("="); 
prop.setProperty(arr[0],arr[1]); 

System.out.println(prop); 
bufr.close(); 
6, 
/* 
将硬盘上的数据进行集合的存储,希望在运算后,将改变后的结果,重新存回配置文件中。 
*/ 
Properties prop = new Properties(); 
FileInputStream fis = new FileInputStream("info.txt"); 
prop.load(fis); 
System.out.println(prop); 
prop.setProperty("wangwu","29");//把集合修改后的数据重新存回配置文件。 
//需要写入流。需要一个存储方法。store(outputStream.string); 
FileOutputStream fos = new FileOutputStream("info.txt"); 
prop.store(fos,"hah"); 
System.out.println(prop); 
fos.close(); 
fis.close(); 


SequenceInputStreamm类: 
可以将多个读取流变成一个读取流。 


操作对象流: 
  ObjectInputStream和ObjectOutputStream 
  对象的持久化存储。 
  也就是说将对象中封装的数据保存到持久化的设备上,比如硬盘。 
  那么其他应用程序都需要建立该对象,直接读取设备上的对象即可。 
   
  ObjectInputStream ObjectOutputtStream 
  专门用于操作对象的流,封装了直接操作对象的方法。 

写入对象: 
  使用输出流中的writerObject();方法,里面传递一个对象。 
  如果一个对象要被写入,必须具备序列化功能,也就是说必须要实现Serializable接口 


读取对象: 
  使用输入流中的readObject();方法,要注意的是需要强制转换, 
  Person p = (Person)ois.readObject(); 


**对象中的静态数据是不会被持久化的。 
只要将不需要被持久化的非静态数据进行transient关键字修饰即可。 

Sirializable序列化接口: 
  用于给类文件加一个UID,就是一个序列号。 
  该序列通过类中的成员的数字签名完成运算得来的。 
   
   
  当类中的成员发生大的改动时,类会重新编译,生成带有新的UID的序列号。这样就 可以和曾经存储的原来的类生成的对象的序列号不匹配。 
  这样就可以让使用者必须重新对新类产生的对象进行存储。避免新类接收老对象出现安 全隐患,这就是序列号的功能所在。 
   
  如果类中没有成员大的改动,只是有个别的一些修改,没有对对象产生打的影响,这时 候,不必去重新对类进行存储,这时可以在定义类时指定序列化,而不让jvm自动算 该序列化。 
   
  Public static final long serialVersionUID = 42L;//给person指定一个固定的序列化。这样就 可以保证该类即使被改动,序列化也不会变 





操作基本数据类型 
  DataInputStream与DataOutputStream 
  DataInputStream和DataOutputStream: 
  writeUTF()方法一般流对里面的数据读取不出来,因为它用的是utf的修改表。只能用 DataInputStream中的readUTF()方法进行读取。 
   
   
操作字节数组 
  ByteArrayInputStream与ByteArrayOutputStream 
  操作数组流对象,它对应的设备就是内存。 
  ByteArrayOutputStream:内部封装了一个可变长度的字节数组 
  关闭它是无效,因为该对系那个根本就没有调用过底层资源 
  可以通过toByteArray()或者toString()获取数组中的数据 
   
  ByteArrayInputStream负责数据源,在初始化的时候,必须要有一个数据源内容。 
  因为操作的是数组,所以源就是一个字节数组。 
  该对象中不会有异常发生,因为没有调用过底层资源。 
   
  为什么不直接操作byte[],还要用到流? 
  因为数组的操作,无非就是数组中的元素进行设置和获取,这个操作正好符合了读和写 的操作。 
  使用流的操作思想在操作数组 
   
操作字符数组 
  CharArrayReader与CharArrayWrite 
操作字符串 
  StringReader与StringWriter 


字符编码: 
  字符流的出现为了方便操作字符 
  更重要的是加入了编码转换。 
  通过子类转换流来完成 
  InputStreamReader OutputStreamWriter 
  在两个对象进行构造的时候可以加入字符集。 


常见的编码表: 
  ASCII:美国标准信息交换码 
  用一个字节的7位可以表示 
  ISO8859-1:拉丁码表,欧洲码表 
  用一个字节的8位表示 
  GB2312:中国的中文编码表 
  GBK:中国的中文编码表升级,融合了更多的中文文字符号。 
  Unicode:国际标准码,融合了多种文字。 
  所有文字都用两个字节来表示,java语言使用的就是unicode 
  UTF-8:最多用三个字节表示一个字符 

字符流 = 字节流+编码表,能指定编码表的转换流 
内部默认了编码表的是转换流的子类FileReader,FileWriter,默认的是本机码表 

OutputStreamWriter osw = new OutputStreamWrtier(new FileOutputStream(“gbk.txt”)); 
OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream(“gbk,txt”),”GBK”); 
FileWriter fw = new FileWriter(“gbk.txt”); 
这三句是一样的,都是在使用默认的GBK表,在操作gbk.txt 


编码解码问题: 
编码:字符串——》字节数组。 
  使用的是String类中的getBytes(charset); 
  Byte[] buf = “你好”.getBytes(“utf-8”); 
   
解码:字节数组——》字符串。 
  使用String类中的构造函数。 
  String s = new String(buf,”utf-8”); 

在gb2312的码表中,中文是两个字节,都是负数,也就是每一个字节的最位都是1 
在gbk的码表中,中文还是两个字节,第一个字节最高位是1,第二个字节最高位可能是0 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值