- 主要类
- File类
- 名称分隔符
path1="d:/temp/test.txt";
path2="d:"+File.separator+"temp"+File.separator+"test.txt";
//1、构建File对象
File src = new File(path);
System.out.println(src.length());
//2、构建File对象
src = new File("D:/java300/IO_study01","IO.png");
src = new File("D:/java300/","IO_study01/IO.png");
System.out.println(src.length());
//3、构建File对象
src = new File(new File("D:/java300/IO_study01"),"IO.png");
System.out.println(src.length());
- 路径基本信息
//用户目录
System.out.println(System.getProperty("user.dir"));
//取得绝对路径
src = new File("IO.png");
System.out.println(src.getAbsolutePath());
File src = new File("IO_study01/IO.png");
//基本信息
System.out.println("名称:"+src.getName());
System.out.println("路径:"+src.getPath());
System.out.println("绝对路径:"+src.getAbsolutePath());
System.out.println("父路径:"+src.getParent());
System.out.println("父对象:"+src.getParentFile().getName());
//文件状态
src = new File("xxx");
if(null == src || !src.exists()) {
System.out.println("文件不存在");
}else {
if(src.isFile()) {
System.out.println("文件操作");
}else { //src.isDirectory()
System.out.println("文件夹操作");
}
}
//获取文件的长度字节数(文件夹返回0)
File src = new File("D:/java300/IO_study01/IO.png");
System.out.println("长度:"+ src.length());
//文件操作
//createNewFile() : 不存在才创建,存在创建失败,只能创建文件
//delete():删除已经存在的文件
//操作系统的设备名不能作为文件名创建
File src = new File("D:/java300/IO_study01/io.txt");
boolean flag =src.createNewFile();
System.out.println(flag);
flag = src.delete();
System.out.println(flag);
- 创建目录
//1、mkdir() : 确保上级目录存在,不存在创建失败
//2、mkdirs(): 上级目录可以不存在,不存在一同来创建
File dir = new File("D:/java300/IO_study01/dir/test");
//创建目录 mkdirs()
boolean flag = dir.mkdirs();
System.out.println(flag);
//创建目录 mkdir()
dir = new File("D:/java300/IO_study01/dir/test2");
flag = dir.mkdirs();
System.out.println(flag);
- 列出目录信息
File dir = new File("D:/java300/IO_study01");
//下级名称 list
String[] subNames = dir.list();
for(String s:subNames) {
System.out.println(s);
}
//下级对象 listFiles()
File[] subFiles = dir.listFiles();
for(File s:subFiles) {
System.out.println(s.getAbsolutePath());
}
//所有盘符
File[] roots = dir.listRoots();
for(File r:roots) {
System.out.println(r.getAbsolutePath());
}
- 统计目录的大小(Byte)
public class Test {
public static void main(String[] args) {
File src = new File("D:\\java300\\IO_study01");
count(src);
System.out.println(len);
}
private static long len =0;
public static void count(File src) {
//获取大小
if(null!=src && src.exists()) {
if(src.isFile()) { //大小
len+=src.length();
}else { //子孙级
for(File s:src.listFiles()) {
count(s);
}
}
}
}
}
- 字符编码
Java字符使用16位的双字节存储。
字符集 | 说明 |
US-ASCII | ASCII编码 |
ISO-8859-1 | Latin-1 拉丁字符,包含中文,日文等 |
UTF-8 | 变长Unicode字符(1-3字节),英文字符占1个字节,中文字符占3个字节。 |
UTF-16BE | 定长Unicode字符(2字节),Gig-Ending编码:高字节低地址 |
UTF-16LE | 定长Unicode字符(2字节),Little-Ending编码:低字节低地址 |
UTF_16 | 文件的开头指明BE/LE编码方式,即BOM(Byte Order Mark):“FE FF”表示BE编码,“FF FE”表示LE编码 |
这里ANSI指系统默认的字符集——windows中文环境下默认字符集是GBK。
- 字符编码
String english = "abc";
String chinese = "将进酒";
byte[] data1 = english.getBytes();
System.out.println("英文\"" + english + "\"的长度:" + data1.length);
byte[] data2 = english.getBytes("GBK");
System.out.println("英文\"" + english + "\"的长度:" + data2.length);
byte[] data3 = chinese.getBytes(); // 默认getBytes("UTF8"),工程字符集,字符集名称大小写均可
System.out.println("中文\"" + chinese + "\"的长度:" + data3.length);
byte[] data4 = chinese.getBytes("GBK");
System.out.println("中文\"" + chinese + "\"的长度:" + data4.length);
- 字符解码
String–>byte[]:编码
byte[] -->String:解码
String str1 = "米国USA";
byte[] data = str1.getBytes();
String str2 = new String(data, 0, data.length, "gbk");
System.out.println(str2);
String str3 = new String(data, "utf8");
System.out.println(str3);
- 乱码的原因
- 字节数不够
- 编码字符集不匹配
- 中文字符集
cp936<gb2312<bgk
- IO流
- 字节流
InputStream/OutputStream - 字符流
Reader/Writer - 读操作步骤(概念)
//1、创建源
File src = new File("abc.txt");
//2、选择流
try {
InputStream is =new FileInputStream(src);
//3、操作 (读取)
int data1 = is.read(); //第一个数据s
int data2 = is.read(); //第二个数据x
int data3 = is.read(); //第三个数据t
int data4 = is.read(); //????不是数据,文件的末尾返回-1
System.out.println((char)data1);
System.out.println((char)data2);
System.out.println((char)data3);
System.out.println(data4);
//4、释放资源
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
- 操作步骤
字节读
//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (读取)
int temp ;
while((temp=is.read())!=-1) { //一个字节一个字节地读
System.out.println((char)temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
块读
//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (分段读取)
byte[] flush = new byte[1024*10]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
//字节数组-->字符串 (解码)
String str = new String(flush,0,len); //String str = new String(flush, "utf8");
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 写操作
//1、创建源
File dest = new File("dest.txt");
//2、选择流
OutputStream os =null;
try {
os = new FileOutputStream(dest,true); //true表示追加写入
//3、操作(写出)
String msg ="IO is so easy\r\n";
byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码,默认字符集)
//byte[] datas = msg.getBytes("utf8"); 按照utf8字符集编码
os.write(datas,0,datas.length); //或者out.write(datas);
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
- 释放资源
先打开的后关闭,后打开的先关闭。
可以利用Closeable接口封装释放资源的动作。
public static void close(Closeable... ios) {
for(Closeable io:ios) {
try {
if(null!=io) {
io.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
或者可以利用try …with…resources自动资源释放(JDK7之后)
try(is;os) { //<----------is和os自动释放
或者
try( InputStream is=new FileInputStream(src);
OutputStream os=new FileOutputStream(dest);){
......
......
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
- 纯文本处理
FileReader/FileWriter(内置解决字符编解码问题)
append()返回Writer,故可以实现链式引用。
块读
//1、创建源
File src = new File("abc.txt");
//2、选择流
Reader reader =null;
try {
reader =new FileReader(src);
//3、操作 (分段读取)
char[] flush = new char[1024]; //缓冲容器,注意是字符数组不是字节数组
int len = -1; //接收长度
while((len=reader.read(flush))!=-1) {
//字符数组-->字符串,解码无需指定字符集(系统已经处理好了)
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
块写
//1、创建源
File dest = new File("dest.txt");
//2、选择流
Writer writer =null;
try {
writer = new FileWriter(dest);
//3、操作(写出)
//写法一
//String msg ="I love you baby\r\n你知道我在等你吗";
//char[] datas =msg.toCharArray(); // 字符串-->字符数组(不存在编码问题)
//writer.write(datas,0,datas.length);
写法二
String msg ="I love you baby\r\n你知道我在等你吗";
writer.write(msg);
writer.write("add");
writer.flush();
//写法三
//writer.append("I love you baby\r\n").append("你知道我在等你吗");
//writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
- 字节数组流
ByteArrayInputStream&ByteArrayOutputStream,在内存中,Java可以直接访问,无需关闭。 - 处理流
使用了装饰模式。 - 装饰器类包裹/包装基本类。接口方法(产生多态行为)从装饰器类向基本类方向层层调用,然后由内层的基本类向外部的包装类层层返回。抽象类实现接口,但主要是要提供公共属性。
- 流的缓冲
- 提供缓冲的装饰流类可以提高IO性能。
- 控制流的基础是节点流,底层不能没有节点流。
- 释放外层装饰器流类的对象,则内层的基本流类对象资源会自动释放。释放是从里到外依次释放。
这里节点流是基本IO流类,而控制流是装饰器IO流类。装饰器IO流类提供流的缓冲提升IO效能。控制流类包装节点流类——装饰器类包装基本类。
示例如下:
File src = new File("abc.txt");
...
is=new BufferedInputStream(new FileInputStream(src));
装饰器类 基本类
控制流类 节点流类
提升IO效能
后释放(手动) 先释放(自动)
-------------------------------------------------------------------
File dest = new File("dest.txt");
...
os =new BufferedOutputStream( new FileOutputStream(dest));
- 字符输入输出加入缓冲流
- 读入
//1、创建源
File src = new File("abc.txt");
//2、选择流
BufferedReader reader =null;
try {
reader =new BufferedReader(new FileReader(src));
//3、操作 (分段读取)
String line =null;
while((line=reader.readLine())!=null) {
//字符数组-->字符串
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 写出
//1、创建源
File dest = new File("dest.txt");
//2、选择流
BufferedWriter writer =null;
try {
writer = new BufferedWriter(new FileWriter(dest));
//3、操作(写出)
writer.append("I love you baby");
writer.newLine(); //输出一个\r\n
writer.append("偏偏喜欢你");
writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
- 转换流
CharactorStreams—>InputStreamReader/OutputStreamWriter—>ByteStreams
InputStreamReader/OutputStreamWriter能将字节流转换为字符流,并且能为字节流指定字符集。
InputStreamReader对应解码;OutputStreamWriter对应编码。
- 将字节流转换成字符流
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
//循环获取键盘的输入(exit退出),输出此内容
String msg ="";
while(!msg.equals("exit")) {
msg = reader.readLine(); //循环读取
writer.write(msg); //循环写出
writer.newLine();
writer.flush(); //强制刷新。不强制刷新,在缓存未满时不输出,卡在上一步。
}
}catch(IOException e) {
System.out.println("操作异常");
}
- 处理指定字符集
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
public class ConvertTest {
public static void main(String[] args) {
try(BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new URL("http://www.baidu.com").openStream(),"UTF-8"));
BufferedWriter writer =
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("baidu.html"),"UTF-8"));){
//3、操作 (读取)
String msg ;
while((msg=reader.readLine())!=null) {
//System.out.println(msg);
writer.write(msg); //如果字符集不统一将出现乱码
writer.newLine();
}
writer.flush();
}catch(IOException e) {
System.out.println("操作异常");
}
}
}
- 数据流
DataInputStream/DataOutputStream保存了数据及其类型。
//写出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作数据类型 + 数据
dos.writeUTF("白日依山尽");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//读取
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dis.readUTF();
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);