看张孝祥视频学习Java IO笔记

本文详细介绍了 Java 中的各种 I/O 流操作,包括文件读写、缓冲流、数据流、管道流等,并探讨了字符编码及随机访问文件的相关概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

File
1、File即可表示文件也可表示文件夹
2、在创建File对象时,若要做到系统无关可用File类的静态成员变量File.seperator,它会根据运行系统自动被解析为相应的分隔符,如widows系统以\为文件分隔符,而Linux、UNIX等则用/
3、File rootDir = new File(File.seperator);表示rootDir 指向当前目录的根目录(如E:\),此后可用File ff = new File(rootDir ,"aa"+File.seperator+"bb");在root:\a\下创建文件夹b(或文件b.txt)
4、File对象可直接调用delete()方法删除自己,但若该对象指向一个目录,仅当目录为空时才能被删除,若里面有文件,则需要构造一个递归的delete方法将目录及其子目录删除。有一个deleteOnExit()方法是用来在程序退出时删除文件对象,一般用在删除程序运行时创建的临时文件
5、list和listFiles,前者返回String[],后者返回File[]。
在list方法有个有用的重载方法String[] list(FilenameFilter f),可以把一个匿名的FilenameFilter类写成内部类,来过滤所列文件,如下例:
String[] names = f.list(new FilenameFilter(){
public boolean accept(File dir,String name){
return name.indexOf(".java")!=-1//返回所以.java文件
}
}
);

I/O
1、流的分类
a、节点流:从特定地方读写的流类
b、过滤流(装饰):使用节点流作为输入或输出,为其提供额外的功能
2、InputStream:
常用方法
abstract int read():读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
int read(byte[] b):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1同上。
int read(byte[] b,int off,int len):功能同上。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。
long skip(long n):在输入流中跳过n个字节并返回实际跳过的字节数。
int available():返回在不发生阻塞的情况下,可读取的字节数。
void close():关闭输入流,释放相关系统资源。
void mark(in readlimit):在输入流的当前位置放置一个标记,如果读取的字节数多余readlimit设置的值,则忽略这个标记。(在InputStream中是空实现)
void reset():返回到上一个标记。(在InputStream中是空实现)
boolean markSupported():测试当前流是否支持mark和reset方法。如果支持,返回true,否则false。
InputStream——》FileInputStream
——》ByteArrayInputStream
——》FilterInputStream——————》DataInputStream
——》ObjectInputStream ——》BufferedInputStream
——》PiledInputStream ——》LineNumberInputStream(很少用)
——》SequenceInputStream ——》PushbackInputStream(很少用)
——》StringBufferInputStream(Deprecated,被StringReader代替)

3、OutputStream
常用方法
abstract void write(int b)
void write(byte[] b)
void write(byte[] b,int off,int len)
参数含义和方法含义InputStream对应
void flush():刷新输出流,强制缓冲区中的输出字节被写出。(用于使用了缓存的输出流,有时候不等缓存满我们就想将缓冲区中数据写出去,则可用该方法,在OutputStream中是空实现)
void close():关闭输出流,释放相关资源。

OutputStream——》FileOutputStream
——》ByteArrayOutputStream
——》FilterOutputStream——————》DataOutputStream
——》ObjectOutputStream ——》BufferedOutputStream
——》PiledOutputStream ——》PrintStream

4、FileOutputStream/FileInputStream
节点流,用于从文件中读取或在文件中写入字节流,如果构造FileOutputStream时文件已经存在,则覆盖这个文件!可用文件名或File对象构造,并且重写了三个writer方法。
例子:
FileOutputStream fos = new FileOutputStream("1.txt");
fos.write("hello world".getByte());
fos.close();

FileInputStream fis = new FileInputStream("1.txt");
byte[] buf = new byte[100];
int len = fis.read(buf);
fis.close();

