java基础—IO (下)
一、转换流
转换流的由来:
字符流与字节流之间的桥梁。
方便了字符流与字节流之间的操作。
转换流的应用:字节流的数据都是字符时,转成字符流操作更高效。
转换流:
InputStreamReader:字节到字符的桥梁,编码。
OutputtreamWriter:字符到字节的桥梁,解码。
示例:
- 需求:用转换流编写如下代码,获取用户键盘录入的数据并将数据变成大写显示在控制台上,如果用户输入的是over,结束键盘录入。
import java.io.*;
class ReadKey1
{
public static void main(String[] args) throws IOException
{
//将键盘录入数据与输入流相关联,字节流转换成字符流
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while ((line=bufr.readLine())!=null)
{
//若输入“over”,则结束键盘录入
if (line.equals("over"))
{
break;
}
//将键盘录入的数据转换成大写
System.out.println(line.toUpperCase());
}
}
}
- 输出结果:
二、流的操作规率
明确源和目的
源:IuputStream Reader
目的:OutputStream Writer
明确数据是否是纯文本数据
源:是纯文本:Reader;否:InputStream
目的:是纯文本:Writer;否:OutputStream
备注:到这里就可以明确需求中具体要使用哪个体系。
明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
键盘:System.out
内存:数组
网络:Socket流
是否需要其他额外功能
- 是否需要高效(缓冲区):是,就加上buffer
三、File类
定义:File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。
作用:File对象可以作为参数传递给流的构造函数。
File对象的常用方法:
获取
获取文件名称:String getName();
获取文件路劲:String getPath();
获取文件大小:long length();
获取文件修改时间:long lastModified();
创建和删除
boolean createNewFile(); 文件不存在的时候创建一个新的空文件。
boolean delete(); 删除此抽象路径名表示的文件或目录。
判断
boolean exists();判断文件或目录是否存在。
boolean isFile();测试此抽象路径名表示的文件是否是一个标准文件。
boolean isDirectory(); 测试此抽象路径名表示的文件是否是一个目录。
重命名
- boolean renameTo(File dest); 重新命名此抽象路径名表示的文件。
系统根目录和容量获取
Sting[] list();返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
long getFreeSpace(); 返回此抽象路径名指定的分区中未分配的字节数。
long getTotalSpace();返回此抽象路径名指定的分区大小。
long getUsableSpace();返回此抽象路径名指定的分区上可用于此虚拟机的字节数。
示例:
- 代码:
File f=new File("file.txt");//创建一个File实例
boolean b1=f.exists();//判断此文件是否存在
System.out.println(b1);
if(!f.exists())
{
f.createNewFile();//若文件不存在,则创建一个新的空的文件
}
if(f.exists())
{
System.out.println(f.isFile());//若文件存在,则判断此文件是否是个标准文件
}
f=new File("abc\\ab");
f.mkdirs();//创建目录
if(f.exists())
{
System.out.println(f.isDirectory());//若存在,则判断此文件是否是个目录。
}
四、递归
- 定义:函数自身直接或者间接的调用到了自身。一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。这时可以用递归来解决问题。
- 示例
- 需求:对指定目录进行所有内容的列出(包含子目录中的内容),也可以理解为深度遍历。
- 代码:
import java.io.*;
class FileListDemo
{
public static void main(String[] args)
{
//将java2015文件夹封装成对象;
File dir=new File("D:\\java2015");
listAll(dir,0);
}
public static void listAll(File dir,int level)
{
System.out.println(getSpace(level)+"dir:"+dir.getAbsolutePath());
level++;
//获取指定目录下的文件和文件夹
File[] files=dir.listFiles();
for(File file:files)
{
//若获取的为文件夹则继续获取子文件中的内容
if(file.isDirectory())
listAll(file,level);
//将获取的文件打印到控制台上
else
{
System.out.println(getSpace(level)+"file:"+file);
}
}
}
//获取标记,显示获取的文件夹或文件在指定目录中的层级。
private static String getSpace(int level)
{
StringBuilder sb=new StringBuilder();
sb.append("|--");
for (int x=0;x<level ;x++ )
{
sb.append("|--");
}
return sb.toString();
}
}
- 输出结果:
五、Properties集合
Map
- |–Hashtable
- |–Properties
- |–Hashtable
特点:
-
- 该集合中的键和值都是字符串类型。
-
- 集合中的数据可以保存到流中,或者从流中获取。
-
- 通常该集合用于操作以键值对形式存在的配置文件。
-
常用方法:
setProperty();储存元素。
getProperty():用指定的键在此属性列表中搜索属性。
stringPropertyNames() : 返回此属性列表中的键集。
list(PrintStream out) : 将属性列表输出到指定的输出流。
示例:
- 代码:
import java.util.*;
import java.io.*;
class PropertiesDemo
{
public static void main(String[] args)throws IOException
{
Properties p=new Properties();
//添加元素
p.setProperty("zhangshang","20");
p.setProperty("lisi","24");
p.setProperty("xupeng","23");
//修改元素
p.setProperty("xupeng","25");
//获取p的键集
Set<String> names=p.stringPropertyNames();
//将键值对打印出来
for(String name:names)
{
String value=p.getProperty(name);
System.out.println(name+":"+value);
}
}
}
- 输出结果:
六、 IO包中的其他流
打印流:PrintWriter与PrintStream(可以直接操作输入流和文件)
PrintStream:
提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式。
它不抛出IOException
构造函数,接受三种类型的值:
字符串路径
File对象
字节输出流
PrintWriter:字符打印流
构造函数参数
字符串路劲
File对象
字节输出流
字符输出流
序列流:SequenceInputStream(对多个流进行合并)
对象流:ObjectInputStream和ObjectOutputStream
- 注意:被操作的对象需要实现Serializable接口。
RandomAccessFile
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)等方法来达到随机访问。
特点:
该对象即能读,又能写。
该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素。
可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
。其实该对象就是将字节输入流和输出流进行了封装。
该对象的源或者目的只能是文件。通过构造函数就可以看出。
管道流:PipedInputStream和PipedOutputStream(输入输出可以直接进行连接,通过结
合线程使用)操作基本数据类型:DataInputStream与DataOutputStream
操作字节数组:ByteArrayInputStream与ByteArrayOutputStream
- 特点:关闭字节数组输入输出流无效,因为它们没有调用底层资源,所有的操作都是在内存中完成的。
七、编码表
编码表的由来:计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表,这就是编码表。
常见的编码表:
ASCII:美国标准信息交换码,用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。
示例:
- 代码:
import java.io.*;
class EncodeDemo
{
public static void main(String[] args) throws Exception
{
String str="您好";
//字符串-->字节数组:编码
//字符数组-->字符串:解码
//编码
byte[] buf1=str.getBytes("GBK");//GBK编码表
printBytes(buf1);
byte[] buf2=str.getBytes("UTF-8");//UTF-8编码表
printBytes(buf2);
//解码
String s1=new String(buf1);
System.out.println("s1="+s1);
String s2=new String(buf2,"UTF-8");
System.out.println("s2="+s2);
}
//将字节数组打印出来
private static void printBytes(byte[] buf)
{
for(byte b:buf)
{
System.out.print(b+""+"\t");
}
System.out.println();
}
}
- 输出结果: