java file I o笔记_Java学习笔记-I/O

File类

一个File类的对象,表示了磁盘上的文件或目录。

File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。

import java.io.*;

class FileTest

{

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

{

//File f = new File("1.txt");

//f.createNewFile();   创建文件

//f.mkdir(); 创建文件夹

//File f = new File("F:\\Java Develop\\1.txt");//使用绝对路径

//f.createNewFile();

/*

*WINDOWS平台下有盘符,LINUX下是没有的

*考虑到JAVA语言的平台性,所有用分隔符seperator/seperatorChar

*/

/*

File fDir = new File(File.separator);//创建了当前的根目录

String strFile = "Java Develop"+File.separator+"1.txt";

File f = new File(fDir,strFile);

f.createNewFile();

//f.delete();

f.deleteOnExit();

Thread.sleep(3000);

*/

/*

for(int i=0;i<5;i++)

{

File.createTempFile("linshi",".tmp");

f.deleteOnExit();

}

Thread.sleep(3000);

*/

File fDir = new File(File.separator);

String strFile ="Java Develop"+File.separator;

File f = new File(fDir,strFile);

//文件过滤器

String[] names = f.list(new FilenameFilter()

{

public boolean accept(File dir,String name)

{

return name.indexOf(".java")!=-1;

}

});

for(int i=0;i

{

System.out.println(names[i]);

}

}

}

流式I/0

流(Stream)是字节的源或目的。

两种基本的流是: 输入流(Input Stream)和输出流(Output Stream)。从从中读出一系列字节的

对象称为输入流。而能向其中写入一系列字节的对象称为输出流。

流的分类

节点流: 从特定的地方读写的流类,例如:磁盘或一块内存区域。

过滤流: 使用节点作为输入或输出。过滤流使用的是一个已经存在的输入流或输出流连接创建的。

(如下图)

b_4ABA553F60E5FD5F.jpg

InputStream(一个抽象的基类)

.三个基本的读写方法

abstract int read(): 读取一个字节数据,并返回到数据,如果返回-1,表示读到了输入流的

末尾。

int read(byte[] b):  将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,

表示读到了输入流的末尾。

int read(byte[] b,int off,int len): 将数据读入一个字节数组,同时返回是实际读取的字

节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放

数据的起始偏移位置;len指定读取的最大字节数。

其他的方法

long-skip(long n): 在输入流中跳过n个字节,并返回实际跳过的字节数。

int available():   返回在不发生阻塞的情况下,可读取的字节数。

void close():      关闭输入流,释放和这个流相关的系统资源。

void mark(int reqdlimit): 在输入流的当前位置放置一个标记,如果读取的字节数多余

readlimit设置的值,则流忽略这个标记。

void reset():      返回到上一个标记。

boolean markSupported(): 测试当前是否支持mark和reset方法。如果支持返回true,反之false。

java.io包中的InputStream的类层次 (下图)

b_051C70533BCF9CF2.jpg

OutputStream

三个基本的写方法

abstract void write(int b): 往输出流中写入一个字节

void write(byte[] b):       往输出流中写入数组b中的所有字节

void writte(byte[] b,int off,int len): 往输出流中写入数组b中从偏移量off开始的len个

字节的数据

其它方法

void flush(): 刷新输出流,强制缓冲区中的输出字节被写出

void close(): 关闭输出流,释放和这个流相关的系统资源

java.io包中OutputStream的类层次(如下图)

b_A7649D38C87C4104.jpg

基本的流类

FileInputStream和FileOutputStream

节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经

存在,则覆盖这个文件。

BufferedInputStream和BufferedOutputStream

过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。

DataInputStream和DataOutputStream

过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。

PipedInputStream和PipedOutputStream

管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream

对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。

code:

import java.io.*;

class StreamTest

{

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

{

/*

int data;

while((data=System.in.read())!=-1)  //从标准设备读取数据

{

System.out.write(data);//从标准设备输出数据

}

*/

//输出流写数据,只需要关闭尾端的流就可以了,因为fos连接到了bos

FileOutputStream fos = new FileOutputStream("1.txt");

//fos.write("http://www.google.cn".getBytes());

//fos.close();

BufferedOutputStream bos = new BufferedOutputStream(fos);

//bos.write("http//www.baidu.com".getBytes());

//bos.flush();

//bos.close();

DataOutputStream dos=new DataOutputStream(bos); //连接到了bos和fis

byte b=3;

int i=78;

char ch='a';

float f=4.5f;

dos.writeByte(b);

dos.writeInt(i);

dos.writeChar(ch);

dos.writeFloat(f);

dos.close(); //必须调用flush()或者close()不然不会写入硬盘

//输入流读数据

FileInputStream fis=new FileInputStream("1.txt");

BufferedInputStream bis = new BufferedInputStream(fis);

//byte[] buf=new byte[100];

//int len=fis.read(buf);

//int len=bis.read(buf);

//System.out.println(new String(buf,0,len));

//fis.close();

//bis.close();

//注意读取的顺序要和写的顺序一样

DataInputStream dis = new DataInputStream(bis);

System.out.println(dis.readByte());

System.out.println(dis.readInt());

System.out.println(dis.readChar());

System.out.println(dis.readFloat());

dis.close();

}

}

管道输入/输出流 code:

import java.io.*;

class PipedStreamTest

{

public static void main(String[] args)

{

PipedOutputStream pos=new PipedOutputStream();

PipedInputStream pis=new PipedInputStream();

//连接

try

{

pos.connect(pis);

new Producer(pos).start();

new Consumer(pis).start();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

class Producer extends Thread

{

private PipedOutputStream pos;

public Producer(PipedOutputStream pos)

{

this.pos=pos;

}

public void run()

{

try

{

pos.write("hello,welcome!".getBytes());

pos.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

class Consumer extends Thread

{

private PipedInputStream pis;

Consumer(PipedInputStream pis)

{

this.pis=pis;

}

public void run()

{

try

{

byte[] buf=new byte[100];

int len=pis.read(buf);

System.out.println(new String(buf,0,len));

pis.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

=================================================================================

Java I/O库的设计原则

Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。

这种机制实际上是一种被称做为Decorator(装饰)的设计模式的应用。

通过流的链接,可以动态的增加流的功能,而这些功能的增加是通过组合一些流的基本功能而动

态获取的。

我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不大容易掌握的原因,

但在I/O库中的Decorator模式的运用,给我们提供了实现上的灵活性。

I/O流的链接图(如下)

b_67BF045E1D09D7AD.jpg

Reader和Writer

Java程序语言使用Unicode来表示字符串和字符。

Reader和Writer这两个抽象类主要用来读写字符流。

java.io包中Reader的类层次(如下图)

b_7D68B185CE1EE42A.jpg

java.io包中Writer的类层次(如下图)

b_B4B95BA560BA15F9.jpg

code:

import java.io.*;

class StreamTest

{

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

{

/*

FileOutputStream fos = new FileOutputStream("1.txt");

OutputStreamWriter osw = new OutputStreamWriter(fos);

BufferedWriter bw = new BufferedWriter(osw);

bw.write("http://www.yahoo.com.cn");

bw.close();

FileInputStream fis = new FileInputStream("1.txt");

InputStreamReader isr = new InputStreamReader(fis);

BufferedReader br = new BufferedReader(isr);

System.out.println(br.readLine());

br.close();

*/

//InputStreamReader/OutputStreamWriter是一个中间过度类,连接字符和字符串

InputStreamReader isr = new InputStreamReader(System.in);

BufferedReader br = new BufferedReader(isr);

String strLine;

while((strLine=br.readLine())!=null)

{

System.out.println(strLine);

}

br.close();

}

}

字符集的编码

ASCII(American Standard Code for Information Interchange,美国信息互换标准代码),是基

于常用的英文字符的一套电脑编码系统。我们知道英文中经常使用的字符,数字符号被计算机

处理时都是以二进制编码的形式出现(bit)二进制数对应。其最高位是0,相应的十进制数是0-127

如,数字1,有一些制表符和其他符号组成。ASCII是现金最通用的单字节编码系统。

GB2312: GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字

符集-基本集》。主要用于给每一个中文字符指定相应的数字,也就是进行编码。一个中文字符

用两个字节的数字来表示,为了和ASCII码有所区别,将中文字符每一个字节的最高位置都用1

来表示。

GBK:为了对更多的字符进行编码,国家又发布了新的编码系统GBK(GBK的K是“扩展”的汉语

拼音的第一个字母)。在新的编码系统里,除了完全兼容GB2312外,还对繁体中文,一些不常用

的汉字和许多符号进行了编码。

ISO-8859-1:是西方国家所使用的字符编码集,是一种单字节的字符集,而英文实际上只用了其

中数字小于128的部分。

Unicode: 这是一种通用的字符集,对所有语言的文字进行统一编码,对每一个字符都采用2个字节

来表示,对于英文字符采取前面加“0”字节的策略实现等长兼容。如"a"的ASCII码为0x61,

UNICODE就为0x00,0x61。

UTF-8: Elight-bit UCS Transformation Format,(UCS,Universal Character Set,通用字符集,

UCS是所有其他字符集标准的一个超集)。一个7位的ASCII码值,对应的UTF码是一个字节,如果

字符是0x0000,或在0x0080与0x007f之间,对应的UTF码是两个字节,如果字符在0x0800与0xffff

之间,对应的UTF码是三个字节。

编码:将一个Unicode码转换为本地字符表示的过程为编码。

解码:将一个字节转换为一个字符(用Unicode表示),这个过程叫解码。

[简单的说去获取一个Unicode码就是解码]

code:

import java.util.*;

import java.nio.charset.*;

class CharsetTest

{

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

{

/*

Map m=Charset.availableCharsets();

Set names=m.keySet();

Iterator it =names.iterator();

while(it.hasNext())

{

System.out.println(it.next());

}

*/

Properties pps=System.getProperties();

//pps.list(System.out);

pps.put("file.encoding","ISO-8859-1");

int data;

byte[] buf=new byte[100];

int i=0;

while((data=System.in.read())!='q')

{

buf[i]=(byte)data;

i++;

}

String str=new String(buf,0,i);

//String strGBK=new String(str.getBytes("ISO-8859-1"),"GBK");

//System.out.println(strGBK);

System.out.println(str);

}

}

RandomAccessFile

RandomAccessFile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,

利用这个类可以在文件的任何位置读取或写入数据。

RandomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下一位数据的位置。

code:

import java.io.*;

class RandomFileTest

{

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

{

Student s1 = new Student(1,"zhangsan",98.5);

Student s2 = new Student(2,"lisi",90.5);

Student s3 = new Student(3,"wangwu",78.5);

RandomAccessFile rsf=new RandomAccessFile("student.txt","rw");  //存取模式rw

s1.WriteStudent(rsf);

s2.WriteStudent(rsf);

s3.WriteStudent(rsf);

Student s =new Student();

rsf.seek(0); //把文件指针移到文件首

for(long i=0;i

{

s.ReadStudent(rsf);

System.out.println(s.num+":"+s.name+":"+s.score);

}

rsf.close();

}

}

class Student

{

int num;

String name;

double score;

Student()

{

}

Student(int num,String name,double score)

{

this.num=num;

this.name=name;

this.score=score;

}

public void WriteStudent(RandomAccessFile raf)throws Exception

{

raf.writeInt(num);

raf.writeUTF(name);

raf.writeDouble(score);

}

public void ReadStudent(RandomAccessFile raf)throws Exception

{

raf.readInt();

raf.readUTF();

raf.readDouble();

}

}

对象序列化

.将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。

.将一个对象保存到永久存储设备上称为持续性。

.一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。

.当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员变量和静态的

成员变量。

.如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。

.如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,

并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象

仍然可以序列化。

code:

import java.io.*;

class ObjectSerialTest

{

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

{

Employee e1 = new Employee("zhangsan",20,2800.50);

Employee e2 = new Employee("lisi",22,25000.50);

Employee e3 = new Employee("wangwu",23,12800.50);

Employee e4 = new Employee("blovesaga",22,3800.50);

FileOutputStream fos=new FileOutputStream("employee.txt");

ObjectOutputStream oos=new ObjectOutputStream(fos);

oos.writeObject(e1);

oos.writeObject(e2);

oos.writeObject(e3);

oos.writeObject(e4);

oos.close();

FileInputStream fis = new FileInputStream("employee.txt");

ObjectInputStream ois =new ObjectInputStream(fis);

Employee e;

for(int i=0;i<4;i++)

{

e=(Employee)ois.readObject();

System.out.println(e.name+":"+e.age+":"+e.salary);

}

ois.close();

}

}

class Employee implements Serializable

{

String name;

int age;

double salary;

transient Thread t1 =new Thread();

Employee(String name,int age,double salary)

{

this.name=name;

this.age=age;

this.salary=salary;

}

//可以写private void readObject()方法来控制我们自己想要实现的

private void writeObject(java.io.ObjectOutputStream oos)throws Exception

{

//例如我们自己写想要显示的顺序和那些需要显示

oos.writeInt(age);

oos.writeUTF(name);

System.out.println("Write Object");

}

private void readObject(java.io.ObjectInputStream ois)throws Exception

{

//按照写入的顺序来读取

age=ois.readInt();

name=ois.readUTF();

System.out.println("Read Object");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值