5、BufferedInputStream/BufferedOutputStream(BufferedInputStream实现了void reset()和boolean markSupported();BufferedOutputStream实现了void flush())
装饰流,提供缓存功能,需要由已有的输入输出流创建
例子1:
FileOutputStream fos = new FileOutputStream("1.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("hello world".getByte());
//bos.flush();如果没有调用关闭也不调用flush,字符串就会留在缓存里而不写入到文件中,因为缓冲还没有满
bos.close(); //如果没有调用flush而是调用了close,字符串会被写到文件中,因为此时表明输入结束,无论缓存是否满都应将数据写出
多个流对象组成的复合流对象只要关闭最外面那个,里面的流对象都会自动关闭,不用每个都调用close
例子2:
FileInputStream fis = new FileInputStream("1.txt");
BufferedInputStream bis = new BufferedInputStream (fis);
byte[] buf = new byte[100];
int len = bis.read(buf);//以缓存读的方式将t.txt中的数据读入到buf中,并返回读取字节数len
System.out.println(new String(buf,0,len));//打印出读取到buf中的部分
bis.close();

6、DataInputStream/DataOutputStream
过滤流,提供了读取/写入java中基本数据的功能,需要由已有的输入输出流创建。
DataOutputStream dos = new DataOutputStream(bos);//此处以bos为基础创建DataOutputStream相当于在原有缓冲输出流的基础上在增加了写入java基本类型的功能。当然此处也能仅以fos为基础创建
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();

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();

7、PipedInputStream/PipedOutputStream
管道流,属于节点流,总是成对出现才有效。用于线程间通信,一个线程的PipedInputStream对象要从另一个线程的PipedOutputStream对象读取输入。
两种对象都可以用对方的对象来创建自己的对象,也可以在创建后用connect方法连接起来,以便完成输入输出任务。
例子:
class PipedStreamTest{
public static void main(String[] args){
PipedOutputStream pos = new PipedOutputStream();
PipedinputStream pis = new PipedInputStream();
try{
pos.connect(pis);//pis.connect(pos);both ok!
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.writer("welcome you!".getBytes());
pos.close();
}catch(Exceptrion e){
e.printStackTrace();
}
}
}

class Consumer extends Thread{
pirvate pipedInputStream pis;
public 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(Exceptrion e){
e.printStackTrace();
}
}
}
运行结果:
welcome!

8、Read/Writer
Reader——》BufferedReader ———》LinNumberReader
——》CharArrayReader
——》FilterReader ———》PushbackReader
——》InputStreamReader ———》FileReader
——》PipedReader
——》StringReader
*张孝祥称没有把BufferedReader(BufferedWriter)设计成FilterReader(FilterWriter)子类是SUN公司的一个bug,真的是这样么?

*InputStreamReader充当字节流-->字符流的桥梁
Wirter——》BufferedWirter
——》CharArrayWirter
——》FilterWirter
——》OutputStreamWirter ———》FileWirter
——》PipedWirter
——》PrintWirter
——》StringWirter
*OutputStreamWirter 充当字符流-->字节流的桥梁

例子:
FileOutputStream fos = new FileOutputStream("1.txt");
//此处OutputStreamWriter 不是充当过滤流的角色,而是作为一个连接字节流-->字符流的桥梁
OutputStreamWriter osw = new OutputStreamWriter(fos);
//一般不会直接用OutputStreamWriter作为输出流,而会用它创建一个缓存输出流。虽然Writer类及其子类不是严格按照装饰类方式设计,但操作上与装饰类一致
BufferedWriter bw = new BufferedWriter(osw);
bw.writer("hello world!");
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 isr1 = new InputStreamReader(System.in);
BufferedReader br1 = new BufferedReader(isr1);
String strLine;
While((strLine = br.readLine()) != null)
System.out.println(strLine);
br.close();

9、字符编码
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码):每个ASCII码与一个8位二进制数对应。其最高位是0,相应的十进制数是0-127

GB2312:中华人民共和国国家汉字信息交换用码。一个中文字符用两个字节的数字来表示,位了和ASCII码有所区别,将中文字符每一个字节的最高位置都用1来表示

GBK是GB2312的扩展码,对不常用的汉子和许多符号进行了编码。

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

