第一讲 File类
一、简述
- File类:文件和目录路径名的抽象表现形式。
- 作用:
- 用来将文件或者文件夹封装成对象。方便于对文件或文件夹的属性信息进行操作。
- 特点:
- 流只能操作数据,而想要操作数据被封装的文件的信息必须用File对象。
- File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变
- File对象可以作为参数传递给流的构造函数。
二、创建对象
- 三种创建方式
- File file = new File("a.txt");
- 将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。
- File file = newFile("e:\\abc","b.txt");
- 将文件所在目录路径和文件一起传入,指定文件路径。
- File f = new File("e:\\abc"); File file = new File(f,"c.txt");
- 将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。
- File file = new File("a.txt");
三、常见方法:
- 创建:
- boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false.
- 和输出流不一样,输出流对象一建立就创建文件,而文件已经存在,会覆盖。
- boolean mkdir():创建文件夹。
- boolean mkdirs():创建多层文件夹。
- boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false.
- 删除:
- boolean delete(): 删除失败返回false.
- void deleteOnExit():在程序退出时删除指定文件。
- 判断:
- booelean canExecute():判断文件是否可执行。
- boolean exists(): 判断文件或目录是否存在。
- boolean isFile():判断是否是文件。
- boolean isDirectory():判断是否是目录。
- 在判断文件对象是否是文件或者是目录时,必须要先判断该文件对象封装的内容是否存在。通过exists判断。
- boolean isHidden():判断是否是隐藏文件。
- boolean isAbsolute():判断是否是绝对路径。
- 获取信息:
- String getName():获取文件名。
- String getPath():获取文件相对路径。
- String getParent():获取文件父目录。该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。
- File getAbsoluteFile():获取文件绝对路径并将其封装成对象。
- String getAbsolutePath():获取文件绝对路径。
- long lastModified():获取文件最后一次修改时间。
- long length(): 获取文件大小。
- File.pathSeparator:返回当前系统默认的路径分隔符,windows默认为 “;”。
- File.Separator:返回当前系统默认的目录分隔符,windows默认为 “\”。
- 重命名:
- boolean renameTo():将文件重命名,并转移到制定目录下。
- 获取计算机的盘符:
File[] files = File.listRoots();
for (File f:files){
System.out.println(f);
}
- String[] list()方法:
- 当list方法所属对象是文件时而不是目录时,返回数组为null,调用list方法的File对象必须是封装的一个目录,而且该目录必须存在。
例如:获取C盘下当前所有的文件夹以及文件的名称(包含隐藏文件)。
File f = new File("c:\\");
//File f = new File("c:\\abc.java");
String[] names = f.list();
for (String name:names){
System.out.println(name);
}
- 当list方法所属对象是文件时而不是目录时,返回数组为null,调用list方法的File对象必须是封装的一个目录,而且该目录必须存在。
- String[] list(FileNameFilter,filter)
- 返回满足过滤器的文件或目录。
- 文件过滤器 FileNameFilter 接口,接口中只有一个返回值为boolean 型的accept()方法。
例如:用匿名内部类的方式来进行文件过滤:返回E盘下mp3文件:
File dir = new File("E:\\");
String[] arr = dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
});
{
return name.endsWith(".mp3");
}
//E盘下文件。
System.out.println("len:"+arr.length);
for (String name: arr){
System.out.println(name);
}
注:list()方法 只返回当前文件目录下的文件及目录的名称。
- File[] listFiles()
- 返回当前目录下的文件以及文件夹的对象。
例如:获取当前目录下的文件及文件夹名称及长度。
File dir = new File("E:\\");
File[] files = dir.listFiles();
for (File f : files){
System.out.println(f.getName() +"::"+f.length());
} - File[] listFiles(FileNameFilter,filter)返回满足过滤器的文件或目录。
- 返回当前目录下的文件以及文件夹的对象。
练习:删除一个带内容的目录
删除原理:在Windows中,删除目录从里面往外删除的。既然是从里往外删除,就需要用到递归。
注:在删除系统盘时,有些是删不掉的。因为有些隐藏目录Java无法访问。无法访问就导致返回数组为空,会出现空指针异常。
系统中有些文件看上去是文件实际是目录,看上去是目录实际上是文件。没有扩展名,会出现空指针异常,导致程序停止。
import java.io.*;
class RemoveDir
{
public static void main(String[] args)
{
File dir = new File("H:\\Exercise");
removeDir(dir);
}
public static void removeDir(File dir)
{
File[] files = dir.listFiles();
for (int x = 0;x < files.length;x++)
{
if(files[x].isDirectory())
removeDir(files[x]);
else
System.out.println(files[x].toString()+"::"+files[x].delete());
}
System.out.println(dir+"::dir::"+dir.delete());
}
}
四、递归
- 什么是递归:
- 当一个功能被重复使用,而每一次使用该功能时的参数不确定,都由上次的功能元素结果来确定。
- 简单说:功能内部又用到该功能,但是传递的参数值不确定。(每次功能参与运算的未知内容不确定)。
- 其实递归就是在栈内存中不断的加载同一个函数。
- 递归的注意事项:
- 一定要定义递归的条件。限定条件,程序必须能够结束。
- 递归的次数不要过多。容易出现 StackOverflowError 栈内存溢出错误。
- 原因:当调用函数时会在栈内存中开辟空间,如果调用的次数过多,函数在栈内存中创建的空间就越大,函数没有执行结束,内存空间得不到释放,导致内存溢出。
练习:
import java.io.*;
class FileDemo3
{
public static void main(String[] args)
{
File dir = new File("G:\\360Downloads");
showDir(dir);
toBin(8);
int n = getSum(10);
System.out.println("n = "+ n);
}
//输出目录下所有文件夹及文件
public static void showDir(File dir)
{
System.out.println(dir);
File[] files = dir.listFiles();
for (int x = 0;x < files.length;x++)
{
if(files[x].isDirectory())
showDir(files[x]);
else
System.out.println(files[x]);
}
}
//求一个整数的2进制
public static void toBin(int num)
{
/*
while (num>0)
{
System.out.println(num%2);
num = num / 2;
}
*/
if (num>0)
{
toBin(num/2);
System.out.println(num%2);
}
}
public static int getSum(int n)
{
//递归求和
if (n==1)
return 1;
return n+getSum(n-1);
}
}
第二讲 Properties类
一、简述
Properties类是Hashtable的子类。也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串,不需要泛型。是集合中和IO技术相结合的集合容器。
- 特点:
- 一般用于键值对形式的配置文件。
- 在加载数据时,需要数据有固定格式:键=值。
- 可以持久化存储数据。
二、特有方法
- 设置
- Object setProperty(String key,String value);
- 设置键和值,调用Hashtable的方法put
- 获取
- String getProperty(String key) 指定key搜索value
- Set<String> stringPropertyName() 返回属性列表的键集,存入Set集合
- 加载流和存入流
- void load(InputStream ism) 从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
- void load(Readerreader) 从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
- void list(PrintStream out) 将属性列表输出到指定的输出流
- void store(OutputStreamout,String comments) 对应load(InputStream ) 将属性列表(键值对)写入输出流。comments属性列表的描述。
- void store(Writerwriter, String comments); 对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。
练习: 用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。
/*
练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。
分析:
很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在并进行了自增。可是随着该应用程序的退出,
该计数器也在内存中消失了。下一次再启动该程序,又重新开始从0记数。这样不是我们想要的。
程序即使结束,该计数器的值也存在。下一次程序启动后会先加载该计数器的值并加1后再重新存储起来。
所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。这样便于阅读数据,并操作数据。
键值对数据是map集合。数据是以文件形式存储,使用IO技术。那么map+IO -->Properties。
思路:1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建
2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。
3、将值小于等于5次的信息数据存入文件中
*/
import java.io.*;
import java.util.*;
class RunCount
{
public static void main(String[] args) throws IOException
{
Properties prop = new Properties();
// 创建配置文件
File file = new File("count.ini");
// 如果文件不存在就创建一个文件
if(!file.exists())
file.createNewFile();
//创建流对象与文件相关联
FileInputStream fis = new FileInputStream("count.ini");
//将流中的数据加载进集合。
prop.load(fis);
//用于记录程序运行次数
int count = 0;
//根据键获取值
String value = prop.getProperty("time");
if(value != null)
{ //如果值不为空,将值转化成整数付给计数器。
count =Integer.parseInt(value);
if(count>=5)
{
System.out.println("您好,使用次数已到,请注册");
return ;
}
}
count++;
//设置键值
prop.setProperty("time",count+"");
//将设置的键值保存到文件中
FileOutputStream fos = new FileOutputStream(file);
prop.store(fos,"setTime");
//关闭流资源
fos.close();
fis.close();
}
}
第三讲 其他流
一、打印流
- 打印流:
- 包括PrintStream PrintWriter
- 该流提供了特有的打印方法,可以将各种数据类型的数据都原样打印。
- 字节打印流:PrintStream
- 构造函数可以接受的参数类型:
- File对象,File。
- 字符串路径,String.
- 自节输出流,OutputStream。
- 字符打印流:PrintWriter
- 构造函数可以接受的参数类型:
- file对象,File。
- 字符串路径,String.
- 自节输出流,OutputStream。
- 字符输出流,Writer。
- 注:PrintWriter(OutputStream out,boolean autoFlush),autoFlush,如果为true,println、printf或format方法将刷新缓冲区。
练习:
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
//键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//创建打印流对象,指定目的地
//PrintWriter out = new PrintWriter(System.out);
// 创建打印流对象,指定目文件相关联,并加入缓冲技术
PrintWriter out =
new PrintWriter(new BufferedWriter(new FileWriter("a.txt")),true);
String line = null;
while ((line = bufr.readLine())!=null)
{
if("over".equals(line))
break;
//将数据写入缓冲区
//out.write(line);
//将数据从缓冲区刷新到目的地
//out.flush();
// 将数据写入缓冲区,从缓冲区刷新到目的地
out.println(line);
}
//关闭流
out.close();
bufr.close();
}
}
异常日志
在程序使用过程当中,程序出现问题是不希望打印给用户看到的,因此,创建程序的异常日志,将出现的问题存储,方便程序员对程序进行修改。
示例:
import java.io.*;
import java.util.*;
import java.text.*;
class ExceptionInfo
{
public static void main(String[] args) throws IOException
{
try
{
int[] arr = new int[2];
System.out.println(arr[3]);
}
catch (Exception e)
{
try
{
//创建时间对象
Date date = new Date();
//将时间格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
String s =sdf.format(date);
//创建输出对象与文件相关联
PrintStream ps = new PrintStream("exception.log");
//输出异常发生时间
ps.println(s);
//设置输出设备为文件
System.setOut(ps);
}
catch (Exception ex)
{
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);
}
}
}
获取系统信息
步骤:
- 创建Properties对象,接收System类的getProperties()获取的系统信息。
- 将信息输出到指定输出流中
- 用Properties对象的list(PrintStream out)
- 将输出流中数据存入指定文件中
- new PrintStream("sysout.txt")
import java.util.*;
import java.io.*;
class SystemInfo
{
public static void main(String[] args) throws IOException
{
Properties prop = System.getProperties();
//将系统信息输出在控制台
//System.out.println(prop);
//prop.list(System.out);
//将系统属性信息存储到关联文件中
prop.list(new PrintStream("sysout.txt"));
}
}
二、 序列流 (SequenceInputStream)
- 作用:对多个流进行合并。
- 构造函数:
- SequenceInputStream(InputStream s1,InputStream s2)
- SequenceInputStream(Enumeration<? extends InputStream> e)
- 常见合并多个流文件步骤
- 创建集合,并将流对象添加进集合
- 创建Enumeration对象,将集合元素加入。
- 创建SequenceInputStream对象,合并流对象
- 创建写入流对象,FileOutputStream关联写入文件
- 利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。
/*
练习:合并多个.txt文件
*/
import java.io.*;
import java.util.*;
class SequenceDemo
{
public static void main(String[] args) throws IOException
{
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("E:\\1.txt"));
v.add(new FileInputStream("E:\\2.txt"));
v.add(new FileInputStream("E:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
//创建序列流对象接收Enumeration对象
SequenceInputStream sis = new SequenceInputStream(en);
//创建输出流对象与文件相关联
FileOutputStream fos = new FileOutputStream("E:\\4.txt");
//创建缓冲区
byte[] buf = new byte[1024];
int len = 0;
while ((len =sis.read(buf))!=-1)
{
//将缓冲区读取的数据写到目的地
fos.write(buf,0,len);
}
//关闭流资源
fos.close();
sis.close();
}
}
练习:文件的切割与合并
import java.io.*;
import java.util.*;
class SplitMergeFile
{
public static void main(String[] args) throws IOException
{
//splitFile();
merge();
}
//切割
public static void splitFile()throws IOException
{
//创建读取流流对象与文件相关联
FileInputStream fis = new FileInputStream("E:\\1.bmp");
//创建写入流对象
FileOutputStream fos = null;
//创建缓冲区
byte[] buf = new byte[1024*1024];
int len = 0;
//对切割次数进行标记
int count = 1;
//将切割缓冲区数据读取并写入目的地
while ((len = fis.read(buf))!=-1)
{
fos = new FileOutputStream("E:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
//合并
public static void merge()throws IOException
{
//创建集合对象
ArrayList<FileInputStream> al = new ArrayList<FileInputStream> ();
//创建流对象与文件相关联并将流对象添加到集合中
for (int x = 1;x<=3 ;x++)
{
al.add(new FileInputStream("E:\\splitfiles\\"+ x +".part"));
}
//创建迭代器
final Iterator<FileInputStream> it = al.iterator();
//枚举的匿名内部类来实现迭代
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
//复写 Enumeration方法
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
//c创建序列流对象接收Enumeration对象
SequenceInputStream sis = new SequenceInputStream(en);
//创建输出流对象与文件相关联
FileOutputStream fos = new FileOutputStream("E:\\splitfiles\\0.bmp");
//创建缓冲区
byte[] buf = new byte[1024*1024];
int len = 0;
while ((len = sis.read(buf))!= -1)
{
//将缓冲区读取的数据写到目的地
fos.write(buf,0,len);
}
//关闭流资源
fos.close();
sis.close();
}
}
三、对象的序列化:
- 对象的持久化存储(序列化)
- 对象本身存在于堆内存中,当程序结束后,内存中的垃圾回收,对象也就消失了。
- 用流将对内存中的对象存储在硬盘上,叫做对象的持久化存储。使用到的类:ObjectInputStream,ObjectOutputStream。
- 被操作的对象需要实现Serializable接口。
- 目的:将一个具体的对象进行持久化,写入到硬盘上。
- 注:
- 对象中静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。
- 用transient关键字修饰变量,可以让非静态数据不被序列化。
- Serializable接口:
- 用于启动对象的序列化功能,可以强制让指定类具备序列化功能,该接口中没有成员,这是一个标记接口。
- 这个标记接口用于给序列化类提供UID。这个uid是依据类中的成员的数字签名进行运行获取的。
- 如果不需要自动获取一个uid,可以在类中,手动指定一个名称为serialVersionUID id号。
- "serialVersionUID"的字段(该字段必须是静态 (static)、最终 (final)的 long 型字段)。
- 如: public static final long serialVersionUID = 42L;
- 依据编译器的不同,或者对信息的高度敏感性。最好每一个序列化的类都进行手动显示的UID的指定。
- 写入流对象:
- 创建对象写入流,与文件关联,即传入目的。
- 通过写入writeObject(Object obj)方法,将对象作为参数传入,即可写入文件。
- 读取流对象
- 创建对象读取流,与文件关联,即传入源。
- 通过readObject()方法,读取文件中的对象,并返回这个对象。
/*
需求:将一个对象序列号,并从硬盘中读取序列化的对象
*/
import java.io.*;
public class ObjectStreamDemo {
public static void main(String[] args) {
writeObj();
readObj() ;
}
//将指定对象序列化到指定文件中
public static void writeObj()
{
ObjectOutputStream oos =null;
try {
//将一个对象写到文件当中,
//数据不是纯文本,对文件进行操作
//选择FileOutputStream
oos = new ObjectOutputStream(new FileOutputStream("person.object"));
//数据("lisi",29) 在堆内存中 被封装到Person对象中,
//将Person对象写入到文件"obj.txt"中
oos.writeObject(new Person("lisi",29,"kr"));
} catch (Exception e) {
throw new RuntimeException("写入数据失败");
}
finally{
try {
if(oos!=null)
oos.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}
//读取指定文件中的对象,也称反序列化
public static void readObj()
{
ObjectInputStream ois =null;
try {
//创建读取流对象,关联文件
ois = new ObjectInputStream(new FileInputStream("person.object"));
//读取文件中的对象
Person p = (Person)ois.readObject();
System.out.println(p.getName()+":"+p.getAge()+":"+p.getCountry());
} catch (Exception e) {
throw new RuntimeException("读取数据失败");
}
finally{
try {
if(ois!=null)
ois.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
}
}
}
//创建Peason类,实现Serializable接口
class Person implements Serializable
{
//自定义serialVersionUID版本号
private static final long serialVersionUID = 42L;
private String name;
transient int age;//用transient修饰后age将不会进行序列化
static String country ="cn";//静态数据不会进行序列化
Person(String name,int age,String country)
{
this.name = name;
this.age = age;
this. country= country;
}
public String getName() {
return name + ":" + age +","+id+","+ country;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static String getCountry() {
return country;
}
public static void setCountry(String country) {
Person.country = country;
}
}
四、管道流:
- 管道流:PipedInputStream。PipedOutputStream。
- 特点:
- 输入输出可以直接进行连接,不用再借助数组或集合等容器进行临时存储。connect()方法,链接管道输入流和管道读取流。
- 通过结合线程使用。管道读取流可以读取管道写入流写入的数据。
- 注:因为read方法是阻塞式的,没有数据的read方法会让线程等待。使用单线程,先执行read,会发生死锁,所以需要使用多线程技术。
- 通常,数据由某个线程写入PipedOutputStream对象,并由其他线程从连接的 PipedInputStream 读取。
- 一般操作步骤:
- 要先创建一个读和写的两个类,实现Runnable接口,因为是两个不同的线程,覆盖run方法,注意,需要在内部处理异常。
- 创建两个管道流,并用connect()方法将两个流连接
- 创建读写对象,并传入两个线程内,并start执行。
import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in = in;
}
public void run()//覆盖run方法。异常不能抛,只能try。
{
try
{
byte[] buf = new byte[1024];
System.out.println("读取前..没有数据,阻塞");
//阻塞式方法read,没有数据就得等,等些入数据后才执行。
int len = in.read(buf);
System.out.println("读到数据..阻塞结束");
String s = new String(buf,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待6秒后.");
Thread.sleep(3000);
out.write("piped lai la".getBytes());
out.close();
}
catch (Exception e )
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args) throws IOException
{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
五、RandomAccessFile类
- 作用:可以实现数据的分段写入。(下载软件原理,多线程下载)
- 该类不算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员。因为它具备读和写的功能。
- 特点:
- 该对象既可以读取,也可以写入。
- 对象内部封装了一个byte数组,而且通过指针对数组的元素进行操作。,
- 该对象可以通过getFilePointer()方法获取指针位置。同时可以通过seek()方法改变指针的位置。
- 该对象操作的源和目的必须是文件。
- 该对象内部封装了字节输入流和字节输出流。
- 完成读写原理:
- 内部封装了字节输入流和字节输出流。byte数组操作的是字节。
- 通过构造函数可以看出,该类只能操作文件。
- 而且操作文件还有模式:只读r,读写rw等。,
- 如果模式为只读 r 。不会创建文件,会去读取一个已存在的文件。
- 如果该文件不存在,则会出现异常。
- 如果模式为rw。操作的文件不存在,会自动创建,如果存在则不会覆盖。
- 随机访问文件,自身具备读写的方法。
- 通过skipBytes(int x),seek(int x);来达到随机访问。
- skipBytes(int x),调整对象中指针,只能向后,不能向前。
- seek(int x) 调整对象中指针,可以前后移动。
- 注:在实现随机数据读取时,数据最好有规律。
练习:
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
writeFile();
readFile();
}
public static void readFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中指针。分段要有规律
//raf.seek(8*1);
//跳过指针的字节数。
raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name:"+name);
System.out.println("age = "+age);
raf.close();
}
public static void writeFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("张三".getBytes());
//write方法只写出int类型的最低8位。
raf.writeInt(99);
raf.write("李四".getBytes());
raf.writeInt(97);
raf.close();
}
//在文件随机位置写入数据
public static void writeFile_2()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*3);
raf.write("周七".getBytes());
raf.writeInt(103);
raf.close();
}
}
六、操作基本数据类型的流对象
- 操作基本数据类型的流对象:DataInputStream,DataOutputStream
- 可用于操作基本数据类型的流对象,包含读写各种基本数据类型的方法。
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);dos.writeBoolean(true);dos.writeDouble(9867.453);dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();boolean b = dis.readBoolean();double d = dis.readDouble();System.out.println("num =" +num);System.out.println("b =" + b);System.out.println("d =" + d);dis.close();
- 注:
- String readUTF();//对应writeUTF,读取以UTF-8修改版编码写入的字符串
- writeUTF(String str);//以与机器无关方式使用UTF-8修改版编码将一个字符串写入基础输出流。
- 操作字节数组的流:ByteArrayInputStream和ByteArrayOutputStream
- ByteArrayInputStream: 在构造的时候,需要接收数据源,而且数据源是一个字节数组。
- ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经封装了一个可变长度的字节数组。这就是数据目的地。
- 因为这两个流对象操作的都是数组并没有使用系统资源,所以不用进行close关闭。即使关闭后,仍可调用。
- 内部包含缓冲区,相当于以内存作为流操作源和目的,不会产生任何IO异常。
- 对象中封装了数组。
- 特有方法:
- ByteArrayOutputStream中:
- writeTo(OutputStream out);
- 将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用out.write(buf, 0, count)调用该输出流的 write 方法效果一样。
- 因为这个方法用到了字节输出流,需要抛IO异常,也是字节数组流中唯一需要抛异常的方法。
- int size();//当前缓冲区的大小
- String toString();使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。
- 对应的字符数组和字符串
- 字符数组流:CharArrayReader和CharArrayWriter
- 字符串流: StringReader和StringWriter
import java.io.*;
class ByteArrayStream
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
//数据源。
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFG".getBytes());
// 数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by = 0;
while ((by = bis.read())!= -1)
{
bos.write(by);
}
System.out.println(bos.size());
System.out.println(bos.toString());
//bos.writeTo(new FileOutputStream("a.txt"));
}
}