Unicode:对所有语言的文字进行了统一编码,对每个字符都用了2个字节来表示(即能表示65536种字符),对于英文字符采取前面加0字节的策略,实现了等长兼容。如“a”的ASCII码为0x61,Unicode就为0x00 0x61

UTF-8:Eight-bit UCS Transformation Format(UCS,Universal Character Set,通用字符集)一个7位的ASCII码值,对应的UTF码是一个字节。如果字符是0x0000,或在0x0080与0x007f之间,对应的UTF码是两个字节,如果字符在0x0800与0xffff之间,对应的UTF码是三个字节(汉字在UTF-8中是三个字节)

10、在java编程过程中需要注意的三处编码:
1)外部输入数据的编码:这与输入数据的编码有关
a、如果是用标准输入输入的数据,则是与当前操作系统的默认编码有关,例如用中文版的windows2000操作系统,起默认编码是GBK,因此若用标准输入System.in.read()读入的数据是经过GBK编码的,即读入的都是GBK的码值。
b、如果是用文件作为输入的话,如文本文件(txt、xml等),其编码与文件本身的编码有关(查看文件本身的编码可以用文本编辑器如notepad或UltraEdit等的另存为查看)。如在windowsXP操作系统中的txt文件默认用ANSI编码,若要改成别的编码可在另存为时将编码改成其他编码。
c、如果是从数据库中读取数据,则与具体数据库表的存储编码相关。

2)JVM的默认编码:这是JVM在执行解码/编码操作时默认采用的编码,可通过以下代码看到:
Porperties pps = System.getPorperties();
pps.list(System.out);//list接受一个OutputStream作为参数,此处用标准输出
在列表中的file.encoding=?项即表明当前JVM用的默认编码
若要修改默认编码可通过以下代码:
pps.put("file.encoding","ISO-8859-1");//此处将默认编码改为ISO-8859-1
在ecipse中有友好的图形化界面可设置。

3)java语言中字符串和字符类型的编码:java中的字符串和字符类型始终采用Unicode编码,任何数据想转换成字符串或字符打印的过程都叫解码,反之,将字符串和字符中的数据输入到别的载体中时叫编码。

由于上述三个编码的不统一常在编程中发生编解码乱码问题,例如:
java程序从外部输入流中(数据库、文件系统、标准输入等)中获得数据,外部数据以byte[]形式(A编码)被读入java程序内部,变成java中的String或char(若变成数值类型则不会碰到编码问题,此处不考虑这种情况),此时外部数据若没有特殊指定,就会按照jvm默认的编码被解码成unicode的String或char,如果默认的编码格式是A则相安无事,若不是,则解码后存在String对象或char变量中的字符已是乱码,若再转由输出流输出必然是乱码。

11、RandomAccessFile
RandomAccessFIile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,利用这个类可以在文件的任何位置读取或写入数据。
RadndomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下以数据的位置。
写入数据有三个方法:
writeByte(String s):写入一个字节,一般用户西文字符的输入,因为它写入一个字符(因为String可以视为char[],它以char为单位写入)的前半个字节,舍弃后半个字节,因为西文字符后半字节为空。因为当输入字符中有西文字符时不建议使用
writeChar(String s):写入整个字符信息
writeUTF(String s):按UTF-8编码写入信息,如西文字符输入两个字节的编码,中文字符则为三个字节。这个方法会在输入数据的前两个字节里记录共输入几个字节字符,因此读取时比较有方便,对应也有一个String readUTF()方法。
RandomAccessFile的构造方法:
RandomAccessFile(File file, String mode) 、RandomAccessFile(String name, String mode) 。mode为存储格式,可以为"r"、"rw"、"rws、"rwd"
例子:

class RandomFileTest{
public static void main(String[] args)throws Exception{
Studend s1 = new Student(1,"zhangsan",98.5);
Studend s2 = new Student(2,"lisi",95.5);
Studend s3 = new Student(3,"wangwu",78.5);
RandomAccessFile raf = new
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值